简化高阶贝塞尔曲线

时间:2015-05-24 03:14:22

标签: bezier

我有一组代表贝塞尔曲线的控制点。它可以是五阶或100阶贝塞尔曲线,也可以是介于两者之间的任何曲线。我正在寻找一种方法将贝塞尔曲线简化为多个三次贝塞尔曲线。下图显示了如何将十度曲线简化为三度曲线,但我想进一步将其简化为几条三次贝塞尔曲线,以实现更好的逼近。

http://snag.gy/aHPjc.jpg

代码示例非常有用。

2 个答案:

答案 0 :(得分:5)

正如mohsenmadi已经指出的那样:一般来说,如果不提出自己的错误指标,这不是一件事。另一个想法是,让我们将这条曲线近似为低阶曲线的序列",这样我们得到的东西看起来更好,并且没有&#39 ; t确实需要错误指标。这有点像"扁平化"曲线到线条,除了代替线条,我们将改为使用立方贝塞尔曲线,这样可以提供漂亮的曲线,同时保持所有的线条和易于处理的曲线。就现代图形库而言。

然后我们能做的是:将那个" 100阶曲线"分开。通过定期对曲线进行采样,然后通过Catmull-Rom算法运行这些点,进入一系列三次贝塞尔曲线。程序非常简单:

  1. t选择一些定期间隔的值,如0,0.2,0.4,0.6,0.8和1,然后
  2. 创建一组点tvalues.map(t => getCoordinate(curve,t))。然后,
  3. 构建虚拟起点和终点:从点0开始形成点1并沿其切线向后移动,并从{{1}开始形成点n+1跟随它的切线。我们这样做,因为:
  4. 构建poly-Catmull-Rom,从虚拟点n开始,到虚拟点0结束。
  5. 让我们在图片中这样做。让我们从11阶贝塞尔曲线开始:

    enter image description here

    然后让我们定期对其进行抽样:

    enter image description here

    我们发明了第0和第n + 1点:

    enter image description here

    然后我们运行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协调p3p2p2 + (p3 - p1)/6p3 - (p4 - p2)/6

答案 1 :(得分:1)

首先,您必须知道没有近似的低度曲线可以帮助您伸张正义!你一定会引入错误没有逃脱。那么问题是:如何近似以使原始和结果曲线在视觉上相似?

假设您的原始曲线为 n 。首先,subdivide它。您可以根据需要多次细分曲线,而不会引入任何错误。这里,每个细分的程度仍然是 n ,但几何复杂度和曲率明显降低。其次,每个细分的reduce the degree,现在是一个没有高曲率的简单形状,会引入近似误差。