通过给定一组数据点并反求控制点的NURBS曲线插值生成Matlab编程实例

0.引言

非均匀有理B样条(NURBS)是几何造型的一个十分有用的工具,以其良好的特性越来越受到工程界的重视。它可以用统一的数学形式表示规则曲面与自由曲面;有操纵控制顶点及权因子,为各种形状设计提供了充分的灵活性,有强有力的几何配套技术,能用于设计、分析与处理等各个环节,是非有理B样条形式以及有理、非有理贝塞尔形式良好的推广。NURBS方法已成为IGES标准、STEP标准中描述产品几何形状的唯一方法。
NURBS曲线曲面在实际应用中可以分为两种形式:一种是已知控制点求解曲线曲面上的点,称为正算问题。另一种情况是已知曲线曲面上一组数据点,即型值点,求解曲线曲面的控制点,称为反算问题。在实际应用中,常常是给出一组离散的型值点,要求构造通过该型值点的曲线曲面,即所谓的曲线曲面插值。

1.NURBS曲线方程

NURBS曲线方程的表达式,有理分式表达:

式中:
在这里插入图片描述

其中, w i w_i wi ( i i i=0,1,…,n)称为权或者权因子,分别与控制顶点 d i ( i = 0 , 1 , . . . . . , n ) d_i(i=0,1,.....,n) di(i=0,1,.....,n)相对应。首末权因子 w 0 w_0 w0 w n > 0 w_n > 0 wn>0,其余 w i ≥ 0 w_i \ge 0 wi0 ,并且连续 k k k个权因子不能同时为零。顺序连接 d i d_i di形成控制多边形。 N i , k ( u ) {N}_{i,k}(u) Ni,k(u)是由节点矢量 U = [ u 0 , u 1 , … , u n + k + 1 ] U=[u_0,u_1,\ldots,u_{n+k+1}] U=[u0,u1,,un+k+1] 计算确定的 k k k次规范 B 样条基函数, i i i表示序号, k k k是样条阶数, k = 3 k=3 k=3,即是三次曲线,。对于NURBS 曲线首尾数据点不相连的,也就是开曲线,通常取两端节点的重复度为 r = k + 1 r=k +1 r=k+1,即 u 0 = u 1 = … = u k u_0=u_{1}=\ldots =u_k u0=u1==uk u n + 1 = u n + 2 = … = u n + k + 1 u_{n+1}=u_{n+2}=\ldots =u_{n+k+1} un+1=un+2==un+k+1 。在很多实际应用中,端节点值常取0、1,故NURBS 曲线的定义域可表示为 u ∈ [ u k , u n + 1 ] ⊂ [ 0 , 1 ] u\in[u_k,u_{n+1}]\subset [0,1] u[uk,un+1][0,1] 。由此可得,当 n = k n = k n=k时, k k k次NURBS 曲线即退化为 k k k次有理Bézier 曲线,其节点矢量与同次有理Bézier 曲线的端点具有相同的几何性质。若首末权因子均不为零,即子 w 1 , w n > 0 w_1,w_n > 0 w1wn>0,则曲线首末端点分别与控制多边形首末顶点重合,同时曲线在该点处与控制多边形首末边相切。

2.NURBS曲线插值生成

给定一组数据点,即型值点,生成通过这些型值点的的NURBS曲线,称为曲线的反算,一般包括三个步骤:(1)计算节点矢量;(2)计算边界条件;(3)反算控制顶点。

2.1 计算节点矢量

