一、Bezier曲线的定义
给定n+1个空间向量
P
i
∈
R
3
(
i
=
0
,
1
,
.
.
.
,
n
)
P_i\in R^3 (i= 0,1,...,n)
Pi∈R3(i=0,1,...,n), 称n次参数曲线段
P
(
t
)
=
∑
i
=
0
n
P
i
B
i
n
(
t
)
,
0
≤
t
≤
1.
(
1
)
P(t) = \sum^n_{i=0}P_iB^n_i(t) ,0\leq t \leq1 .(1)
P(t)=i=0∑nPiBin(t),0≤t≤1.(1)
为一条n次Bezier曲线.
P
i
P_i
Pi称为控制顶点,依次用直线段连接相邻的两个
P
i
P_i
Pi所得的n边折线多边形称为Bezier多边形或者控制多边形.
下图为3次Bezier曲线,其中折线为相应的控制多边形.
下面给出matlab代码:
function bezier
%bezier曲线画图
px=[0,1,2,3];
py=[0,4,1,5]; %控制顶点(0,0),(1,4),(2,1),(3,5)
M = 40;
hx = 1/M; %将[0,1]区间M等分
x = (0:hx:1)';
n=length(px)-1;
Px = 0;
Py = 0;
for i = 1:n+1
Px = Px + px(i)*B(x,n,i-1) %将控制顶点与Bernstein基函数相乘得到bezier曲线
Py = Py + py(i)*B(x,n,i-1)
end
plot(Px,Py,'r',px,py,'b')
end
function y = B(x,n,i)
y = k(n,i).*(x.^i).*((1-x).^(n-i));
end
function y = k(n,i)
y1 = factorial(n); %n的阶乘
y2 = factorial(i)*factorial(n-i);
y = y1/y2;
end
二、Bezier曲线的性质
-
几何不变性和仿射不变性. 因为Bernstein基函数满足单位分解性,对Bezier曲线(1)式进行仿射变换,即用线性变换M和平移c作用,得到新的曲线
P ∗ ( t ) = M P ( t ) + c = M ∑ i = 0 n P i B i n ( t ) + c ∑ i = 0 n B i n ( t ) = ∑ i = 0 n M P i B i n ( t ) + ∑ i = 0 n c B i n ( t ) = ∑ i = 0 n P i ∗ B i n ( t ) \ P^*(t) = MP(t)+c = M\sum^{n}_{i = 0}P_iB^{n}_i(t) + c\sum^{n}_{i = 0}B^{n}_i(t) \\= \sum^{n}_{i = 0}MP_iB^{n}_i(t) + \sum^{n}_{i = 0}cB^{n}_i(t) = \sum^n_{i=0}P^*_iB^n_i(t) P∗(t)=MP(t)+c=Mi=0∑nPiBin(t)+ci=0∑nBin(t)=i=0∑nMPiBin(t)+i=0∑ncBin(t)=i=0∑nPi∗Bin(t)
为对原Bezier曲线(1)式的控制顶点 P i P_i Pi进行仿射变换后得到的新的控制顶点 P i ∗ ( i = 0 , 1 , . . . , n ) P^*_i(i=0,1,...,n) Pi∗(i=0,1,...,n)对应的Bezier曲线.这说明,Bezier曲线不依赖于坐标系的选取,是几何不变的. -
凸包性质. 从几何上看,意味着bezier曲线落在了控制多边形的凸包之中。
-
端点性质.
P ( 0 ) = P 0 , P ( 1 ) = P n P(0) = P_0,P(1) = P_n P(0)=P0,P(1)=Pn
P ′ ( 0 ) = n ( P 1 − P 0 ) , P ′ ( 1 ) = n ( P n − P n − 1 ) . P'(0)=n(P_1-P_0),P'(1) = n(P_n-P_{n-1}). P′(0)=n(P1−P0),P′(1)=n(Pn−Pn−1). -
移动n次Bezier曲线(1)式的第i个控制顶点 P i P_i Pi,将对整条曲线产生影响,其中参数为 t = i n t=\frac {i}{n} t=ni的那个点 P ( i n ) P(\frac {i}{n}) P(ni)处的影响最大.这是因为相应的基函数 B i n ( t ) B^n_i(t) Bin(t)在 t = i n t=\frac {i}{n} t=ni达到最大值。
三、Bezier曲线的de Casteljau算法和几何作图法
在构造出一条Bezier曲线之后,常常需要计算曲线上对应某个参数值
t
∗
t^*
t∗的点
P
(
t
∗
)
P(t^*)
P(t∗).数值计算的方法由直接代入参数值即可得到所求点的坐标.借助于Bezier基函数,我们还可以采用几何作图的发放计算Bezier曲线上的点.
由Bernstein基函数的递推性质
B
i
n
(
t
)
=
(
1
−
t
)
B
i
n
−
1
(
t
)
+
t
B
i
−
1
n
−
1
(
t
)
,
B
−
1
n
−
1
(
t
)
=
B
n
n
−
1
(
t
)
=
0
,
i
=
0
,
1
,
.
.
.
,
n
B^n_i(t) = (1-t)B^{n-1}_i(t)+tB^{n-1}_{i-1}(t),\\ \\B^{n-1}_{-1}(t)=B^{n-1}_{n}(t)=0, i=0,1,...,n
Bin(t)=(1−t)Bin−1(t)+tBi−1n−1(t),B−1n−1(t)=Bnn−1(t)=0,i=0,1,...,n
可知
P
(
t
)
=
∑
i
=
0
n
P
i
B
i
n
(
t
)
P(t) = \sum^n_{i=0}P_iB^n_i(t)
P(t)=∑i=0nPiBin(t)
=
P
0
(
1
−
t
)
B
0
n
−
1
(
t
)
+
∑
i
=
0
n
−
1
[
P
i
B
i
n
−
1
(
t
)
+
t
B
i
−
1
n
−
1
(
t
)
]
+
P
n
(
t
)
B
n
−
1
n
−
1
(
t
)
=
(
1
−
t
)
∑
i
=
0
n
−
1
P
i
B
i
n
−
1
(
t
)
+
t
∑
i
=
0
n
−
1
P
i
+
1
B
i
n
−
1
(
t
)
=
∑
i
=
0
n
−
1
[
(
1
−
t
)
P
i
+
t
P
i
+
1
]
B
i
n
−
1
(
t
)
=P_0(1-t)B^{n-1}_0(t)+ \sum^{n-1}_{i=0}[P_iB^{n-1}_i(t)+t B^{n-1}_{i-1}(t)] +P_n(t) B^{n-1}_{n-1}(t) \\=(1-t) \sum^{n-1}_{i=0}P_iB^{n-1}_i(t)+t \sum^{n-1}_{i=0}P_{i+1}B^{n-1}_i(t) \\= \sum^{n-1}_{i=0}[(1-t)P_i+tP_{i+1}] B^{n-1}_i(t)
=P0(1−t)B0n−1(t)+i=0∑n−1[PiBin−1(t)+tBi−1n−1(t)]+Pn(t)Bn−1n−1(t)=(1−t)i=0∑n−1PiBin−1(t)+ti=0∑n−1Pi+1Bin−1(t)=i=0∑n−1[(1−t)Pi+tPi+1]Bin−1(t)
这说明,一条n次Bezier曲线可以表示为分别由前后n个控制顶点决定的两条n-1次Bezier曲线的线性组合.由此可得Bezier曲线上某一点递归求值的 de Casteljau算法
{
P
i
0
(
t
)
≡
P
i
0
=
P
i
,
i
=
0.1....
,
n
,
P
i
r
(
t
)
=
(
1
−
t
)
P
i
r
−
1
(
t
)
+
t
P
i
+
1
r
−
1
(
t
)
,
r
=
0
,
1
,
.
.
.
,
n
,
i
=
0.1....
,
n
−
r
.
\begin{cases}P^0_i(t)\equiv P^0_i =P_i,i = 0.1....,n, \\ P^r_i(t) = (1-t)P^{r-1}_i(t)+tP^{r-1}_{i+1}(t) , \\ r=0,1,...,n ,i = 0.1....,n-r. \end{cases}
⎩⎪⎨⎪⎧Pi0(t)≡Pi0=Pi,i=0.1....,n,Pir(t)=(1−t)Pir−1(t)+tPi+1r−1(t),r=0,1,...,n,i=0.1....,n−r.
于是
P
(
t
)
=
∑
i
=
0
n
−
1
P
i
1
B
i
n
−
1
(
t
)
=
.
.
.
=
∑
i
=
0
n
−
r
P
i
r
B
i
n
−
r
(
t
)
=
.
.
.
=
P
0
n
(
t
)
,
P(t) = \sum^{n-1}_{i=0}P^1_iB^{n-1}_i(t)=... = \sum^{n-r}_{i=0}P^r_iB^{n-r}_i(t)=... =P^n_0(t),
P(t)=i=0∑n−1Pi1Bin−1(t)=...=i=0∑n−rPirBin−r(t)=...=P0n(t),
P
0
n
(
t
)
P^n_0(t)
P0n(t)即为所求的
P
(
t
)
P(t)
P(t).若记
P
0
=
(
P
0
,
P
1
,
⋯
,
P
n
)
T
,
P
r
(
t
)
=
(
P
0
r
,
P
1
r
,
⋯
,
P
n
−
r
r
)
T
P^0=(P_0,P_1,\cdots,P_n)^T,P^r(t)= (P_0^r,P_1^r,\cdots,P_{n-r}^r)^T
P0=(P0,P1,⋯,Pn)T,Pr(t)=(P0r,P1r,⋯,Pn−rr)T,则可以把de Castaljau算法表示为
P
r
(
t
)
=
M
r
(
t
)
⋯
M
2
(
t
)
M
1
(
t
)
P
0
,
P^r(t)= M_r(t) \cdots M_2(t)M_1(t)P^0,
Pr(t)=Mr(t)⋯M2(t)M1(t)P0,
其中
M
r
(
t
)
=
(
1
−
t
t
0
⋯
0
0
0
1
−
t
t
⋯
0
0
⋮
⋮
⋮
⋱
⋮
⋮
0
0
⋯
1
−
t
t
0
0
0
⋯
0
1
−
t
0
)
M_r(t)=\begin{pmatrix} 1-t & t & 0 & \cdots & 0 & 0 \\ 0 & 1-t & t & \cdots & 0 & 0 \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & 1-t & t & 0 \\ 0 & 0 & \cdots & 0 &1-t & 0 \\ \end{pmatrix}
Mr(t)=⎝⎜⎜⎜⎜⎜⎛1−t0⋮00t1−t⋮000t⋮⋯⋯⋯⋯⋱1−t000⋮t1−t00⋮00⎠⎟⎟⎟⎟⎟⎞
是一个
(
n
−
r
+
1
)
×
(
n
−
r
+
2
)
(n-r+1) \times (n-r+2)
(n−r+1)×(n−r+2)阶矩阵.
四、de Casteljau算法的matlab程序实现:
px=[0,1,2,3];
py=[0,4,1,5]; %控制顶点(0,0),(1,4),(2,1),(3,5)
M=100; %将[0,1]区间M等分
hx = 1/M; %每个小区间长度
n=length(px)-1;
xx=[];yy=[];
for x = 0:hx:1
xx1 = px';
yy1 = py';
for i = 1:n
M(i,i) = 1-x;
M(i,i+1) = x; %生成迭代矩阵
end
for i = 1:n
M = M(1:n+1-i,1:n+2-i);
xx1 = M*xx1;
yy1 = M*yy1;
end
xx(end+1)=xx1(1); %xx存储曲线的横坐标
yy(end+1)=yy1(1); %yy存储曲线的纵坐标
end
plot(xx,yy,px,py,px,py,'b*');
hold on;
%以下是当x = 0.3时的具体实现
xx1 = px';
yy1 = py';
x = 0.3;
for i = 1:n
M(i,i) = 1-x;
M(i,i+1) = x;
end
for i = 1:n
M = M(1:n+1-i,1:n+2-i);
xx1 = M*xx1;
yy1 = M*yy1;
plot(xx1,yy1,xx1,yy1,'o');hold on %将每一步得到的结果画出来
end
程序结果如下:
接下来附上我第一次上课时交的编程作业(傻乎乎的程序):
px=[0,1,2,3];py=[0,4,1,5];
A=[px;py];N=size(A,2)-1;
x=zeros(1,N+1);y=zeros(1,N+1);
xx=[];yy=[];
for t=0:0.001:1;
for i=1:N
for j=0:N-i
if i==1
x(j+1) = (1 - t)*A(1,j+1) + t*A(1,j+2);
y(j+1) = (1 - t)*A(2,j+1) + t*A(2,j+2);
continue;
end
x(j+1) = x(j+1) * (1 - t) + x(j + 2) * t;
y(j+1) = y(j+1) * (1 - t) + y(j + 2) * t;
end
end
xx(end+1)=x(1);
yy(end+1)=y(1);
end
plot(A(1,:),A(2,:),'mo',A(1,:),A(2,:),'b','linewidth',2);
hold on;grid on;
axis tight;
plot(xx,yy,'r','linewidth',2);
hold on;
t=0.3;
for j=0:N-1
x(j+1) = (1 - t)*A(1,j+1) + t*A(1,j+2);
y(j+1) = (1 - t)*A(2,j+1) + t*A(2,j+2);
plot(x(j+1),y(j+1),'-go','linewidth',2);hold on;
end
plot(x(1:N),y(1:N),'k-','linewidth',2);hold on;
for j=0:N-2
x(j+1) = x(j+1) * (1 - t) + x(j + 2) * t;
y(j+1) = y(j+1) * (1 - t) + y(j + 2) * t;
plot(x(j+1),y(j+1),'-co','linewidth',2);hold on;
end
plot(x(1:N-1),y(1:N-1),'g-','linewidth',2);hold on;
for j=0:N-3
x(j+1) = x(j+1) * (1 - t) + x(j + 2) * t;
y(j+1) = y(j+1) * (1 - t) + y(j + 2) * t;
plot(x(j+1),y(j+1),'-ko','linewidth',2);hold on;
end
程序结果为: