计算三次B样条的长度

7 投票
2 回答
9546 浏览
提问于 2025-04-15 18:46

我在使用scipy的interpolate.splprep函数来获取一个参数样条曲线,这个曲线是基于参数u的。不过,u的范围并不是样条曲线的线积分,而是输入坐标之间的分段线性连接。我试过integrate.splint,但它只给出了u上的各个积分。显然,我可以通过数值方法计算一堆笛卡尔坐标的微分距离,但我在想,是否有一种封闭形式的方法可以直接得到样条曲线或样条段的长度(使用scipy或numpy),而我可能忽略了。

补充说明:我在寻找一种封闭形式的解决方案,或者一种非常快速的方法来得到机器精度的答案。我几乎放弃了数值根查找的方法,现在主要想要一个封闭形式的答案。如果有人有经验处理椭圆函数的积分,或者能推荐一个好的资源(除了Wolfram),那就太好了。

我打算尝试Maxima,看看能否得到我认为是样条曲线一个段的函数的不定积分:我在MathOverflow上也发了这个问题。

2 个回答

4

你可以对这个函数 sqrt(x'(u)**2+y'(u)**2) 进行积分,里面的 u 是一个变量。在这个函数中,x'y' 是你坐标的导数,你可以用 scipy.interpolate.splev 来计算它们。积分可以使用 scipy.integrate 中的某个方法来完成,比如 quad 方法比较精确(使用的是 Clenshaw-Curtis 方法),而 romberg 方法通常会更快。这样做应该比把很多小距离加起来更精确,也可能更快(因为把小距离加起来相当于用矩形法进行积分)。

7

因为 x 和 y 都是三次参数函数,所以没有简单的公式可以直接算出结果。我们需要用数值积分的方法来解决这个问题。可以选择积分弧长的表达式,或者直接把线段的长度加起来,这取决于你想要的准确度和你愿意付出的努力。

一种准确且快速的“加线段长度”方法:

使用递归细分(这是一种 de Casteljeau 算法的形式)来生成点,可以用很少的点得到非常准确的表示。只有在细分的部分不符合某个标准时,才进行进一步的细分。通常这个标准是基于连接控制点的长度(也叫外壳或笼子)。

对于三次曲线,通常是比较 P0P1 + P1P2 + P2P3 的长度与 P0P3 的长度,P0、P1、P2 和 P3 是定义你贝塞尔曲线的控制点。

你可以在这里找到一些 Delphi 代码:链接文本

把这些代码转换成 Python 应该相对简单。它会生成点,并且代码已经计算了线段的长度,以便测试标准。你可以在这个过程中简单地累加这些长度值。

撰写回答