在一定距离后如何获取Catmull-Rom样条的焦点?

5
如果我有一个长度为Catmull-Rom spline的曲线,如何计算它在某个距离处的位置?通常,要计算catmull rom曲线上的点,您需要输入0到1之间的值以通过比例获得其位置,那么如何计算距离呢?例如,如果我的曲线长度为30个单位,如何在距离8处获取其位置?
我之所以问这个问题,是因为似乎对于catmull rom曲线,在[0,1]范围内给出的点并不能保证它将给出该距离到曲线的点。例如,如果我将0.5输入到长度为30的catmull rom曲线中,除非该曲线本身是一条直线,否则不能保证我会得到距离曲线15个单位的位置。
3个回答

4
通常的方法是存储每个段的长度,然后通过增加一个epsilon值来计算两点之间的线性距离,直到找到部分段的长度。显然,epsilon值越小,结果越好,但它给出了出人意料的好结果。我用这种方法在catmul-rom上以恒定速度移动,你看不到它加速和减速...它确实以恒定速度移动。显然,根据你的段有多紧密,你的epsilon值需要改变,但通常情况下,你可以选择一个“足够好”的epsilon值,一切都会很好。

非迭代地找到答案是非常昂贵的(我曾经看过推导,那不是很漂亮;))。你将不得不使用一个很小的epsilon值来获得更差的性能...


3

另一个链接:Anti-Grain Geometry库中的自适应Bezier曲线细分主要涉及在像素网格上使用宽画笔绘制Bezier曲线的不同问题,但请查看末尾。
(添加:)Antigrain还有一个可爱的examples/bspline.cpp示例,您可以移动节点并改变中间点的数量。


我最近才听说AGG库,但我对它印象非常深刻。 - tfinniga

1
Goz的答案很准确-这是一个关于Bezier曲线长度的讨论related discussion about length of Bezier curves。帖子总结了,使用近似值比计算精确值更少计算量(并且更简单)。可应用此方法,因为您可以更改参数样条的基础,所以您可以将Catmull-Rom曲线转换为Bezier曲线段。
对于近似值,基本上将其分解为具有简单分析长度的原语,然后求所有简单长度的和。虽然大多数人使用线段,但您确实会有收缩。您可以通过使用小线段来最小化误差,但对于非线性曲线,您的近似值始终小于真实长度。
如果您需要更高的精度,则可以从jgt的paper from jgt中了解如何使用圆形作为近似原语,这似乎更快/更准确,但实现起来并不困难。他们包括一个示例C实现。

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