【发布时间】:2010-10-27 05:43:57
【问题描述】:
我有一个很好的三次样条代码,但它仅用于插值。我需要extrapolate 一点点未来。有谁知道这样做的好代码源,而不是库?
This is the code我用basic(现在的ASM)写的插值。
【问题讨论】:
标签: plot interpolation spline graphing extrapolation
我有一个很好的三次样条代码,但它仅用于插值。我需要extrapolate 一点点未来。有谁知道这样做的好代码源,而不是库?
This is the code我用basic(现在的ASM)写的插值。
【问题讨论】:
标签: plot interpolation spline graphing extrapolation
为简单起见,我将表示三次贝塞尔曲线 作为 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 个点 作为一些较大的贝塞尔样条曲线的左半部分(或右半部分)。
我确定您已经知道这一点,但只是为了清楚起见:
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”的东西——它总是为零)。
【讨论】:
你真的需要稍微扩展一下这个问题。此外,“三次样条”是一个非常广泛的术语。
如果您对样条线感兴趣,我可以衷心推荐 Carl de Boors 的“样条线实用指南”。然而,它有点数学导向,但它包含代码示例(可以从作者的主页下载)。谷歌搜索和维基搜索“三次样条”可以提出一些示例,甚至可能是特定语言的示例 - 另一件事要添加到问题中(如果您正在寻找代码)。
如果您对外推和曲线拟合感兴趣,可以在 Google 上搜索这些内容可能会有所帮助。 Matlab 包有一个非常好的曲线拟合工具箱。维基百科有一些有用参考的链接
真的,这个问题太宽泛了,甚至无法开始猜测答案。
另外,你能解释一下你到底想做什么吗?什么样的数据?有什么事吗?
Edit1:在这里,试试这个:你可能会在这里找到有用的东西 - link
【讨论】:
您不需要为此添加新代码。
要外推样条,您可以外推第一个和最后一个样条的参数。
取决于您现有的代码/库,如果不修改代码可能无法实现。在这种情况下,只需将 另外两个点添加到点列表的开头/结尾即可。您可以通过在第一个/最后两个点之间进行线性插值来获得这两个点。
小心:根据点的原始含义,外推可能完全不合适,尤其是在涉及统计数据时。在这种情况下,您应该考虑使用regression analysis。
【讨论】:
您需要为请求的代码编写更好的需求。样条通常用于通过使用一些固定数据集对一些未知或复杂函数进行插值。如果你想在这个数据集的边界之外估计函数的值,那么你不应该使用样条线。
如果您的样条是在您真正想要评估值(三次,但不是分段三次)的地方定义的函数,那么您已经可以评估该值。
如果您希望能够在插值范围之外评估样条曲线,但在插值范围内将其保留为具有相同值的分段三次函数,那么您应该通过一些节点扩展样条曲线范围,并添加一些评估逻辑新节点处的值(例如,您希望样条曲线不仅是连续函数,而且还有一些一阶导数也是连续函数)
真的我建议你使用一些更适合外推的算法,比如使用Lagrange polynomial,如果你真正需要的都是离原始数据集点不远的单个值。
【讨论】:
通常,对于样条插值,您使用变量 t 在线上进行插值。只要 0 1 时,您只是在外推样条曲线。
【讨论】: