我有一组代表贝塞尔曲线的控制点。它可以是五阶或100阶贝塞尔曲线,也可以是介于两者之间的任何曲线。我正在寻找一种方法将贝塞尔曲线简化为多个三次贝塞尔曲线。下图显示了如何将十度曲线简化为三度曲线,但我想进一步将其简化为几条三次贝塞尔曲线,以实现更好的逼近。
代码示例非常有用。
答案 0 :(得分:5)
正如mohsenmadi已经指出的那样:一般来说,如果不提出自己的错误指标,这不是一件事。另一个想法是,让我们将这条曲线近似为低阶曲线的序列",这样我们得到的东西看起来更好,并且没有&#39 ; t确实需要错误指标。这有点像"扁平化"曲线到线条,除了代替线条,我们将改为使用立方贝塞尔曲线,这样可以提供漂亮的曲线,同时保持所有的线条和易于处理的曲线。就现代图形库而言。
然后我们能做的是:将那个" 100阶曲线"分开。通过定期对曲线进行采样,然后通过Catmull-Rom算法运行这些点,进入一系列三次贝塞尔曲线。程序非常简单:
t
选择一些定期间隔的值,如0,0.2,0.4,0.6,0.8和1,然后0
开始形成点1
并沿其切线向后移动,并从{{1}开始形成点n+1
跟随它的切线。我们这样做,因为:n
开始,到虚拟点0
结束。让我们在图片中这样做。让我们从11阶贝塞尔曲线开始:
然后让我们定期对其进行抽样:
我们发明了第0和第n + 1点:
然后我们运行Catmull-Rom程序:
n+1
formCRCurve做什么?好问题:
i = 0
e = points.length-4
curves = []
do {
crset = points.subset(i, 4)
curves.push(formCRCurve(crset))
} while(i++<e)
所以我们看到为什么我们需要这些虚拟点:给定四个点,我们可以使用我们在第1点和第4点的帮助下得到的切线信息,形成从第2点到第3点的Catmull-Rom曲线。
当然,我们实际上需要Bezier曲线,而不是Catmull-Rom曲线,但因为它们是相同的#34;类型&#34;曲线,我们可以freely convert between the two,所以:
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)
因此,基于点{p1,p2,p3,p4}的Catmull-Rom曲线(通过通过点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
)
和p2
)可以写成等效贝塞尔曲线,使用start / control1 / control2 / end协调p3
,p2
,p2 + (p3 - p1)/6
和p3 - (p4 - p2)/6
。
答案 1 :(得分:1)
首先,您必须知道没有近似的低度曲线可以帮助您伸张正义!你一定会引入错误没有逃脱。那么问题是:如何近似以使原始和结果曲线在视觉上相似?
假设您的原始曲线为 n 。首先,subdivide它。您可以根据需要多次细分曲线,而不会引入任何错误。这里,每个细分的程度仍然是 n ,但几何复杂度和曲率明显降低。其次,每个细分的reduce the degree,现在是一个没有高曲率的简单形状,会引入近似误差。