在数学 的数值分析 领域中,贝塞尔曲线 (英语:Bézier curve )是电脑图形学 中相当重要的参数曲线 。更高维度 的广泛化贝塞尔曲线就称作贝兹曲面 ,其中贝兹三角 是一种特殊的实例。
三次方贝塞尔曲线
贝塞尔曲线于1962年,由法国 工程师皮埃尔·贝兹 (Pierre Bézier )所广泛发表,他运用贝塞尔曲线来为汽车 的主体进行设计。贝塞尔曲线最初由保尔·德·卡斯特里奥 于1959年运用德卡斯特里奥算法 开发,以稳定数值 的方法求出贝塞尔曲线。
给定点P 0 、P 1 ,线性贝塞尔曲线只是一条两点之间的直线 。这条线由下式给出:
B
(
t
)
=
P
0
+
(
P
1
−
P
0
)
t
=
(
1
−
t
)
P
0
+
t
P
1
,
t
∈
[
0
,
1
]
{\displaystyle \mathbf {B} (t)=\mathbf {P} _{0}+(\mathbf {P} _{1}-\mathbf {P} _{0})t=(1-t)\mathbf {P} _{0}+t\mathbf {P} _{1}{\mbox{ , }}t\in [0,1]}
且其等同于线性插值 。
二次方贝塞尔曲线的路径由给定点P 0 、P 1 、P 2 的函数B (t )追踪:
B
(
t
)
=
(
1
−
t
)
2
P
0
+
2
t
(
1
−
t
)
P
1
+
t
2
P
2
,
t
∈
[
0
,
1
]
{\displaystyle \mathbf {B} (t)=(1-t)^{2}\mathbf {P} _{0}+2t(1-t)\mathbf {P} _{1}+t^{2}\mathbf {P} _{2}{\mbox{ , }}t\in [0,1]}
TrueType 字体就运用了以贝兹样条 组成的二次贝塞尔曲线。
P 0 、P 1 、P 2 、P 3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于P 0 走向P 1 ,并从P 2 的方向来到P 3 。一般不会经过P 1 或P 2 ;这两个点只是在那里提供方向资讯。P 0 和P 1 之间的间距,决定了曲线在转而趋进P 2 之前,走向P 1 方向的“长度有多长”。
曲线的参数 形式为:
B
(
t
)
=
P
0
(
1
−
t
)
3
+
3
P
1
t
(
1
−
t
)
2
+
3
P
2
t
2
(
1
−
t
)
+
P
3
t
3
,
t
∈
[
0
,
1
]
{\displaystyle \mathbf {B} (t)=\mathbf {P} _{0}(1-t)^{3}+3\mathbf {P} _{1}t(1-t)^{2}+3\mathbf {P} _{2}t^{2}(1-t)+\mathbf {P} _{3}t^{3}{\mbox{ , }}t\in [0,1]}
现代的成象系统,如PostScript 、Asymptote 和Metafont ,运用了以贝兹样条 组成的三次贝塞尔曲线,用来描绘曲线轮廓。
一些关于参数曲线的术语,有
B
(
t
)
=
∑
i
=
0
n
P
i
b
i
,
n
(
t
)
,
t
∈
[
0
,
1
]
{\displaystyle \mathbf {B} (t)=\sum _{i=0}^{n}\mathbf {P} _{i}\mathbf {b} _{i,n}(t),\quad t\in [0,1]}
即多项式
b
i
,
n
(
t
)
=
(
n
i
)
t
i
(
1
−
t
)
n
−
i
,
i
=
0
,
…
n
{\displaystyle \mathbf {b} _{i,n}(t)={n \choose i}t^{i}(1-t)^{n-i},\quad i=0,\ldots n}
又称作n 阶的伯恩斯坦基底多项式 ,定义00 = 1。
点P i 称作贝塞尔曲线的控制点 。多边形 以带有线 的贝兹点连接而成,起始于P 0 并以P n 终止,称作贝兹多边形 (或控制多边形 )。贝兹多边形的凸包 (convex hull)包含有贝塞尔曲线。
开始于P 0 并结束于P n 的曲线,即所谓的端点插值法 属性。
曲线是直线的充分必要条件是所有的控制点都位在曲在线。同样的,贝塞尔曲线是直线的充分必要条件是控制点共线 。
曲线的起始点(结束点)相切 于贝兹多边形的第一节(最后一节)。
一条曲线可在任意点切割成两条或任意多条子曲线,每一条子曲线仍是贝塞尔曲线。
一些看似简单的曲线(如圆 )无法以贝塞尔曲线精确的描述,或分段成贝塞尔曲线(虽然当每个内部控制点对单位圆上的外部控制点水平或垂直的的距离为
4
(
2
−
1
)
/
3
{\displaystyle 4\left({\sqrt {2}}-1\right)/3}
时,分成四段的贝塞尔曲线,可以小于千分之一的最大半径误差近似于圆)。
位于固定偏移量的曲线(来自给定的贝塞尔曲线),又称作偏移曲线 (假平行于原来的曲线,如两条铁轨之间的偏移)无法以贝塞尔曲线精确的形成(某些平凡实例除外)。无论如何,现存的启发法 通常可为实际用途中给出近似值。
线性贝塞尔曲线演示动画,t 在[0,1]区间
线性贝塞尔曲线函数中的t 会经过由P 0 至P 1 的B (t )所描述的曲线。例如当t=0.25 时,B (t )即一条由点P 0 至P 1 路径的四分之一处。就像由0至1的连续t ,B (t )描述一条由P 0 至P 1 的直线。
为建构二次贝塞尔曲线,可以中介点Q 0 和Q 1 作为由0至1的t :
由P 0 至P 1 的连续点Q 0 ,描述一条线性贝塞尔曲线。
由P 1 至P 2 的连续点Q 1 ,描述一条线性贝塞尔曲线。
由Q 0 至Q 1 的连续点B (t ),描述一条二次贝塞尔曲线。
二次贝塞尔曲线的结构
二次贝塞尔曲线演示动画,t 在[0,1]区间
为建构高阶曲线,便需要相应更多的中介点。对于三次曲线,可由线性贝塞尔曲线描述的中介点Q 0 、Q 1 、Q 2 ,和由二次曲线描述的点R 0 、R 1 所建构:
三次贝塞尔曲线的结构
三次贝塞尔曲线演示动画,t 在[0,1]区间
对于四次曲线,可由线性贝塞尔曲线描述的中介点Q 0 、Q 1 、Q 2 、Q 3 ,由二次贝塞尔曲线描述的点R 0 、R 1 、R 2 ,和由三次贝塞尔曲线描述的点S 0 、S 1 所建构:
四次贝塞尔曲线的结构
四次贝塞尔曲线演示动画,t 在[0,1]区间
还可参阅五阶贝塞尔曲线的构成:
五次贝塞尔曲线演示动画,t 在[0,1]区间
这些运动轨迹使用德卡斯特里奥算法 计算出贝塞尔曲线。[ 1]
n 次贝塞尔曲线可以变换为一个形状完全相同的n+1 次贝塞尔曲线。
这在软件只支持特定阶次的贝塞尔曲线时很有用。
例如,Cairo 只支持三次贝塞尔曲线,你就可以用升阶的方法在Cairo画出二次贝塞尔曲线。
我们利用
B
(
t
)
=
(
1
−
t
)
B
(
t
)
+
t
B
(
t
)
{\displaystyle \mathbf {B} (t)=(1-t)\mathbf {B} (t)+t\mathbf {B} (t)}
这个特性来做升阶。我们把曲线方程式中每一项
b
i
,
n
(
t
)
P
i
{\displaystyle \mathbf {b} _{i,n}(t)\mathbf {P} _{i}}
都乘上 (1 − t ) 或 t ,让每一项都往上升一阶。以下是将二阶升为三阶的示例
(
1
−
t
)
2
P
0
+
2
(
1
−
t
)
t
P
1
+
t
2
P
2
=
(
1
−
t
)
3
P
0
+
(
1
−
t
)
2
t
P
0
+
2
(
1
−
t
)
2
t
P
1
+
2
(
1
−
t
)
t
2
P
1
+
(
1
−
t
)
t
2
P
2
+
t
3
P
2
=
(
1
−
t
)
3
P
0
+
3
(
1
−
t
)
2
t
P
0
+
2
P
1
3
+
3
(
1
−
t
)
t
2
2
P
1
+
P
2
3
+
t
3
P
2
{\displaystyle {\begin{aligned}&{}\quad (1-t)^{2}\mathbf {P} _{0}+2(1-t)t\mathbf {P} _{1}+t^{2}\mathbf {P} _{2}\\&=(1-t)^{3}\mathbf {P} _{0}+(1-t)^{2}t\mathbf {P} _{0}+2(1-t)^{2}t\mathbf {P} _{1}\\&{}\qquad +2(1-t)t^{2}\mathbf {P} _{1}+(1-t)t^{2}\mathbf {P} _{2}+t^{3}\mathbf {P} _{2}\\&=(1-t)^{3}\mathbf {P} _{0}+3(1-t)^{2}t{\frac {\mathbf {P} _{0}+2\mathbf {P} _{1}}{3}}+3(1-t)t^{2}{\frac {2\mathbf {P} _{1}+\mathbf {P} _{2}}{3}}+t^{3}\mathbf {P} _{2}\end{aligned}}}
对任何的n 值,我们都可以使用以下等式
(
n
+
1
i
)
(
1
−
t
)
b
i
,
n
=
(
n
i
)
b
i
,
n
+
1
,
(
1
−
t
)
b
i
,
n
=
n
+
1
−
i
n
+
1
b
i
,
n
+
1
{\displaystyle {n+1 \choose i}(1-t)\mathbf {b} _{i,n}={n \choose i}\mathbf {b} _{i,n+1},\quad (1-t)\mathbf {b} _{i,n}={\frac {n+1-i}{n+1}}\mathbf {b} _{i,n+1}}
(
n
+
1
i
+
1
)
t
b
i
,
n
=
(
n
i
)
b
i
+
1
,
n
+
1
,
t
b
i
,
n
=
i
+
1
n
+
1
b
i
+
1
,
n
+
1
{\displaystyle {n+1 \choose i+1}t\mathbf {b} _{i,n}={n \choose i}\mathbf {b} _{i+1,n+1},\quad t\mathbf {b} _{i,n}={\frac {i+1}{n+1}}\mathbf {b} _{i+1,n+1}}
B
(
t
)
=
(
1
−
t
)
∑
i
=
0
n
b
i
,
n
(
t
)
P
i
+
t
∑
i
=
0
n
b
i
,
n
(
t
)
P
i
=
∑
i
=
0
n
n
+
1
−
i
n
+
1
b
i
,
n
+
1
(
t
)
P
i
+
∑
i
=
0
n
i
+
1
n
+
1
b
i
+
1
,
n
+
1
(
t
)
P
i
=
∑
i
=
0
n
+
1
(
i
n
+
1
P
i
−
1
+
n
+
1
−
i
n
+
1
P
i
)
b
i
,
n
+
1
(
t
)
=
∑
i
=
0
n
+
1
b
i
,
n
+
1
(
t
)
P
′
i
{\displaystyle {\begin{aligned}\mathbf {B} (t)&=(1-t)\sum _{i=0}^{n}\mathbf {b} _{i,n}(t)\mathbf {P} _{i}+t\sum _{i=0}^{n}\mathbf {b} _{i,n}(t)\mathbf {P} _{i}\\&=\sum _{i=0}^{n}{\frac {n+1-i}{n+1}}\mathbf {b} _{i,n+1}(t)\mathbf {P} _{i}+\sum _{i=0}^{n}{\frac {i+1}{n+1}}\mathbf {b} _{i+1,n+1}(t)\mathbf {P} _{i}\\&=\sum _{i=0}^{n+1}\left({\frac {i}{n+1}}\mathbf {P} _{i-1}+{\frac {n+1-i}{n+1}}\mathbf {P} _{i}\right)\mathbf {b} _{i,n+1}(t)=\sum _{i=0}^{n+1}\mathbf {b} _{i,n+1}(t)\mathbf {P'} _{i}\end{aligned}}}
式中
P
−
1
{\displaystyle \mathbf {P} _{-1}}
和
P
n
+
1
{\displaystyle \mathbf {P} _{n+1}}
可以任意挑选。
因此,新的控制点为[ 2]
P
′
i
=
i
n
+
1
P
i
−
1
+
n
+
1
−
i
n
+
1
P
i
,
i
=
0
,
…
,
n
+
1.
{\displaystyle \mathbf {P'} _{i}={\frac {i}{n+1}}\mathbf {P} _{i-1}+{\frac {n+1-i}{n+1}}\mathbf {P} _{i},\quad i=0,\ldots ,n+1.}
由于需要点阵化更精细的分辨率时,重新插值(补点)的计算量较小,贝塞尔曲线被广泛地在电脑图形中用来为平滑曲线建立模型。贝塞尔曲线是矢量图形文件和相应软件(如PostScript、PDF等)能够处理的唯一曲线,用于光滑地近似其他曲线。
二次和三次贝塞尔曲线最为常用。
下列代码为一简单的实际运用示例,展示如何使用C语言 标出三次方贝塞尔曲线。注意,此处仅简单的计算多项式系数,并读尽一系列由0至1的t值;实践中一般不会这么做,递归求解通常会更快速——以更多的存储器为代价,花费较少的处理器时间。不过直接的方法较易于理解并产生相同结果。以下代码已使运算更为清晰。实践中的优化会先计算系数一次,并在实际计算曲线点的循环中反复使用。此处每次都会重新计算,损失了效率,但代码更清楚易读。
曲线的计算可在曲线数组上将相连点画上直线——点越多,曲线越平滑。
在部分架构中,下以代码也可由动态规划 进行优化。举例来说,dt 是一个常量,cx * t 则等同于每次反复就修改一次常量。经反复应用这种优化后,循环可被重写为没有任何乘法(虽然这个过程不是稳定数值 的)。
/*
產生三次方貝茲曲線的程式碼
*/
typedef struct
{
float x ;
float y ;
}
Point2D ;
/*
cp在此是四個元素的陣列:
cp[0]為起始點,或上圖中的P0
cp[1]為第一個控制點,或上圖中的P1
cp[2]為第二個控制點,或上圖中的P2
cp[3]為結束點,或上圖中的P3
t為參數值,0 <= t <= 1
*/
Point2D PointOnCubicBezier ( Point2D * cp , float t )
{
float ax , bx , cx ;
float ay , by , cy ;
float tSquared , tCubed ;
Point2D result ;
/*計算多項式係數*/
cx = 3.0 * ( cp [ 1 ]. x - cp [ 0 ]. x );
bx = 3.0 * ( cp [ 2 ]. x - cp [ 1 ]. x ) - cx ;
ax = cp [ 3 ]. x - cp [ 0 ]. x - cx - bx ;
cy = 3.0 * ( cp [ 1 ]. y - cp [ 0 ]. y );
by = 3.0 * ( cp [ 2 ]. y - cp [ 1 ]. y ) - cy ;
ay = cp [ 3 ]. y - cp [ 0 ]. y - cy - by ;
/*計算位於參數值t的曲線點*/
tSquared = t * t ;
tCubed = tSquared * t ;
result . x = ( ax * tCubed ) + ( bx * tSquared ) + ( cx * t ) + cp [ 0 ]. x ;
result . y = ( ay * tCubed ) + ( by * tSquared ) + ( cy * t ) + cp [ 0 ]. y ;
return result ;
}
/*
ComputeBezier以控制點cp所產生的曲線點,填入Point2D結構的陣列。
呼叫者必須分配足夠的記憶體以供輸出結果,其為<sizeof(Point2D) numberOfPoints>
*/
void ComputeBezier ( Point2D * cp , int numberOfPoints , Point2D * curve )
{
float dt ;
int i ;
dt = 1.0 / ( numberOfPoints - 1 );
for ( i = 0 ; i < numberOfPoints ; i ++ )
curve [ i ] = PointOnCubicBezier ( cp , i * dt );
}
另一种贝塞尔曲线的应用是在动画中,描述对象的运动路径等等。此处,曲线的x、y位置不用来标示曲线,但用来表示图形位置。当用在这种形式时,连续点之间的距离会变的更为重要,且大多不是平均比例。点将会串的更紧密,控制点更接近每一个点,而更为稀疏的控制点会散的更开。如果需要线性运动速度,进一步处理时就需要循所需路径将点平均分散。
有时我们可能想要把贝塞尔曲线表示为多项式 ,而非比较不直接的伯恩斯坦多项式 。使用二项式定理 和贝塞尔曲线的定义,刷新后可以得到:
B
(
t
)
=
∑
j
=
0
n
t
j
C
j
{\displaystyle \mathbf {B} (t)=\sum _{j=0}^{n}{t^{j}\mathbf {C} _{j}}}
此处
C
j
=
n
!
(
n
−
j
)
!
∑
i
=
0
j
(
−
1
)
i
+
j
P
i
i
!
(
j
−
i
)
!
=
∏
m
=
0
j
−
1
(
n
−
m
)
∑
i
=
0
j
(
−
1
)
i
+
j
P
i
i
!
(
j
−
i
)
!
.
{\displaystyle \mathbf {C} _{j}={\frac {n!}{(n-j)!}}\sum _{i=0}^{j}{\frac {(-1)^{i+j}\mathbf {P} _{i}}{i!(j-i)!}}=\prod _{m=0}^{j-1}(n-m)\sum _{i=0}^{j}{\frac {(-1)^{i+j}\mathbf {P} _{i}}{i!(j-i)!}}.}
计算曲在线的点时需要多次计算
B
(
t
)
{\displaystyle \mathbf {B} (t)}
,因此事先计算好
C
j
{\displaystyle \mathbf {C} _{j}}
会比较实际;然而要小心高阶曲线可能会缺乏数值稳定性 (需使用德卡斯特里奥算法 来处理)。注意其空积 为1。
有理贝塞尔曲线的示例
有理贝兹增加可调节的权重,以提供更近似于随意的形状。分子是加权的伯恩斯坦形式贝塞尔曲线,而分母是加权的伯恩斯坦多项式 的总和。
给定n + 1控制点P i ,有理贝塞尔曲线可如下描述:
B
(
t
)
=
∑
i
=
0
n
b
i
,
n
(
t
)
P
i
w
i
∑
i
=
0
n
b
i
,
n
(
t
)
w
i
{\displaystyle \mathbf {B} (t)={\frac {\sum _{i=0}^{n}b_{i,n}(t)\mathbf {P} _{i}w_{i}}{\sum _{i=0}^{n}b_{i,n}(t)w_{i}}}}
或简单的
B
(
t
)
=
∑
i
=
0
n
(
n
i
)
t
i
(
1
−
t
)
n
−
i
P
i
w
i
∑
i
=
0
n
(
n
i
)
t
i
(
1
−
t
)
n
−
i
w
i
{\displaystyle \mathbf {B} (t)={\frac {\sum _{i=0}^{n}{n \choose i}t^{i}(1-t)^{n-i}\mathbf {P} _{i}w_{i}}{\sum _{i=0}^{n}{n \choose i}t^{i}(1-t)^{n-i}w_{i}}}}
德卡斯特里奥算法
样条
贝兹样条
贝兹曲面
贝兹三角
NURBS
string art ,Bézier curves are also formed by many common forms of string art, where strings are looped across a frame of nails.
埃尔米特曲线