【发布时间】:2015-05-24 03:14:22
【问题描述】:
我有一组代表贝塞尔曲线的控制点。它可以是五阶或 100 阶贝塞尔曲线,或者介于两者之间的任何曲线。我正在寻找一种将贝塞尔曲线简化为多条三次贝塞尔曲线的方法。下图展示了如何将 10 度曲线简化为 3 度曲线,但我想更进一步,将其简化为几条三次贝塞尔曲线以达到更好的逼近。
代码示例会很有帮助。
【问题讨论】:
-
一般来说:分段贝塞尔曲线只不过是 b 样条曲线。
标签: bezier
我有一组代表贝塞尔曲线的控制点。它可以是五阶或 100 阶贝塞尔曲线,或者介于两者之间的任何曲线。我正在寻找一种将贝塞尔曲线简化为多条三次贝塞尔曲线的方法。下图展示了如何将 10 度曲线简化为 3 度曲线,但我想更进一步,将其简化为几条三次贝塞尔曲线以达到更好的逼近。
代码示例会很有帮助。
【问题讨论】:
标签: bezier
正如 mohsenmadi 已经指出的那样:一般来说,如果不提出自己的错误度量标准,您就无法做到这一点。另一个想法是“好吧,让我们将这条曲线近似为低阶曲线的序列”,以便我们得到看起来更好的东西,并且不需要错误度量。这有点像将曲线“展平”为线,除了我们将使用三次贝塞尔线段代替线之外,这会产生漂亮的曲线,同时就现代图形库而言保持一切“易于处理”。
那么我们可以做的是:通过定期对曲线进行采样,然后通过 Catmull-Rom 算法运行这些点,将“100 阶曲线”拆分为一系列三次贝塞尔曲线。过程很简单:
t 选择一些规则间隔的值,例如 0、0.2、0.4、0.6、0.8 和 1,然后1 开始并沿其切线向后移动形成点0,并通过从n 开始并沿其切线形成点n+1。我们这样做是因为:0 开始,到虚拟点 n+1 结束。让我们在图片中做到这一点。让我们从 11 阶贝塞尔曲线开始:
然后让我们定期对其进行采样:
我们发明了第 0 点和第 n+1 点:
然后我们运行 Catmull-Rom 程序:
i = 0
e = points.length-4
curves = []
do {
crset = points.subset(i, 4)
curves.push(formCRCurve(crset))
} while(i++<e)
formCRCurve 有什么作用?好问题:
formCRCurve(points: p1, p2, p3, p4):
d_start = vector(p2.x - p1.x, p2.y - p1.y)
d_end = vector(p4.x - p3.x, p4.y - p3.y)
return Curve(p2, d_start, d_end, p3)
所以我们明白了为什么需要这些虚拟点:给定四个点,我们可以使用从点 1 和点 4 获得的切线信息,形成从点 2 到点 3 的 Catmull-Rom 曲线。
当然,我们实际上想要的是 Bezier 曲线,而不是 Catmull-Rom 曲线,但因为它们是相同的“种类”曲线,我们可以freely convert between the two,所以:
i = 0
e = points.length-4
bcurves = []
do {
pointset = points.subset(i, 4)
bcurves.push(formBezierCurve(pointset))
} while(i++<e)
formBezierCurve(points: p1, p2, p3, p4):
return bezier(
p2,
p2 + (p3 - p1)/6
p3 - (p4 - p2)/6
p3
)
因此,基于点 {p1,p2,p3,p4} 的 Catmull-Rom 曲线通过 点 p2 和 p3,可以写成等效的贝塞尔曲线使用 start/control1/control2/end 坐标 p2、p2 + (p3 - p1)/6、p3 - (p4 - p2)/6 和 p3。
【讨论】:
d_start 和 d_end 在第二个 formCurve 函数中做了什么?第二个函数应该替换第一个函数,还是我应该以某种方式同时使用它们? (2) 我尝试实现这一点,仅使用您的最后一段作为信息,但仅在使用 p2 + (p3 - p1)/6 和 p3 - (p4 - p2)/6 时才得到合理的结果。请注意,我切换了+ 和-。是我做错了还是你做错了?
首先,您必须知道没有近似的低阶曲线可以让您公正!你一定会引入错误而无法逃脱。那么问题来了:如何近似使得原始曲线和结果曲线在视觉上相似?
假设您的原始曲线的度数为 n。首先,subdivide它。您可以根据需要多次细分曲线而不会引入任何错误。这里,每个细分的度数仍然是n,但是几何复杂度和曲率大大降低。其次,每个细分的 reduce the degree 现在是一个简单的形状,没有会引入近似误差的高曲率。
【讨论】: