细分多分段Cubic Bezier样条

时间:2016-03-06 00:10:53

标签: linear bezier spline after-effects cubic

首先让我为一个糟糕的英语道歉,可能不是很直接的问题,因为我不确定如何称呼它。

我有一个多分段立方贝塞尔曲线在After Effects中,它是由5个顶点定义的IN& OUT切线。我的任务是将它细分为Java Script中的N个小线性块。

EDIT提交了更多信息。 给定一个多分段的Cubic Bezier样条,由5个点定义,In&切线,我需要得到它的线性表示。其中N是线性段的数量,由用户定义。

Cubic Bezier Spline:

Segment1: P0, P0out, P1in, P1;
Segment2: P1, P1out, P2in, P2;
Segment3: P2, P2out, P3in, P3;
Segment4: P3, P3out, P4in, P4;

预期产出:

N = 1: linear spline with 2 anchors representing entire shape;
N = 2: linear spline with 3 anchors representing entire shape;
N = 3: linear spline with 4 anchors representing entire shape;
N = 4: linear spline with 5 anchors representing entire shape;
...
N = 8: linear spline with 9 anchors representing entire shape;

distance(L0,L1) = distance(L1,L2) = distance(L2,L3) = ... = distance(L-n, Ln)

在示例图像中,我使用了4段样条,其中段长度彼此相等 - 这更容易绘制以解释我的任务。但在实际项目中,这些细分市场并不相同,总共会有超过4个细分市场。

我查看了de Casteljau方法,但据我所知,它适用于一个段样条。我的数学技能很尘埃,所以我不确定我是否可以在我的例子中使用de Casteljau。

2 个答案:

答案 0 :(得分:1)

这在概念上是直截了当的,虽然它可能涉及相当多的代码,原因稍后会解释。你要做的是压扁(立方)poly-Bezier,所以让我们从那开始:

单个三次贝塞尔曲线由四个点生成:起点,确定起点切线的控制点,终点和确定终点切线的控制点。然后,曲线是立方贝塞尔函数的图:

Bx(t) = p1.x × (1-t)³ + 2 × p2.x × (1-t)² × t + 2 × p3.x × (1-t) × t² + p4.x × t³
By(t) = p1.y × (1-t)³ + 2 × p2.y × (1-t)² × t + 2 × p3.y × (1-t) × t² + p4.y × t³

在区间t=[0,1]上绘制单个贝塞尔曲线,因此在整个区间N × [0,1]上绘制了N段的多贝塞尔曲线。

首先,简单的案例:简单的扁平化。贝塞尔曲线是非线性曲线,因此我们首先不要为每个线段强制执行“相同的长度”。给定一个N段poly-Bezier:

S = number of segments we want
points = empty list
for (s = 0):(s = S):(step = S/N):
  v = s * step
  segmentid = floor(v)
  segment = polycurve.segments[segmentid] 
  t = v % 1
  points.push(
    segment.pointAt(t)
  )

我们现在拥有了我们需要的所有要点,我们只需将它们与线路连接起来。完成。

然而,贝塞尔曲线是非线性曲线,因此以这种方式展平不会产生最细微的等距离曲线。如果我们想这样做,我们需要使用distance along the curve而不是t值。

S = number of segments we want
points = empty list
for (s = 0):(s = S):(step = S/N):
  v = s * step
  segmentid = floor(v)
  segment = polycurve.segments[segmentid]
  distanceRatio = v % 1
  t = segment.getTforDistanceRatio(distanceRatio)
  points.push(
    segment.pointAt(t)
  )

这将完全按照您的意愿工作,但getTforDistanceRatio是困难的部分,因为我们在这里做的是重新参数化曲线的距离,而不是时间,这是非常难的< / em>数学问题(没有一般的符号解决方案)。最便宜的方法是使用查找表(LUT),在上面的链接中对“沿曲线的距离”进行了解释。

答案 1 :(得分:0)

de Casteljau方法用于计算贝塞尔曲线上的点,并获得过程中两条细分曲线的控制点。所以,是的,如果您知道控制点,您应该能够使用de Cateljau方法在贝塞尔曲线上评估任意多个点。

从你展示的图片和你的“三次贝塞尔样条曲线”输入/输出切线作为输入这一事实,我认为你的样条实际上是“三次Hermite样条”,其中每个段确实是一个三次贝塞尔曲线。您可以将样条曲线的每个线段转换为三次贝塞尔曲线,然后使用de Cateljau方法根据需要计算多个点,然后用直线连接这些点。