【问题标题】:Simplify high-order Bezier curve简化高阶贝塞尔曲线
【发布时间】:2015-05-24 03:14:22
【问题描述】:

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

代码示例会很有帮助。

【问题讨论】:

  • 一般来说:分段贝塞尔曲线只不过是 b 样条曲线。

标签: bezier


【解决方案1】:

正如 mohsenmadi 已经指出的那样:一般来说,如果不提出自己的错误度量标准,您就无法做到这一点。另一个想法是“好吧,让我们将这条曲线近似为低阶曲线的序列”,以便我们得到看起来更好的东西,并且不需要错误度量。这有点像将曲线“展平”为线,除了我们将使用三次贝塞尔线段代替线之外,这会产生漂亮的曲线,同时就现代图形库而言保持一切“易于处理”。

那么我们可以做的是:通过定期对曲线进行采样,然后通过 Catmull-Rom 算法运行这些点,将“100 阶曲线”拆分为一系列三次贝塞尔曲线。过程很简单:

  1. t 选择一些规则间隔的值,例如 0、0.2、0.4、0.6、0.8 和 1,然后
  2. 创建点集 tvalues.map(t => getCoordinate(curve, t))。那么,
  3. 构建虚拟起点和终点:从点1 开始并沿其切线向后移动形成点0,并通过从n 开始并沿其切线形成点n+1。我们这样做是因为:
  4. 构建 poly-Catmull-Rom,从虚拟点 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 曲线通过 p2p3,可以写成等效的贝塞尔曲线使用 start/control1/control2/end 坐标 p2p2 + (p3 - p1)/6p3 - (p4 - p2)/6p3

【讨论】:

  • 两个问题:(1) d_startd_end 在第二个 formCurve 函数中做了什么?第二个函数应该替换第一个函数,还是我应该以某种方式同时使用它们? (2) 我尝试实现这一点,仅使用您的最后一段作为信息,但仅在使用 p2 + (p3 - p1)/6p3 - (p4 - p2)/6 时才得到合理的结果。请注意,我切换了+-。是我做错了还是你做错了?
  • 啊,好点!让我更新答案。第二个函数替​​换了第一个函数(第一个函数生成 Catmull-Rom 曲线,第二个函数生成 Bezier 曲线,基于 Catmull-Rom 曲线)。是的,我完全不小心加了 +/- 符号。
【解决方案2】:

首先,您必须知道没有近似的低阶曲线可以让您公正!你一定会引入错误而无法逃脱。那么问题来了:如何近似使得原始曲线和结果曲线在视觉上相似?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 2011-03-10
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多