Bezier曲线及其de casteljau算法 matlab实现

一、Bezier曲线的定义

      给定n+1个空间向量 P i ∈ R 3 ( i = 0 , 1 , . . . , n ) P_i\in R^3 (i= 0,1,...,n) PiR3(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=0nPiBin(t),0t1.1

为一条n次Bezier曲线. P i P_i Pi称为控制顶点,依次用直线段连接相邻的两个 P i P_i Pi所得的n边折线多边形称为Bezier多边形或者控制多边形.
      下图为3次Bezier曲线,其中折线为相应的控制多边形.
n=3
下面给出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曲线的性质

  1. 几何不变性和仿射不变性. 因为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=0nPiBin(t)+ci=0nBin(t)=i=0nMPiBin(t)+i=0ncBin(t)=i=0nPiBin(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曲线不依赖于坐标系的选取,是几何不变的.

  2. 凸包性质. 从几何上看,意味着bezier曲线落在了控制多边形的凸包之中。

  3. 端点性质.
    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(P1P0),P(1)=n(PnPn1).

  4. 移动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)=(1t)Bin1(t)+tBi1n1(t),B1n1(t)=Bnn1(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(1t)B0n1(t)+i=0n1[PiBin1(t)+tBi1n1(t)]+Pn(t)Bn1n1(t)=(1t)i=0n1PiBin1(t)+ti=0n1Pi+1Bin1(t)=i=0n1[(1t)Pi+tPi+1]Bin1(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)=(1t)Pir1(t)+tPi+1r1(t),r=0,1,...,n,i=0.1....,nr.
于是
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=0n1Pi1Bin1(t)=...=i=0nrPirBinr(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,,Pnrr)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)=1t000t1t000t1t000t1t0000
是一个 ( n − r + 1 ) × ( n − r + 2 ) (n-r+1) \times (n-r+2) (nr+1)×(nr+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

程序结果为:
在这里插入图片描述
在这里插入图片描述

五、参考文献:计算几何教程;王仁宏,李崇军,朱春钢编著

  • 11
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值