C#中的三次样条平滑插值/曲线插值

14

下面是一个三次插值函数:

public float Smooth(float start, float end, float amount)
{
    // Clamp to 0-1;
    amount = (amount > 1f) ? 1f : amount;
    amount = (amount < 0f) ? 0f : amount;

    // Cubicly adjust the amount value.
    amount = (amount * amount) * (3f - (2f * amount));

    return (start + ((end - start) * amount));
}

这个函数将在0.0f-1.0f之间的数值上进行立方插值,以在起始值和结束值之间获得中间值。如果您绘制此曲线,您会得到类似于以下内容:

已过期的Imageshack图像已被删除

这里使用的是立方函数:

    amount = (amount * amount) * (3f - (2f * amount));

我该如何修改这个函数以产生两个进出切线?

要产生像这样的曲线:(从线性开始到立方结束)

过期的Imageshack图像已移除

一个函数可以产生下面这样的曲线:

另一个函数可以产生像这样的曲线:(从立方开始到线性结束)

过期的Imageshack图像已移除

有人有什么想法吗?谢谢。


2
投票关闭此问题,因为它依赖于图像来展示问题是什么,而这些图像显然已经不存在了。因此,就我个人而言,这个问题本身没有价值,答案也没有价值,因为没有人知道这些答案回答的是什么问题。 - Lasse V. Karlsen
3个回答

12

1
感谢罗伯特,使它看起来漂亮多了 :) - Donnie DeBoer
1
是的。这是完成此操作的方法。分段三次Hermite插值具有良好的性质,即它在断点处保证连续和可导,因为给定了每个区间端点的值和一阶导数。在我看来,这是一种非常漂亮的构建分段三次函数的方式。 - user85109

3
你可以进行线性插值和三次插值,并在两个插值函数之间进行插值。
例如:
cubic(t) = cubic interpolation
linear(t) = linear interpolation
cubic_to_linear(t) = linear(t)*t + cubic(t)*(1-t)
linear_to_cubic(t) = cubic(t)*t + linear(t)*(1-t)

t的取值范围为0到1


我会尝试让您的解决方案运行起来。不过,理想情况下,我宁愿在方法中调整立方函数:amount = (amount * amount) * (3f - (2f * amount));我认为这可以相对容易地完成,只是我不确定如何做到。 - Rob
1
如果你想要有切线,请使用我下面发布的三次Hermite样条。 - Donnie DeBoer

0

嗯,一个简单的方法是这样的:

-Expand your function by 2 x and y
-Move 1 to the left and 1 down
Example: f(x) = -2x³+3x²
g(x) = 2 * [-2((x-1)/2)³+3((x-1)/2)²] - 1

或者以编程方式(立方体调整):

double amountsub1div2 = (amount + 1) / 2;
amount = -4 * amountsub1div2 * amountsub1div2 * amountsub1div2 + 6 * amountsub1div2 * amountsub1div2 - 1;

对于另一个,只需省略“moving”即可:

g(x) = 2 * [-2(x/2)³+3(x/2)²]

或者以编程方式(立方体调整):

double amountdiv2 = amount / 2;
amount = -4 * amountdiv2 * amountdiv2 * amountdiv2 + 6 * amountdiv2 * amountdiv2;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接