三次Hermite样条曲线表现异常

7
我正在尝试使用三次Hermite样条绘制图形。我从插值方法页面中获取了相应的简单代码。
这是我的代码:
private float HermiteInterpolate(float y0, float y1, float y2, float y3, float mu)
{
    var mu2 = mu * mu;

    var a0 = -0.5f * y0 + 1.5f * y1 - 1.5f * y2 + 0.5f * y3;
    var a1 = y0 - 2.5f * y1 + 2f * y2 - 0.5f * y3;
    var a2 = -0.5f * y0 + 0.5f * y2;
    var a3 = y1;

    return (a0 * mu * mu2) + (a1 * mu2) + (a2 * mu) + a3;
}

使用这些数据(y值从0到1,x值均匀分布在0到21之间):

0、0.09448819、0.1102362、0.1338583、0.1811024、0.2283465、0.3543307、0.4645669、0.480315、0.480315、0.527559、0.527559、0.527559、0.527559、0.527559、0.527559、0.6062992、0.6377953、0.6377953、0.6377953、0.7480315

这是结果:

Hermite Graph

问题在于,图表的某些区域,线条会向下。查看数据,它从未减少。我不知道算法是否应该这样做,但对于我正在处理的内容,我希望线条永远不要向下(如果我手绘图表,我也不会让它们指向下方)。
所以,
  • 图表有什么问题吗?
  • 算法是否应该这样做?如果是,有没有这种情况不会发生的算法?
  • 我尝试了余弦插值,但不喜欢结果。
这是实际的图表函数:
public void DrawGraph(IList<float> items)
{
    for (var x = 0; x < Width; x++)
    {
        var percentThrough = (float)x / (float)Width;
        var itemIndexRaw = items.Count * percentThrough;
        var itemIndex = (int)Math.Floor(itemIndexRaw);

        var item = items[itemIndex];
        var previousItem = (itemIndex - 1) < 0 ? item : items[itemIndex - 1];
        var nextItem = (itemIndex + 1) >= items.Count ? item : items[itemIndex + 1];
        var nextNextItem = (itemIndex + 2) >= items.Count ? nextItem : items[itemIndex + 2];

        var itemMu = FractionalPart(itemIndexRaw);

        var pointValue = HermiteInterpolate(previousItem, item, nextItem, nextNextItem, itemMu);

        WritePixel(x, (int)(pointValue * Height) - 1, (1 - FractionalPart(pointValue)), false);
        WritePixel(x, (int)(pointValue * Height), 1.0f, false);
        WritePixel(x, (int)(pointValue * Height) + 1, FractionalPart(pointValue), false);
    }
}

嗨Snea,我正在尝试理解Cubic Hermite Spline的工作原理。你能告诉我你的HermiteInterpolate方法是如何调用的吗? - Doro
1个回答

10

这种行为是正常的。

插值方法会施加一些连续性条件,以呈现平滑曲线的外观。对于Hermite插值,没有要求通过一系列递增值的插值曲线也必须在任何地方都是递增的条件,因此有时你会得到你展示的效果。

有一种被称为单调立方插值的方法可以做到您想要的:如果数据点是递增的,则插值曲线在任何地方都将递增。


1
太好了!现在我只需要想办法将所有这些步骤解释为代码。 - Snea

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