贝塞尔路径加宽
我有一条贝塞尔曲线 B,其中有点 S、C1、C2、E,以及代表宽度的正数 w。有没有一种方法可以快速计算两条贝塞尔曲线B1、B2的控制点,使得B1和B2之间的东西就是B表示的加宽路径?
更正式地说:计算 B1、B2 的良好 Bezier 近似的控制点,其中 B1 = {(x,y) + N(x,y)(w/2) | C 中的 (x,y)}
B2 = {(x,y) - N(x,y)(w/2) | B2 = {(x,y) - N(x,y)(w/2) | C 中的 (x,y)},
其中 N(x,y) 是法线 C 在 (x,y) 处。
我说好的近似值是因为 B1、B2 可能不是多项式曲线(我不确定它们是否是)。
I have a bezier curve B with points S, C1, C2, E, and a positive number w representing width. Is there a way of quickly computing the control points of two bezier curves B1, B2 such that the stuff between B1 and B2 is the widened path represented by B?
More formally: compute the control points of good Bezier approximations to B1, B2, where
B1 = {(x,y) + N(x,y)(w/2) | (x,y) in C}
B2 = {(x,y) - N(x,y)(w/2) | (x,y) in C},
where N(x,y) is the normal
of C at (x,y).
I say good approximations because B1, B2 might not be polynomial curves (I'm not sure if they are).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从数学角度来看,贝塞尔曲线的精确平行相当难看(它需要 10 次多项式)。
容易做的是从贝塞尔曲线的多边形近似计算加宽(即从贝塞尔曲线计算线段,然后沿着曲线两侧的法线移动点)。
如果你的厚度与曲率相比不是太大,这会给出很好的结果......“远平行”本身就是一个怪物(并且甚至很难找到什么是开放曲线的平行的定义这会让每个人都高兴)。
一旦两侧有了两条多段线,如果您需要该表示,您可以做的是为这些路径找到最佳近似贝塞尔曲线。我再次认为,对于“正常情况”(即相当细的线),即使两侧各有一条贝塞尔曲线也应该非常准确(误差应该比线的粗细小得多)。
编辑:实际上,即使对于相当正常的情况,使用单个贝塞尔曲线看起来也比我预期的要糟糕得多。我还尝试在每一侧使用两个贝塞尔弧,结果更好,但仍然不完美。当然,误差远小于线条的粗细,因此除非线条非常粗,否则它可能是一个合理的选择。在下图中,它显示了加厚的贝塞尔曲线(每点加厚)、每侧使用单个贝塞尔曲线的近似值以及每侧使用两个贝塞尔曲线的近似值。
编辑2:根据要求,我添加了用于获取图片的代码;它是用 python 编写的,只需要 Qt。这段代码并不适合其他人阅读,因此我使用了一些可能不会在实际生产代码中使用的技巧。该算法也非常低效,但我并不关心速度(这本来是一个一次性程序,看看这个想法是否有效)。
The exact parallel of a bezier curve is quite ugly from a mathematical point of view (it requires 10th-degree polynomials).
What is easy to do is compute a widening from a polygonal approximation of the bezier (that is you compute line segments from the bezier and then move the points along the normals on the two sides of the curve).
This gives good results if your thickness isn't too big compared to the curvature... a "far parallel" instead is a monster on its own (and it's not even easy to find a definition of what is a parallel of an open curve that would make everyone happy).
Once you have two polylines for the two sides what you can do is finding a best approximating bezier for those paths if you need that representation. Once again I think that for "normal cases" (that is reasonably thin lines) even just a single bezier arc for each of the two sides should be quite accurate (the error should be much smaller than the thickness of the line).
EDIT: Indeed using a single bezier arc looks much worse than I would have expected even for reasonably normal cases. I tried also using two bezier arcs for each side and the result are better but still not perfect. The error is of course much smaller than the thickness of the line so unless lines are very thick it could be a reasonable option. In the following picture it's shown a thickened bezier (with per-point thickening), an approximation using a single bezier arc for each side and an approximation using two bezier arcs for each side.
EDIT 2: As requested I add the code I used to get the pictures; it's in python and requires only Qt. This code wasn't meant to be read by others so I used some tricks that probably I wouldn't use in real production code. The algorithm is also very inefficient but I didn't care about speed (this was meant to be a one-shot program to see if the idea works).