我有一个很好的三次样条代码,但它仅用于插值。我需要extrapolate进入未来。这样做有没有人知道一个很好的代码来源,而不是一个库?
This is the code我在基本(现在的ASM)中写了插值。
答案 0 :(得分:6)
您不需要新的代码。
要推断样条曲线,您可以推断第一个和最后一个样条曲线的参数。
取决于您现有的代码/库,如果不修改代码,可能无法实现。在这种情况下,只需将两个其他点添加/添加到点列表的开头/结尾。您可以通过在第一个/最后两个点之间进行线性插值来获得这两个点。
小心:根据点的原始含义,外推可能完全不合适,特别是在统计数据方面。在这种情况下,您应该考虑使用regression analysis。
答案 1 :(得分: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 切断Bezier曲线 左半部分和右半部分。 即使在没有“乘法”指令的微控制器上,这也非常简单, 因为它只需要计算一些平均值才能得到一个中点:
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 :(得分:2)
你真的必须稍微扩展这个问题。此外,“三次样条”是一个非常宽泛的术语。
如果您对样条线感兴趣,我可以衷心地推荐Carl de Boors“Splines实用指南”。然而,它有点数学导向,但它包含代码示例(可以从作者的主页下载)。谷歌搜索和维基“三维样条”可以提出一些例子,甚至可能在特定的语言中 - 另一个问题是添加到问题中(如果你正在寻找代码)。
如果您对外推和曲线拟合感兴趣,谷歌搜索可能会有所帮助。 Matlab包有一个非常漂亮的曲线拟合工具箱。维基百科有一些指向有用参考的链接
真的,这个问题太宽泛了,甚至开始猜测答案。
另外,你能解释一下你到底想要做什么吗?什么样的数据?什么?
Edit1:在这里,试试这个:你可以在这里找到一些有用的东西 - link
答案 3 :(得分:1)
通常,对于样条插值,您可以使用变量t对线进行插值。只要0 <= t <= 1,就进行插值。但是,当t < 0或t> 1你只是简单地推断样条曲线。
答案 4 :(得分:0)
您需要为请求的代码编写更好的要求。样条通常用于通过使用某些固定数据集来插入某些未知或复杂函数。如果要在此数据集的边界之外估计函数的值,则不应使用样条曲线。
如果您的样条函数在您真正想要评估值的位置定义(立方体,而不是分段立方体),那么您已经可以评估该值。
如果您希望能够在插值范围之外评估样条曲线,但将其保留为在插值范围内具有相同值的分段三次函数,则应该通过某些节点扩展样条曲线范围,并添加一些评估逻辑新节点处的值(例如,您希望样条不仅是连续函数,而且还有一些一阶导数也是连续函数)
我真的建议你使用一些更适合外推的算法,比如使用Lagrange polynomial,如果你真正需要的是单个值,距离原始数据集的点不是很远。