贝塞尔样条评估正确性

Bezier spline evaluation correctness

在任意点评估样条曲线的best/most正确方法是什么?

我绘制了我的评估结果,并将它们与我使用 UI 库获得的结果进行了比较,发现我的结果是错误的。

我对中心段使用三次公式,对曲线的第一段和最后一段使用二次公式。

我认为我遇到这个问题的原因是因为在它的评估中 X 坐标发生变化(移动)并且我目前正在以恒定的步进坐标评估它,这导致输入 x 和输出之间存在一些差异一个(我目前忽略了)

如果需要我可以提供代码。 (我使用 Qt 作为检查正确性的方法以防它有帮助)

原来是数学和编程的结合。

从那以后,我扩展了我对正在实施的特定曲线类型的知识,现在我可以更好地解释我试图实现的目标以及我的问题所在。对于可能造成的任何混淆,我们深表歉意。

我正在实现一个 FCurve 并且需要能够 "evaluate" 它在任意输入值。 FCurves 是表示函数的样条曲线(即对于任何给定的输入,它们 return 一个唯一的输出)

在评估我的旧样条实现时,我得到了不正确的评估结果,因为我的评估代码没有考虑曲线弧长,除了 FCurves 稍微更严格这一事实。

我目前使用的获取精确评估值的方法是用不同的"t"填充一组"segment samples",然后遍历它以找到最接近的匹配项并在它们之间进行线性插值。稍后我会回到它并尝试找到一种聪明的方法来获取真正需要多少样本来以最小的错误评估该段,但目前效果非常好。

所有这一切之所以发生,是因为在应用上述公式(三次贝塞尔曲线)时,从输入 "x" 和 "t".[=14 中得到不同的 "x" 值是很常见的=]

这是我在评估它时得到的部分代码:

    const uint32_t sampleCount = 20;
    Vec2 samples[sampleCount];
    fillSegmentSamples(x, &samples[0], sampleCount);

    uint32_t best = 0;
    for(uint32_t i = 0; i < sampleCount; i++)
    {
        if(samples[i].x > x)
            break;

        best = i;
    }

    uint32_t nxt = best + 1;
    if(nxt >= sampleCount)
    {
        best--;
        nxt--;
    }

    float t = (x - samples[best].x) / (samples[nxt].x - samples[best].x);

    y = lerp(samples[best].y, samples[nxt].y, t);

之前,我是 运行 等同于以下内容,这是错误的,因为它没有对 x 轴移动进行任何补偿。 (请注意,在这种情况下,"t" 是从 "x" 中提取的)

Vec2 samples[1];
fillSegmentSamples(x, &samples[0], 1);
y = samples[0].y;

以下两个 questions/answers 帮助我了解出了什么问题:

他们并没有特别关注 fcurves,但是弧长给了我解决这个问题的提示。

干杯!