点序列插值

10

给定空间中任意一组点序列,如何在它们之间生成平滑连续的插值?

欢迎提供2D和3D解决方案。既能产生任意粒度点列表的解决方案,也能产生贝塞尔曲线的控制点的解决方案。

此外,如果能够看到一种迭代解决方案,该解决方案可以在接收到点时近似前几个曲线段,以便您可以使用它进行绘制,则非常酷。

9个回答

9

Catmull-Rom样条能够通过所有控制点,相较于调整其他类型的样条的中间控制点,我发现这更方便。

Christopher Twigg的PDF文档对于样条的数学知识有一个简明的介绍。最好的总结语句是:

Catmull-Rom样条具有C1连续性、局部控制和插值特性,但不在其控制点的凸包内。

换句话说,如果点指示向右急转弯,则样条将在向右转弯之前向左倾斜(该文档中有一个示例图片)。这些转弯的紧密程度可通过该示例矩阵中的tau参数进行控制。

这里是另一个示例,其中包含一些可下载的DirectX代码。


这是一个赞同的投票。几年前我在一个视频游戏中使用了Catmull方法,效果非常好。 - Jim Buck
这正是Catmull-Rom所设计的(特别地,是为了使动态样条经过控制点)。 - Jared Updike

3

一种方法是使用拉格朗日插值多项式,这是一种产生通过所有给定数据点的多项式的方法。

在我大学的第一年,我写了一个小工具来处理二维数据,你可以在这个页面找到它,它叫做Lagrange solver。维基百科的页面上也有一个示例实现。

它的工作原理如下:你有一个n阶多项式p(x),其中n是你拥有的数据点的数量。它的形式为a_n x^n + a_(n-1) x^(n-1) + ...+ a_0,其中_是下标,^是幂次。然后将其转换为一组同时方程:

p(x_1) = y_1
p(x_2) = y_2
...
p(x_n) = y_n

您需要将上述内容转换为增广矩阵,并解出系数a_0 ... a_n。然后您将得到一个通过所有点的多项式,现在您可以在点之间进行插值。请注意,这可能不适合您的目的,因为它没有提供调整曲率等的方法 - 您将被困在一个不能更改的单一解决方案中。

2
你应该看一下B样条曲线。它们相对于Bezier曲线的优势在于每个部分仅依赖于局部点。因此,移动一个点不会影响远离该点的曲线部分,其中“远离”由样条的一个参数确定。
拉格朗日多项式的问题在于添加一个点可能会对曲线的看似任意的部分产生极端影响;没有像上面描述的“局部性”。

1

1

你看过Unix的spline命令吗?它能被强制转换成你想要的功能吗?


那是一个有趣的地方寻找解决方案!谢谢。我会去看看的。 - Nick Retallack

1

不幸的是,拉格朗日或其他形式的多项式插值不能在任意点集上工作。它们只适用于一维情况下的点集,例如 x

xi < xi+1

对于任意点集,例如飞机的飞行路径,其中每个点都是(经度,纬度)对,您最好只需使用当前经度和纬度以及速度来模拟飞机的旅程。通过根据飞机距离下一个航路点的距离调整其转弯速率(角速度),您可以实现平滑曲线。

生成的曲线在数学上并不重要,也不会给您贝塞尔控制点。但是,无论航路点数量如何,该算法都非常简单,并且可以产生任意粒度的插值点列表。它也不需要您提前提供完整的点集,您只需根据需要向点集末尾添加航路点即可。


1

有几种算法可以在任意(但最终)一组点之间进行插值(和外推)。你应该查看数值计算方法,它们还包括这些算法的C++实现。


0

搜索“正交回归”。

最小二乘法试图将拟合线与每个f(x)之间的垂直距离最小化,而正交回归则最小化垂直距离。

补充说明

在存在噪声数据的情况下,值得考虑古老而可敬的RANSAC算法。


0
在 3D 图形世界中,NURBS 是很受欢迎的。更多信息可以轻松地通过谷歌搜索获得。

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