最近要想办法从三次Hermite样条曲线创建平行曲线,比如铁路车道。首先,我只是沿着法线方向移动它们的开始/结束控制点,同时保持相同的开始/结束切线。它在大多数情况下工作得很好,因为在我的用例中,大多数样条曲线不是很弯曲。
但我很快发现,即使是一些轻微弯曲的样条,用这种天真的方式复制的曲线也往往会导致变窄。所以,我决定硬着头皮通过谷歌搜索了解一下其他聪明人已经想通的事情。
建议:使用NSDT设计器快速建立一个可编程的三维场景。
我很快了解到这种曲线的官方术语是偏置曲线或平行曲线。我遇到的第一种方法是将曲线转换为折线,偏移折线,然后将它们重建为一条或多条曲线。这听起来很复杂。我想找一个更直接的方法,不经过折线阶段。
我发现的下一个方法是偏移它的控制多边形(这里和这里)。您可以轻松地将三次Hermite样条曲线转换为贝塞尔曲线,如下所述。在贝塞尔曲线形式中,你可以从四个控制点得到一个控制多边形。您可以偏移它,并从它获得偏移样条线,如下所示:
如上面两个环节所述,这种方法不适合曲率较高的曲线,这种情况下你需要将原曲线分成多段才能得到较好的效果。我觉得对于我的用例来说,拆分/细分是没有必要的,所以我决定尝试这种方法。
我有3D样条,所以我使用斜线之间的距离方程(如这里)来获得控制多边形的偏移边之间的交点。我的样条曲线对于每个控制点也只有一条切线。换句话说,没有单独的引入/引出切线。因此,一旦计算出相邻线段的偏移样条,我会将共享控制点的切线设置为第一条线段的结束切线和第二条线段的起始切线的平均值。
这种方法提供的平行曲线对于我所拥有的大多数样条曲线来说已经足够好了。但是,当切线很长,控制多边形与自身相交时,一些偏移曲线会变得很糟糕。此外,对于其他情况,它们有点过度补偿,变得比应有的更宽。
所以我介绍了一些调整,比如当控制多边形的内角太尖锐的时候回到naive模式,在naive结果和基于内角余弦的方法之间调整,避免在某些情况下变得太宽。在极少数情况下,这种调整后的方法仍然会失败。对于他们,我可以在此方法之前应用分段,但现在,我决定手动修改原始样条,以便他们可以更好地使用此方法,而无需自动分段。我认为每个控制点都有一条切线(没有单独的输入/输出切线)也会使这些情况变得更糟。
如您所见,这并不完全令人满意。它需要一些肮脏的调整,但它仍然不能处理所有的情况。业余时间多挖掘了一些内容,发现了一些有用的信息和更多值得以后尝试的方法。这份存档的PDF文档解释了从第34页开始通过求解三个线性方程获得的贝塞尔偏移曲线。它从一个简单的方法开始,通过求解三个未知数的线性方程组来计算如何修改获得的曲线以满足理想偏移曲线的性质。这种方法也有一些失败的情况,本文解释了一种通过确定一个未知量并仅使用两个线性方程来处理这些失败情况的方法。它在Postscript中有示例代码。
很多参考文献告诉你,一般来说,不能用另一条Bezier曲线(或者任何多项式参数曲线,不管你更喜欢什么高阶)来表示Bezier曲线的等距曲线。第28页也说了,任何三次曲线的等距曲线都需要10次代数曲线。
Github有一个非常漂亮详细的关于贝塞尔曲线的入门,里面包含了关于贝塞尔曲线的各种有用信息,还有交互式和可视化的指南。它的偏移曲线部分解释了另一种涉及分段的方法。使用它,您可以“将曲线切割成‘安全’子曲线(其中安全意味着所有控制点总是在基线的一侧,并且t=0.5时曲线的中点大致在中心),然后相对于其缩放原点(即起点和终点的点法线的交点)缩放每个子曲线。”它在这个仓库中有所有相关的代码,所以你可以很容易地检查它的实现细节。
上面说的两个备选方案,听起来都很合理,似乎也不难实现。当控制多边形对我的用例来说变得太脆弱和麻烦时,我会尝试当前的方法。
我的短暂研究对我来说是一次非常有趣和有教育意义的旅程,它显示了如何获得样条曲线的平行版本这一看似简单的问题中所涉及的细微差别和复杂性。希望对你有意思,有帮助!
原文链接:http://www . bi mant . com/blog/cubic-spline-offset-curves-calculation/