返回贝塞尔曲线上等弧长点列表的函数

5

某个地方一定有人解决过这个问题。我可以找到许多很棒的网站来解释这个问题以及如何解决它。虽然我相信它们写得很好并且数学天才能够理解,但那并不包括我。虽然我可能会以一种模糊的方式理解,但我不知道如何将这些数学转化为我可以使用的函数。

所以我请求您,如果您有任何语言的函数可以解决这个问题(甚至是FORTRAN或6502汇编语言),请帮助我。

  • 更喜欢解析解而不是迭代解

编辑:我想指定我正在处理的是三次贝塞尔曲线。

1个回答

3
您所要求的是弧长函数的反函数。因此,给定曲线B,您需要一个函数Linv(len),它返回介于0和1之间的t值,使得曲线在0到t之间的弧长为len。
如果您有了这个函数,那么问题就很容易解决了。让B(0)成为第一个点。要找到下一个点,只需计算B(Linv(w)),其中w是您所提到的“等弧长”。要获取下一个点,只需评估B(Linv(2*w))等,直到Linv(n*w)大于1为止。
我最近也遇到了这个问题。我想出了一些解决方案,或者说发现了一些解决方案,但对我来说都不太令人满意(但也许对您有用)。
现在,这有点复杂,所以让我先给您提供源代码链接:http://icedtea.classpath.org/~dlila/webrevs/perfWebrev/webrev/raw_files/new/src/share/classes/sun/java2d/pisces/Dasher.java。您所需的内容在LengthIterator类中。您不必查看文件的其他部分。还有另一个文件中定义的一堆方法。要访问它们,只需从“/raw_files/”开始剪切,直到URL的结尾。使用它的方法是:在曲线上初始化对象。然后,要从曲线开头获取弧长为L的点的参数,只需调用next(L)(要获取实际点,请使用deCasteljau算法或zneak的建议评估您的曲线)。每次调用next(x)将使您相对于上次位置沿曲线移动x距离。当您用完曲线时,next返回负数。
代码解释:我需要一个t值,使得B(0)到B(t)的长度为LEN(其中LEN已知)。我简单地将曲线展平。因此,只需递归地细分曲线,直到每条曲线足够接近一条直线(可以通过比较控制多边形的长度和连接端点的线段的长度来测试这一点)。您可以计算此子曲线的长度为(controlPolyLength + endPointsSegmentLen)/ 2。将所有这些长度添加到累加器中,并在累加器值> = LEN时停止递归。现在,调用最后一个子曲线C并让[t0,t1]为其域。您知道要找的t是t0 <= t C(1)线上,但它非常接近我们想要的点。因此,我们只需解决Bx(t)=Px和By(t)=Py。这只是找到立方根,具有封闭源解,但我只使用了牛顿法。现在我们有了所需的t,我们可以计算C(t),这是实际点。
我应该提到,几个月前我浏览了一篇论文,其中有另一种解决方案,找到了曲线的自然参数化的近似值。作者在此处发布了一个链接:Equidistant points across Bezier curves

非常抱歉两年前您发布这篇文章时我没有进行评论,因为我在SO上并没有太多的声望(这也让我没有获得任何声望..是的,是的)...但是您的回答非常出色,代码示例也很棒,现在我需要完全理解这个响应.... - Prozacgod

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