三次样条外推

7
5个回答

6

您不需要新的代码。

要推断样条曲线,您可以外推第一个和最后一个样条曲线的参数。

根据您现有的代码/库,如果不修改代码可能无法实现。在这种情况下,只需在点列表的开头/结尾添加两个其他点即可。您可以通过在线性插值第一个/最后两个点之间来获取这两个点。

请注意: 根据原始点的含义,该外推可能完全不适合,特别是涉及统计数据时。在这种情况下,您应考虑使用回归分析


你可以通过在线性插值第一个/最后两个点之间来获得这两个点。 这样做会失去这个练习的意义。我想要基于样条曲线生成的结果进行扩展。 - Mike Trader
正如我所说,如果你现有的代码/库不允许你外推(即使用参数<0或>1),那么这将是次优的后备方案。 - Daniel Rikowski

3
为了简化,我将一个三次贝塞尔曲线表示为4个点(A、B、C、D),其中A和D是曲线的端点,B和C是"控制手柄点"。(实际曲线通常不会触及控制手柄点)。
请参见"Don Lancaster's Guru's Lair Cubic Spline Library",了解将此表示法转换为其他常见表示法的方法。
插值
给定一个三次贝塞尔曲线(P0、P1、P2、P3),我们使用De Casteljau's algorithm将贝塞尔曲线分成左半部分和右半部分。即使在没有"乘法"指令的微控制器上,这也非常容易,因为它只需要计算一些平均值,直到我们得到一个中点。
P0
   F0 := average(P0, P1)
P1                       S0 := average(F0, F1)
   F1 := average(P1, P2)         Midpoint := average(S0, S1)
P2                       S1 := average(F1, F2)
   F2 := average(P2, P3)
P3

整个贝塞尔曲线是 (P0, P1, P2, P3)。
该整个贝塞尔曲线的左半部分是贝塞尔曲线 (P0, F0, S0, M)。
该整个贝塞尔曲线的右半部分是贝塞尔曲线 (M, S1, F2, P3)。
许多微控制器继续将每个曲线划分为越来越小的小曲线,直到每个片段足够小,可以用一条直线近似。
但我们想要反过来,推断出一个更大的曲线。
外推法
给定左半部分或右半部分,我们可以反向运行它以恢复原始曲线。
假设我们忘记了原始点 P1、P2 和 P3。
给定贝塞尔曲线 (P0, F0, S0, M) 的左半部分,我们可以用外推法推断出右半部分。
S1 := M + (M - S0)
F1 := S0 + (S0 - F0)
P1 := F0 + (F0 - P0)

然后使用这些值进行计算。
F2 := S1 + (S1 - F1)
P2 := F1 + (F1 - P1)

最后

P3 := F2 + (F2 - P2)

对于外推和恢复外推的Bazier曲线(P0,P1,P2,P3)。

细节

外推曲线(P0,P1,P2,P3) 通过原始曲线中的每个点 (P0,F0,S0,M)-- 特别是从P0开始,通过中点M -- 并一直保持到达P3。

我们总是可以从任何4个点(P0,F0,S0,M)进行外推, 无论这些4个点是否最初计算为某个更大的Bezier样条的左半部分(或右半部分)。

我确定您已经知道了,但只是为了清晰起见:

Midpoint = average(F0, F1)

意思是“在点F0和F1之间精确地找到正中间点”,换句话说,

Midpoint.x = (F0.x + F1.x)/2
Midpoint.y = (F0.y + F1.y)/2
Midpoint.z = (F0.z + F1.z)/2

表达式

S1 := M + (M - S0)

意思是“给定一条线段,其中一个端点为S0,中点为M,在S0处开始并沿着直线穿过M直到你到达另一个端点S1”,或者说(除非你有一个不错的向量库)需要3行代码。

S1.x := M.x + (M.x - S0.x)
S1.y := M.y + (M.y - S0.y)
S1.z := M.z + (M.z - S0.z)

如果你正在进行2D制作,跳过所有的“z”相关内容——它总是为零。

2
您需要稍微展开您的问题,另外,“三次样条插值”是一个非常广泛的术语。
如果您对样条感兴趣,我可以强烈推荐Carl de Boors的“样条实用指南”。然而,它有点数学取向,但其中包括了代码示例(可以从作者的主页下载)。在Google和Wiki中搜索“三次样条插值”可能会找到一些示例,甚至可能用特定的语言 - 这是应该添加到问题中的另一件事情(如果您正在寻找代码)。
如果您对外推和曲线拟合感兴趣,则可以通过Google搜索来帮助。Matlab包具有非常好的曲线拟合工具箱。维基百科提供了一些有用参考链接。
真的是一个太宽泛的问题,无法开始猜测答案。
此外,您能解释一下您试图做什么吗?什么类型的数据?任何东西?
P.S.:这里有一个链接,您可能会在其中找到一些有用的信息 - link

MATLAB是一个库,我正在寻找如下所述的代码。 我有一系列数据点产生的曲线。我需要向前延伸一点曲线。它并不比此更复杂。 - Mike Trader
好的,只需拿出你最后得到的三次曲线并计算所需的值即可。如果你已经通过了拟合,那么你已经得到了系数。 - Rook
这段代码是很多年前写的,当时我轻松就能处理这个水平的数学问题。现在我得把整段代码都拆开来,重新掌握相关概念才行... 非常不容易。我希望这篇文章会促使有人提供一些代码链接... - Mike Trader
但是你必须了解使用的算法和你编写的代码。毕竟,如果你一开始就编写了样条曲线,这是微不足道的。我无法为你提供关于代码的任何帮助,因为我不知道你做了什么。正如我在帖子中所说,“三次样条”并不是一个确切的描述。 - Rook

1
通常,对于样条插值,您使用变量t在线上进行插值。只要0 <= t <= 1,您就可以进行插值。但是,当t < 0或t > 1时,您只是在外推样条。

是的,这是正确的。在这个例子中,我需要 t > 1 的数据点(但只是稍微大于 t)。 - Mike Trader
1
只需使用 t > 1 的样条公式进行计算,对于较小的 t,您应该没问题。 - Jasper Bekkers

1

您需要编写更好的代码需求。样条通常用于通过某些固定数据集对某些未知或复杂函数进行插值。如果您想要在此数据集范围之外估算函数值,那么就不应该使用样条。

如果您的样条是在您真正想要评估值的位置定义的函数(三次函数,但不是分段三次函数),那么您已经可以评估该值了。

如果您想要能够在插值范围之外评估您的样条,但仍将其保留为具有插值范围内相同值的分段三次函数,则应通过一些节点扩展样条范围,并添加一些逻辑以在新节点处评估值(例如,您希望您的样条不仅是连续函数,而且还具有一些连续函数的一阶导数)

实际上,我建议您使用更适合外推的算法,例如使用Lagrange polynomial,如果您真正需要的只是距离原始数据点不远的单个值。


你不应该使用样条曲线。为什么呢?因为三阶多项式已经被计算出来了。我只需要使用“曲率”并稍微向前延伸即可。我会学习拉格朗日多项式。 - Mike Trader

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