若要让一条 K K K次NURBS 曲线通过一组给定的型值点 P i ( i = 0 , 1 , . . . . . , n ) P_i(i=0,1,.....,n) Pi(i=0,1,.....,n),不仅要保证曲线的首末端点与型值点重合, 还应保证 P i P_i Pi依次与构造曲线定义域内的节点 u i + k ( i = 0 , 1 , . . . . . , n ) u_{i+k}(i=0,1,.....,n) ui+k(i=0,1,.....,n)一一对应。通常需要对型值点进行参数化处理,以确定型值点 P i P_i Pi的参数值 u i + k ( i = 0 , 1 , . . . . . , n ) u_{i+k}(i=0,1,.....,n) ui+k(i=0,1,.....,n)。具有 n + 1 n+1 n+1个型值点 P i P_i Pi k k k次NURBS曲线将由 n + 3 n+3 n+3个控制顶点 D i ( i = 0 , 1 , . . . . . , n , n + 1 , n + 2 ) D_i(i=0,1,.....,n,n+1,n+2) Di(i=0,1,.....,n,n+1,n+2)及其权因子 w i w_i wi以及节点矢量 U = [ u 0 , u 1 , … , u n + k + 3 ] U=[u_0,u_1,\ldots,u_{n+k+3}] U=[u0,u1,,un+k+3]定义。节点矢量最后的下标是 n + k + 3 n+k+3 n+k+3,是因为节点的数量要比控制顶点的数量多重复度 r = k + 1 r=k +1 r=k+1个,而控制顶点数量比型值点数量多2个,所以节点矢量最后下标是 = n + 2 + k + 1 = n + k + 3 =n+2+k+1=n+k+3 =n+2+k+1=n+k+3 n + 1 n+1 n+1个型值点,下标从0开始, n n n结束)。首末节点的重复度 r = k + 1 r=k +1 r=k+1。前 k + 1 k+1 k+1个节点取值为0,后 k + 1 k+1 k+1个节点取值为1。
引入符号 △ \bigtriangleup ,将每个节点区间长度表示为: △ i = u i + 1 − u i \bigtriangleup_i=u_{i+1}-u_i i=ui+1ui。常用的参数化方法有以下几种,以三次曲线( k = 3 k=3 k=3)为例:
(1)均匀参数化法
使节点在参数轴上呈现等距离分布,也就是应用向前差分表示每个节点区间的长度,即 △ i = u i + 1 − u i = \bigtriangleup_i=u_{i+1}-u_i= i=ui+1ui=正常数,为保证节点矢量在[0,1]的范围内,对节点规范化处理,保证 [ u 0 , u n ] = [ 0 , 1 ] [u_0,u_n]=[0,1] [u0,un]=[0,1],具体的参数化方法为:
在这里插入图片描述
这种均匀参数化方法适用的类型仅为给定数据点的多边形各边(或弦长)接近相等的情形,具有一定的局限性。
(2)积累弦长参数化法
该方法克服了均匀参数化法的弊端,如若遇到数据点多边形各弦长分布不均匀时,应用该方法可以避免均匀参数化法出现的问题,并如实地表现出数据点依据多边形各弦长的分布情形,且能得到光顺性较好的插值曲线,是最常采用的参数化方法,该参数化方法满足:
在这里插入图片描述
(3)向心参数化法
这种参数化方法如实反映了数据点相邻弦线的折拐情况。
在这里插入图片描述
(4)修正弦长参数化法
这种参数化方法对绝对曲率较大,与实际弧长相比弦长又偏短的曲线段起到了修正的作用,且生成的插值曲线具有较好的光顺性。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 边界条件的确定

下式表示的线性方程组由 n + 1 n +1 n+1个矢量方程组成,具有 n + 3 个 n +3个 n+3未知控制顶点,上述方程组中的节点矢量 U = [ u 0 , u 1 , … , u n + k + 3 ] U=[u_0,u_1,\ldots,u_{n+k+3}] U=[u0,u1,,un+k+3]已确定,但未知顶点数大于方程数,因此求解该方程组,需要增加两个适当的边界条件,而常用的边界条件有:(1)切矢条件;(2)自由端点条件;(3)闭曲线条件。常采用切矢条件。以三次曲线( k = 3 k=3 k=3)为例进行说明。在这里插入图片描述
(1)切矢条件
要求首末端点的切线方向固定:
在这里插入图片描述
式中: △ i = u i + 1 − u i \bigtriangleup_i=u_{i+1}-u_i i=ui+1ui P 0 ′ P^{'}_0 P0 P n ′ P^{'}_n Pn为首末端点切矢。
(2)自由端点条件
自由端点条件要求首末端点具有零曲率:
在这里插入图片描述
(3)闭曲线条件
要求曲线首末端点重合且二阶连续:在这里插入图片描述

2.3 控制顶点的反算

1、对于 c 2 c^2 c2 连续的NURBS 三次闭曲线,由于其首末数据点相重, n − 1 n-1 n1 个方程足以求出 n + 1 n+1 n+1个控制顶点,所以NURBS 三次闭曲线控制顶点反算的矩阵表达式为:
在这里插入图片描述
式中: d i d_i di为控制顶点, △ i = u i + 1 − u i ( i = 0 , 1 , … , n − 2 ) \bigtriangleup_i=u_{i+1}-u_i (i=0,1,\ldots,n-2) i=ui+1ui(i=0,1,,n2)
2、对于NURBS 三次开曲线,则还需要添加两个边界条件满足的附加方程。NURBS 三次开曲线两端点的重复度取4,所以NURBS 三次曲线的首末控制顶点就是其首末端的型值点,即: d 0 = P 0 d_0=P_0 d0=P0 d n + 2 = P n d_{n+2}=P_n dn+2=Pn 。边界条件以切矢条件为例,应用矩阵的形式给出NURBS 三次开曲线控制顶点反算的表达式:
在这里插入图片描述
式中: d i d_i di为控制顶点, △ i = u i + 1 − u i ( i = 0 , 1 , … , n ) \bigtriangleup_i=u_{i+1}-u_i (i=0,1,\ldots,n) i=ui+1ui(i=0,1,,n),则:
在这里插入图片描述

