本文介绍了Bezier曲线的几个核心问题!
普通Bezier曲线
普通 n 次Bezier曲线定义为:
C(t)=i=0∑nBi,n(t)Pi
其中 Bernstein 基函数为:
Bi,n(t)=(in)(1−t)n−iti
并且:
i=0∑nBi,n(t)=1
所以普通Bezier曲线可以理解为: 在每个参数 t 处,对所有控制点 Pi 做一次加权平均。
有理Bezier曲线
有理Bezier曲线在每个控制点前增加了权重 wi:
C(t)=∑i=0nwiBi,n(t)∑i=0nwiBi,n(t)Pi
也可以写成:
C(t)=i=0∑nRi,n(t)Pi
其中:
Ri,n(t)=∑j=0nwjBj,n(t)wiBi,n(t)
这里的 Ri,n(t) 叫做有理基函数。
因此,权重并不是简单地把控制点坐标放大,而是改变控制点在加权平均中的比例。
权重的作用
在有理Bezier曲线中,控制点的权重 wi 表示该控制点对曲线的吸引力强弱。
- wi>1:曲线更靠近控制点 Pi
- wi=1:等同于普通Bezier曲线
- 0<wi<1:曲线远离控制点 Pi
- wi=0:该控制点基本失去影响
- wi<0:数学上可以存在,但几何行为不直观,工程中通常避免
普通Bezier曲线不能精确表示圆、椭圆、双曲线等圆锥曲线,只能近似。
有理Bezier曲线通过权重可以精确表示这些曲线。
例如,用二次有理Bezier曲线表示一段圆弧时,中间控制点权重常取:
w=cos2θ
其中 θ 是圆弧对应的圆心角。
例如 90∘ 圆弧:
w=cos45∘=22≈0.7071
这就是 CAD、NURBS、OpenCASCADE 等几何系统大量使用有理曲线的原因。
二次有理Bezier曲线例子
对于三个控制点:
P0, P1, P2
二次有理Bezier曲线为:
C(t)=(1−t)2w0+2t(1−t)w1+t2w2(1−t)2w0P0+2t(1−t)w1P1+t2w2P2
通常令两端权重为:
w0=1,w2=1
只调节中间控制点的权重:
w1=w
则:
C(t)=(1−t)2+2wt(1−t)+t2(1−t)2P0+2wt(1−t)P1+t2P2
当 t=0.5 时:
C(0.5)=0.5+0.5w0.25P0+0.5wP1+0.25P2
可以看到,w 越大,中间控制点 P1 的影响越大,曲线越靠近 P1。
齐次坐标
有理Bezier曲线还可以理解为: 先在高一维空间中做普通Bezier曲线,然后再投影回来。
对于二维控制点:
Pi=(xi,yi)
引入齐次坐标:
Pih=(wixi, wiyi, wi)
在三维中计算普通Bezier曲线:
Q(t)=i=0∑nBi,n(t)Pih
得到:
Q(t)=(X(t),Y(t),W(t))
然后投影回二维:
C(t)=(W(t)X(t),W(t)Y(t))
这正是有理Bezier曲线公式中“分子除以分母”的来源。
当w1=0.707时,曲线为什么是精确1/4圆弧
前提
当 w1=0.7071≈22 时,二次有理Bezier曲线是精确 1/4 圆弧,前提是控制点取成圆弧端点及其切线交点,例如单位圆第一象限:
P0=(1,0),P1=(1,1),P2=(0,1)
权重为:
w0=1,w1=22,w2=1
此时曲线就是单位圆
x2+y2=1
上的第一象限圆弧。
二次有理Bezier曲线公式
C(t)=(1−t)2+2wt(1−t)+t2(1−t)2P0+2wt(1−t)P1+t2P2
证明
令:
a=(1−t)2b=2wt(1−t)c=t2
带入点坐标,则曲线点为:
C(t)=Da(1,0)+b(1,1)+c(0,1)=(Da+b,Db+c)
也就是:
x(t)=Da+b,y(t)=Db+c
我们要证明它在单位圆上,即:
x(t)2+y(t)2=1x2+y2=(Da+b)2+(Db+c)2=D2(a+b)2+(b+c)2
因此只需要证明:
(a+b)2+(b+c)2=D2
右式=D2=(a+b+c)2=a2+b2+c2+2ab+2ac+2bc左式=(a+b)2+(b+c)2=a2+2ab+b2+b2+2bc+c2
两者相等的条件是:
a2+b2+c2+2ab+2ac+2bc=a2+c2+2ab+2bc+2b2b2+2ac=2b2证明:2ac=b2
前面定义:
a=(1−t)2b=2wt(1−t)c=t2
所以:
2ac=2(1−t)2t2
而:
b2=(2wt(1−t))2=4w2t2(1−t)2
要求:
2ac=b2
即:
2t2(1−t)2=4w2t2(1−t)2w2=21w=22≈0.7071
更一般结论
对于一段圆心角为 θ 的圆弧,二次有理Bezier曲线可以精确表示它。
如果:
- P0、P2 是圆弧两端点
- P1 是两端点切线的交点
- w0=1
- w2=1
那么中间控制点权重应取:
w1=cos2θ
最大可以表示多大弧度的圆弧
用一段二次有理Bezier曲线精确表示圆弧时,通常最大表示:
θ<180∘
也就是:
θ<π
工程上一般不用一段表示正好 180∘,而是把圆弧拆成多段。
为什么要求小于180°
二次有理Bezier圆弧的中间权重为:
w1=cos2θ
其中 θ 是圆弧对应的圆心角。
当:
0<θ<180∘
有:
0<2θ<90∘
所以:
cos2θ>0
权重是正数,曲线行为稳定、直观。
等于180°
如果是半圆:
θ=180∘w1=cos90∘=0w1=0
这时中间控制点的权重为零。
从几何上看,半圆两端点的切线是平行的,不会相交于有限点,因此中间控制点 P1 会跑到无穷远。
所以一段普通有限控制点的二次有理Bezier曲线不能稳定表示半圆。
大于180°
如果圆弧超过半圆:
θ>180∘2θ>90∘w1=cos2θ<0
中间权重变成负数。
负权重在数学上可以讨论,但在 CAD/NURBS 建模中通常不推荐:
- 曲线可能出现不直观的形状
- 参数化可能不稳定
- 分母可能接近或经过零
- 几何解释变差
- 许多几何内核更偏好正权重
因此工程中通常不使用一段二次有理Bezier表示超过 180∘ 的圆弧。
结论
一段二次有理Bezier曲线精确表示圆弧时:
w1=cos2θ
因此:
- 0∘<θ<180∘:权重为正,可稳定表示
- θ=180∘:权重为 0,控制点在无穷远,工程中不用
- θ>180∘:权重为负,通常不推荐
所以通常说:
一段二次有理贝塞尔曲线最大稳定表示小于 180∘ 的圆弧
实际工程中更推荐:
90∘ 一段,整圆拆成 4 段
Bezier曲线的计算
理论公式的局限性
普通Bezier曲线理论公式是:
C(t)=i=0∑nBi,n(t)Pi
其中:
Bi,n(t)=(in)(1−t)n−iti
这个公式当然可以直接计算,特别是阶数较低时,比如二次、三次Bezier曲线。
例如三次Bezier:
C(t)=(1−t)3P0+3(1−t)2tP1+3(1−t)t2P2+t3P3
但在实际计算中,直接公式有几个问题:
- 需要计算组合数
- 需要计算多次幂
- 高阶时数值误差更明显
- 阶数变化时实现不够统一
- 不方便做曲线分割、细分、求点构造
所以 CAD、图形学、字体、曲线编辑器中,通常更喜欢 de Casteljau 算法。
de Casteljau 算法
de Casteljau 算法的核心思想是:不断对相邻控制点做线性插值,最后得到曲线上的点。
两个点 A、B 之间按参数 t 插值:
L(A,B,t)=(1−t)A+tB
对于三次Bezier,控制点为:
P0,P1,P2,P3
第一层插值:
P01=(1−t)P0+tP1
P11=(1−t)P1+tP2
P21=(1−t)P2+tP3
第二层插值:
P02=(1−t)P01+tP11
P12=(1−t)P11+tP21
第三层插值:
P03=(1−t)P02+tP12
最后:
C(t)=P03
这和理论 Bernstein 公式是等价的,但数值稳定性更好。
二次Bezier的直观例子
二次Bezier有三个控制点:
P0,P1,P2
先插值:
Q0=(1−t)P0+tP1
Q1=(1−t)P1+tP2
再插值:
C(t)=(1−t)Q0+tQ1
这就是曲线上的点。
展开后会得到:
C(t)=(1−t)2P0+2(1−t)tP1+t2P2
所以 de Casteljau 算法不是近似,而是和公式完全等价。
有理Bezier怎么计算
有理Bezier曲线通常有两种实际计算方式。
方式一:直接用有理公式
有理Bezier曲线为:
C(t)=∑i=0nwiBi,n(t)∑i=0nwiBi,n(t)Pi
低阶曲线时直接算很方便。
例如二次有理Bezier:
C(t)=(1−t)2w0+2t(1−t)w1+t2w2(1−t)2w0P0+2t(1−t)w1P1+t2w2P2
如果你的程序只是计算二次或三次曲线上的点,这种方法完全可以接受。
方式二:用齐次坐标 + de Casteljau
工程中更统一的方式是使用齐次坐标。
二维点:
Pi=(xi,yi)
转换为三维齐次点:
Pih=(wixi,wiyi,wi)
然后对这些齐次点使用普通 de Casteljau 算法,得到:
Q(t)=(X(t),Y(t),W(t))
最后投影回二维:
C(t)=(W(t)X(t),W(t)Y(t))
三维点也是类似:
Pi=(xi,yi,zi)
转换为四维齐次点:
Pih=(wixi,wiyi,wizi,wi)
计算后再投影:
C(t)=(W(t)X(t),W(t)Y(t),W(t)Z(t))
这种方法的优点是:
- 普通Bezier和有理Bezier处理方式统一
- 数值稳定
- 适合任意阶数
- 方便做曲线分割
- 和 NURBS/CAD 内核的思想一致
实际工程的做法
低阶曲线,比如二次、三次
可以直接用公式:
C(t)=∑wiBi(t)∑wiBi(t)Pi
优点:
任意阶曲线
更推荐 de Casteljau 或其变体,原因:
- 不需要手写不同阶数公式
- 更适合动态控制点数量
- 细分曲线非常方便
- 数值稳定性更好
- 更符合几何算法实现习惯