假设我正在使用一些允许我绘制的图形API bezier曲线通过指定4个必要点: 开始,结束,两个控制点。
我可以重复使用此功能来绘制“原始”曲线的 x% (通过调整控制点和终点)?
还是不可能?
不必要的信息,如果有人关心:
我正在使用Java的Path2D来绘制贝塞尔曲线:
Path2D p = new GeneralPath();
p.moveTo(x1, y1);
p.curveTo(bx1, by1, bx2, by2, x2, y2);
g2.draw(p);
答案 0 :(得分:17)
您需要的是the De Casteljau algorithm。这样您就可以将曲线分割成您想要的任何片段。
然而,由于你只处理三次曲线,我想建议一个稍微容易使用的公式,它会给你一个从t0
到t1
的片段,其中{{1 }}。这是一些伪代码:
0 <= t0 <= t1 <= 1
然后绘制由u0 = 1.0 - t0
u1 = 1.0 - t1
qxa = x1*u0*u0 + bx1*2*t0*u0 + bx2*t0*t0
qxb = x1*u1*u1 + bx1*2*t1*u1 + bx2*t1*t1
qxc = bx1*u0*u0 + bx2*2*t0*u0 + x2*t0*t0
qxd = bx1*u1*u1 + bx2*2*t1*u1 + x2*t1*t1
qya = y1*u0*u0 + by1*2*t0*u0 + by2*t0*t0
qyb = y1*u1*u1 + by1*2*t1*u1 + by2*t1*t1
qyc = by1*u0*u0 + by2*2*t0*u0 + y2*t0*t0
qyd = by1*u1*u1 + by2*2*t1*u1 + y2*t1*t1
xa = qxa*u0 + qxc*t0
xb = qxa*u1 + qxc*t1
xc = qxb*u0 + qxd*t0
xd = qxb*u1 + qxd*t1
ya = qya*u0 + qyc*t0
yb = qya*u1 + qyc*t1
yc = qyb*u0 + qyd*t0
yd = qyb*u1 + qyd*t1
,(xa,ya)
,(xb,yb)
和(xc,yc)
组成的Bézier曲线。
请注意,(xd,yd)
和t0
不是曲线距离的确切百分比,而是曲线参数空间。如果你绝对必须有距离那么事情要困难得多。尝试一下,看看它是否能满足您的需求。
编辑:值得注意的是,如果t1
或t0
为0或1(即您只想从一侧修剪),这些方程式会相当简化
此外,关系t1
并非严格要求。例如,0 <= t0 <= t1 <= 1
和t0 = 1
可用于向后“翻转”曲线,或t1 = 0
和t0 = 0
可用于将曲线延伸超过原始结束。但是,如果您尝试将其延伸超过t1 = 1.5
范围,则曲线可能与您预期的不同。
Edit2:在我的原始答案超过3年后,MvG在我的方程式中指出了一个错误。我忘记了最后一步(额外的线性插值来获得最终控制点)。上面的等式已得到纠正。
答案 1 :(得分:9)
在an answer到another question中,我只包含了一些公式来计算三次曲线的一部分的控制点。随着 u = 1 - t ,立方贝塞尔曲线被描述为
B( t )= u 3 P 1 + 3 < i>你 2 t P 2 + 3 ut < sup> 2
3 + 3 P 4 子>
P 1 是曲线的起点, P 4 是其终点。 P 2 和 P 3 是控制点。
给出两个参数 t 0 和 t 1 (以及 u 0 =(1 - t 0 ), u 1 =(1 - t 1 )),区间[ t 0 , t < / i> 1 ]由新控制点
描述请注意,在带括号的表达式中,至少有一些术语是相同的,可以组合使用。我没有这样做,因为这里所说的公式将使模式更清晰,我相信。您可以单独为 x 和 y 方向执行这些计算,以计算新的控制点。
请注意, t 的参数范围的给定百分比通常不会与长度的相同百分比相对应。因此,您很可能必须在曲线上进行积分,以将路径长度转换回参数。或者你使用一些近似值。