在这里插入图片描述
求解上述线性方程组,即可得到所有未知的控制顶点。根据要求选取合适的权因子,即可最终确定NURBS 曲线的表达式。

3 Matlab编程实例

本程序既适用于二维平面曲线,也适用于三维空间曲线,且有良好的鲁棒性。
data1.txt

0	0  
3	11 
21	17 
26	6  
32	1  
60	13 
50	23 
70  28 
75  35 

data2.txt

0	0  0
3	11 1
21	17 2
26	6  3
32	1  10
60	13 11
50	23 15
70  28 20
75  35 25
% 给定一组数据点,即型值点,反求其控制顶点,并构造通过这些型值点的2D或3D nurbs曲线,首末型值点与控制顶点重合,称为nurbs曲线插值
% 具有n个型值点的k次nurbs插值曲线,将有n+2个未知控制顶点,首末节点取重复度r=k+1,从而具有n+2+k+1个节点
% 三次Nurbs曲线的首末节点取重复度r=k+1=4,u1=u2=u3=u4=0,Un+3=Un+4=Un+5=Un+6=1
clear
pt=load('data2.txt'); 
[row,column]=size(pt);  %每行代表一个型值点,采用列向量表示x,y,z坐标,便于线性方程组求解
n=length(pt);  %型值点数量
k=3;  %样条阶数
U=zeros(1,n+k+3);  %节点矢量
%第一步:计算节点矢量********************
if(column == 2)   % 2D curve
    x=pt(:,1);
    y=pt(:,2);
else              % 3D curve
    x=pt(:,1);
    y=pt(:,2);
    z=pt(:,3);
end

%n个数据点,利用规范积累弦长法进行型值点参数化处理
temp=zeros(1,n-1);
for i=1:n-1  %n个数据点,n-1段弦长
   if(column == 2)    % 2D curve
   temp(i)=sqrt((x(i+1)-x(i))^2+(y(i+1)-y(i))^2);
   else               % 3D curve
   temp(i)=sqrt((x(i+1)-x(i))^2+(y(i+1)-y(i))^2+(z(i+1)-z(i))^2);
   end
end
sumtemp=sum(temp);%顺序相邻两型值点之间距离的和,即总弦长
for i=1:k+1      %前k+1个节点为0
    U(i)=0;
end
for i=n+k:n+k+3  %后k+1个节点为1
    U(i)=1;
end
 %n个数据点,内节点为n-2个,U(k+1)作为初始值
for i=k+1:n+k-2
    U(i+1)=U(i)+temp(i-k)/sumtemp;  %n-1段弦长,U(k+1)到U(n+k)共n个节点
end

%第二步:反算n+2个控制点,采用切矢边界*****************************
%控制顶点的首末端点和给定型值点的首末端点重合
if(column == 2)
    dpt1=[0 1];%给定首数据点切矢
    dptn=[-1 0];%给定末数据点切矢
else
    dpt1=[0 0 1];%给定首数据点切矢
    dptn=[-1 0 0];%给定末数据点切矢
end
dU=zeros(1,n+k+3);  %节点增量,△U=Ui+1-Ui
for i=k+1:n+k-1
    dU(i)=U(i+1)-U(i);
end

%求解线性方程组获得控制顶点向量,A*D=E,A为系数矩阵,元素为B样条基函数的值;D是控制顶点列向量;E是列向量
A=zeros(n);
if(column == 2)
    E=zeros(n,2);  %2D curve
else
    E=zeros(n,3);  %3D curve
end
A(1,1)=1;  %切矢条件a1=1,b1=c1=0
A(n,n)=1;  %切矢条件an=bn=0,cn=1
E(1,:)=pt(1,:)+(dU(4)/3)*dpt1;    %首端点条件
E(n,:)=pt(n,:)-(dU(n+2)/3)*dptn;  %末端点条件
%计算系数矩阵A的元素a,b,c以及列向量E的元素e的值
for i=2:n-1  
    A(i,i-1)=dU(i+3).^2/(dU(i+1)+dU(i+2)+dU(i+3));                  %a的值
    A(i,i)=dU(i+3)*(dU(i+1)+dU(i+2))/(dU(i+1)+dU(i+2)+dU(i+3))+...  %b的值
        dU(i+2)*(dU(i+3)+dU(i+4))/(dU(i+2)+dU(i+3)+dU(i+4));
    A(i,i+1)=dU(i+2).^2/(dU(i+2)+dU(i+3)+dU(i+4));                  %c的值
    E(i,:)=(dU(i+2)+dU(i+3))*pt(i,:);                               %e的值
end
D=A\E;  %解方程组,获得去除首末端点的控制顶点向量
D=[pt(1,:);D;pt(n,:)]; %控制顶点向量,控制顶点比数据点多两个,加上首末端点
[s,t]=size(D);  %s:控制点数量

%第三步:求出Nurbs曲线*****************************
dt=0.001;  %Nurbs曲线插值密度,dt越小,越光滑
P=[];      %Nurbs曲线
syms dx;   %定义节点间的递增变量为变量dx
for i=k+1:s
    u=U;
    d=sym(D);
    %每次迭代后将d恢复初值
    for m=1:k
        for j=i-k:i-m
            alpha(j)=(dx-u(j+m))/(u(j+k+1)-u(j+m));
            d(j,:)=(1-alpha(j))*d(j,:)+alpha(j)*d(j+1,:);
        end
    end
    %带入变量dx求出各节点区间[ui,ui+1]内m=3的控制点d
    M=subs(d(i-k,:),dx,(u(i):dt:(u(i+1)-dt))');    %节点区间内的插值点替换dx
    P=[P;double(M)];
end
M=subs(d(s-k,:),dx,1);
P=[P;double(M)];%补上最后一个点

%第四步、绘制给定型值点、控制点及其Nurbs曲线*****************************
if(column == 2)  %2D curve
    plot(pt(:,1),pt(:,2),'*r');  %绘制型值点
    hold on;
    plot(D(:,1),D(:,2),'b-o');   %绘制控制点
    hold on;
    plot(P(:,1),P(:,2),'r');     %绘制nurbs曲线
    hold on;  
else             %3D curve
    plot3(pt(:,1),pt(:,2),pt(:,3),'*r'); %绘制型值点
    hold on;
    plot3(D(:,1),D(:,2),D(:,3),'b-o');   %绘制控制点
    hold on;
    plot3(P(:,1),P(:,2),P(:,3),'r');     %绘制nurbs曲线
    hold on;
end
axis equal;
grid on;

二维NURBS曲线插值:
在这里插入图片描述
三维NURBS曲线插值:
在这里插入图片描述

4 优化效率

上述程序在反求出控制点节点矢量后,进行NURBS曲线生成时的效率较低,如果数据点过多,会十分影响运行速度,为此可以调用外部库函数提高NURBS曲线生成效率。这里使用的是 D.M. Spink提供的NURBS Toolbox,里面有大量的关于NURBS的函数。

%nurbs_toolbox库调用实例
%注释掉程序第三步的求解nurbs曲线的代码,运行以下代码,并修改第四步代码,使用nurbs_toolbox库函数绘制nurbs曲线函数
%使用nurbs_toolbox库函数nrbmak(coefs,knots)生成nurbs曲线,coefs是控制点向量;knots是节点向量
pts=[D(:,1)';D(:,2)';D(:,3)'];%nrbmak函数采用的行向量存储x,y,z坐标,上述程序是采用列向量存储x,y,z坐标,在此进行转换
crv=nrbmak(pts,U);
nrbplot(crv,1000);  %第二个参数是插值点的数量,值越大,则nurbs曲线越光滑

%第四步、绘制给定型值点、控制点及其Nurbs曲线*****************************
if(column == 2)  %2D curve
    plot(pt(:,1),pt(:,2),'*r');  %绘制型值点
    hold on;
    plot(D(:,1),D(:,2),'b-o');   %绘制控制点
    hold on;
%     plot(P(:,1),P(:,2),'r');     %绘制nurbs曲线
    nrbplot(crv,1000);    %使用nurbs_toolbox库函数绘制nurbs曲线
    hold on;  
else             %3D curve
    plot3(pt(:,1),pt(:,2),pt(:,3),'*r'); %绘制型值点
    hold on;
    plot3(D(:,1),D(:,2),D(:,3),'b-o');   %绘制控制点
    hold on;
%     plot3(P(:,1),P(:,2),P(:,3),'r');     %绘制nurbs曲线
    nrbplot(crv,1000);    %使用nurbs_toolbox库函数绘制nurbs曲线
    hold on;
end

参考文献

1、Piegl L, Tiller W. The NURBS book[M]. 2nd ed. Berlin Heidelberg: Springer-Verlag,1997
2、叶丽, 谢明红. 采用用积累弦长法拟合3次NURBS曲线[J]. 华侨大学学报(自然科学版), 2010, 31(4): 383-387
3、彭小军. 曲线曲面的NURBS 造型技术与数控仿真[D]. 西安: 长安大学, 2013

评论 68
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值