第5 章 样条曲面 曲线与曲面是计算机图形学中重要的研究对象,是计算机绘图与动画技术的核心 要素。在 计算机中,可以用离散的点来描述曲线曲面,也可以用直线段或者小平面片拼接在 一起表示曲线曲面。平面曲线可以用一个一维数组描述,数组下标作为横坐标,数组元素 的值作为纵坐标;空间曲线可以用三个一维数组描述,每个数组分别为X 、Y、Z 值,这便 是参数方程表示方法;曲面可以用三维数组表示,也可以用一些三角形或者四边形的顶点 数组表示。 5.1 三维空间样条曲线 在第2章中介绍了二维贝塞尔曲线等,现在讨论三维空间的样条曲线,主要介绍贝塞 尔曲线与B样条曲线。 5.1.1 三维空间贝塞尔曲线 第2章中介绍的各种曲线都可以扩展到三维空间中来。例如,2.3节中的式2-8表示 的曲线是平面贝塞尔曲线,如果增加一个表达式,如式5-1所示,那么就表示三维空间中 的贝塞尔曲线。 x(t)=Σn i=0 xiBi,n(t) y(t)=Σn i=0 yiBi,n(t) z(t)=Σn i=0 ziBi,n(t) ì . í .... .... (5-1) 式5-1中的n 就是曲线的次数,当n=3时,式5-1就表示空间三次贝塞尔曲线。 Bi,n(t)=Ci nti (1-t)n-i是伯恩斯坦多项式,这与二维情形相同。 式2-12是平面贝塞尔曲线的通用矩阵表示形式,在三维空间中,这个表示形式不变, 只是P(t)= x(t) y(t) z(t) é . êêêê ù . úúúú ,P0=(x0,y0,z0),…,P3=(x3,y3,z3)。 例如,当P[3][4]={{1 2 5 6},{1.5 7 11 5},{2 3 6 5.5}},即4个控制 164 计算机图形学(VC++实现)(第 3 版) 点依次是(1,5,2),(2,7,3),(5,6),(6,5,5)时,其三维空间中的贝塞尔曲线如 图5-1所示。 1.11,5. 图5- 1 空间三次贝塞尔曲线 空间贝塞尔曲线的两个端点即是两端的控制点,其他控制点用来控制曲线的形状,图 5-1中有4个控制点,生成的贝塞尔曲线是三次贝塞尔曲线。 t),t),t)], 与空间三次贝塞尔曲线类似,让式217 中的P(=[x(y(就可以表 示空间三次B样条曲线段。 -t)z( 上面介绍的各种曲线本质上都是多项式曲线,只因为给定的初始条件不同,或者曲线 对控制点的要求不同,所以产生了区别。一个曲线的多种参数方程是可以互相转换的。 5.1.2 曲线的拼接 两条曲线端点处的函数值决定是否能实现拼接,函数值相同才可以拼接到一起。如 果端点处的切线斜率(一阶导数)也相同就可以实现平滑连接,没有折起的棱角。有时根 据具体问题,要求连接时函数值相同、一阶导数相同、二阶导数也相同,如果是三维空间曲 线连接,还要求导数的方向也相同,这是一种更高要求的连接。 2.2节中的Hermte曲线给出了端点坐标值以及端点处的切向量,所以该方法绘制 4.i 的曲线容易实现平滑连接。 如果两段贝塞尔曲线要实现光滑连接(一阶导数相同), 那么需要满足一定的条件。 下面的例题研究的是两段三次贝塞尔曲线连接问题。 【例5-1】给定4个控制点P1、P2、P3、P4,绘制出的三次贝塞尔曲线记为C1,再根 据另外4个控制点P4、P5、P6、P7 可以绘制出三次贝塞尔曲线C2。问这7个顶点满足 什么条件时两条曲线在P4 点光滑连接(导数相等)? 由贝塞尔曲线的性质:贝塞尔曲线起点处切线与终点处切线分别是特征多边形的第 一条边和最后一条边所在直线。所以,当P3、P4、P5 在一条直线上时,两条空间三次贝 塞尔曲线在P4 点光滑连接。 第5 章 样条曲面1 65 5.1.3 三维空间B 样条曲线 B样条曲线也属于一种由基函数乘以系数构造的参数曲线,其基函数与贝塞尔曲线 不同,所以具有不同的性质。 【例5-2】 给定4个控制点P1、P2、P3、P4 绘制出的三次B 样条曲线段记为C1;再 给定一点P5,绘制出由P2、P3、P4、P5 控制的三次B样条曲线段记为C2,观察曲线段C1 与C2 的关系。 三次B样条曲线的基函数如下。 F0,3(t)=16 (-t3 +3t2 -3t+1) F1,3(t)=16 (3t3 -6t2 +4) F2,3(t)=16 (-3t3 +3t2 +3t+1) F3,3(t)=16 t3 三次B样条曲线段的参数方程如下。 x(t)=F0,3(t)x0 +F1,3(t)x1 +F2,3(t)x2 +F3,3(t)x3 y(t)=F0,3(t)y0 +F1,3(t)y1 +F2,3(t)y2 +F3,3(t)y3 z(t)=F0,3(t)z0 +F1,3(t)z1 +F2,3(t)z2 +F3,3(t)z3 ì . í .. .. 建立单文档项目,在视图文件中OnDraw()函数的前面写入函数Draw3()如下。 void Draw3(float k[4][3],int color,CDC *p) { float x,y,z; float f3t[4],kk[4][3]={0}; for(int i=0;i<4;i++) for(int j=0;j<3;j++) kk[i][j]=k[i][j]; for(float t=0;t<1;t=t+0.001) { f3t[0]=1/6.0*(-pow(t,3)+3*pow(t,2)-3*t+1); f3t[1]=1/6.0*(3*pow(t,3)-6*pow(t,2)+4); f3t[2]=1/6.0*(-3*pow(t,3)+3*pow(t,2)+3*t+1); f3t[3]=1/6.0*pow(t,3); x=f3t[0]*kk[0][0]+f3t[1]*kk[1][0]+f3t[2]*kk[2][0]+f3t[3]*kk[3][0]; y=f3t[0]*kk[0][1]+f3t[1]*kk[1][1]+f3t[2]*kk[2][1]+f3t[3]*kk[3][1]; z=f3t[0]*kk[0][2]+f3t[1]*kk[1][2]+f3t[2]*kk[2][2]+f3t[3]*kk[3][2]; p->SetPixel((int)x+100,(int)y+100,color); } } 1 66 计算机图形学(VC++ 实现)(第3 版) 在OnDraw()函数中写入调用函数Draw3()的代码,写入后OnDraw()函数的代码 如下(其中粗体是加入的语句)。 void CBbbView::OnDraw(CDC* pDC) { CBbbDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //TODO: add draw code for native data here Float xyz1[4][3]={{20,100,110},{70,120,10},{200,60,20},{250,20,160}}; Draw3(xyz1,0,pDC); Float xyz2[4][3]={{70,120,10},{200,60,20},{250,20,160},{150,16,178}}; Draw3(xyz2,0,pDC); } 编译运行,绘制出如图5-2(a)所示的投影图形。 把语句 p->SetPixel((int)x+100,(int)y+100,color) 修改为: p->SetPixel((int)x+100,(int)z+100,color) 绘制出如图5-2(b)所示的投影图形。 把这个语句再修改为: p->SetPixel((int)y+100,(int)z+100,color) 绘制出如图5-2(c)所示的投影图形。 图5-2 三次B样条曲线在三个坐标轴上的投影(0<t<1) 该程序绘制的曲线是三维空间中的曲线,在三个坐标平面上的投影都是样条曲线。 本来是绘制两段曲线,但是这两段曲线(“无缝地”)连接在一起了。 为了更好地观察连接情况,把语句 for(float t=0;t<1;t=t+0.001) 修改为 第5 章 样条曲面1 67 for(float t=-1;t<1;t=t+0.001) 结果绘制出的对应各个坐标平面的投影图形如图5-3所示。从图上可以看到两段不 同的曲线在某个点处光滑的连接过渡情形。 图5-3 三次B样条曲线在三个坐标轴上的投影(-1<t<1) 【注】 该例题的坐标系是VC++ 默认的坐标系,左上角为(0,0)点,横轴正方向向 右,纵轴正方向向下。 【思考题】 在例5-2给出的条件下,为什么两个B样条曲线段能够实现光滑连接? 参数t 的范围为什么限制在0~1就可以无缝光滑连接? 与贝塞尔曲面类似,绘制B样条曲线也有快速算法。正是因为有快速绘制方法,所 以这类曲线曲面才在图形绘制中被广泛使用。 5.1.4 三维空间分段插值曲线 给定三维空间中的一些离散点,然后求(或者绘制)满足一定条件的一条曲线,使得该 曲线过这些离散点,这就是三维空间曲线插值问题。 与贝塞尔曲线以及B样条曲线不同的是,插值曲线必须过插值点。 给定三维插值点后,实现三维空间曲线插值有很多方法,其中,三次样条插值是比较 常用的一种方法。 下面以一个具体例子说明三维空间中的三次样条插值问题。 给定5个点(1,1,1),(2,2,3),(3,6,5),(6,3,2),(9,6,1),求三维空间内顺次经过这5 个点的两段三次样条插值曲线,使得在(3,6,5)点连续并且在该点的一阶导数与二阶导数相 等,在点(1,1,1)处斜率向量为(-1,-1,-1),在点(9,6,1)处的斜率向量为(1,1,1)。 空间曲线可以视为两个曲面的交线,由式5-2确定,也可以由式5-3参数方程确定。 F1(x,y,z)=0 F2(x,y,z)=0 { (5-2) x =x(t) y =y(t) z =z(t) ì . í .. .. (5-3) 1 68 计算机图形学(VC++ 实现)(第3 版) 所谓切向量,如果使用式5-3,就是指dx dt,dy dt,dz dt . è . . . ÷ 。 对于上面的三维空间三次样条插值问题,使用待定系数法可以计算出三次样条插值 曲线(段)。 5.2 贝塞尔曲面 在图形学中,贝塞尔曲面是常用的曲面之一。在前面绘制曲面的过程中,使用了方 程进行绘制。对于计算机图形学中的一些曲面,例如贝塞尔曲面也有参数方程,可以 使用方程绘制。不过,贝塞尔曲面以及B样条曲面除了可以使用方程绘制外,还可以 使用递归快速算法进行绘制。使用贝塞尔曲面可以轻松绘制出高次多项式曲面,同时 可以控制该曲面的大致形状。诸多的优点使得计算机图形学教材或者著作中都介绍 这类曲面。 5.2.1 贝塞尔曲面的定义 下面给出贝塞尔曲面的参数表达形式: 在三维空间中,给定(n+1)×(m +1)个点Pij =(xij,yij,zij),i=0,1,2,…,n;j= 0,1,2,…,m 。 X =f(u,v)=Σn i=0Σm j=0 xijBi,n(u)Bj,m (v) Y =g(u,v)=Σn i=0Σm j=0 yijBi,n(u)Bj,m (v) Z =h(u,v)=Σn i=0Σm j=0 zijBi,n(u)Bj,m (v) ì . í .... .... 0≤u ≤1,0≤v ≤1 (5-4) 其中,Bi,n(u)=Ci nui (1-u)n-i,Bj,m (v)=Cj mvj (1-v)m -j 是伯恩斯坦基函数,组合数 Ci n = n! i!(n-i)!,Cj m = m ! j!(m -j)!。 从式5-4看出,贝塞尔曲面的构造方式与贝塞尔曲线类似,基函数是相同的;只是贝 塞尔曲面有三个变量,也就有三个参数方程构成方程组。当u,v 在一个平面区域变化 时,三维点(X ,Y,Z)便形成了曲面。 5.2.2 双一次贝塞尔曲面 在式5-4中,如果n=m =1,那么得到的曲面称为双一次贝塞尔曲面。 【例5-3】 把n=m =1代入式5-4,求出双一次贝塞尔曲面的参数方程,分析双一次 贝塞尔曲面片的特征。 把n=m =1代入后得: 第5 章 样条曲面1 69 X =Σ1 i=0Σ1 j=0 xijBi,1(u)Bj,1(v) Y =Σ1 i=0Σ1 j=0 yijBi,1(u)Bj,1(v) Z =Σ1 i=0Σ1 j=0 zijBi,1(u)Bj,1(v) ì . í .... .... . X =[B0,1(u)B1,1(u)]x00 x01 x10 x11 é . êê ù . úú B0,1(v) B1,1(v) é . êê ù . úú Y =[B0,1(u)B1,1(u)]y00 y01 y10 y11 é . êê ù . úú B0,1(v) B1,1(v) é . êê ù . úú Z =[B0,1(u)B1,1(u)]z00 z01 z10 z11 é . êê ù . úú B0,1(v) B1,1(v) é . êê ù . úú ì . í .... . .... 其中,基函数: B0,1(u)=1-u, B1,1(u)=u B0,1(v)=1-v, B1,1(v)=v 所以有 X =(1-u)(1-v)x00 +u(1-v)x10 + (1-u)vx01 +uvx11 Y =(1-u)(1-v)y00 +u(1-v)y10 + (1-u)vy01 +uvy11 Z =(1-u)(1-v)z00 +u(1-v)z10 + (1-u)vz01 +uvz11 ì . í .. .. (5-5) 写成矩阵表示形式为 P(u,v)=[u 1]-1 1 1 0 é . êê ù . úú P00 P01 P10 P11 é . êê ù . úú -1 1 1 0 é . êê ù . úú v1 é . êê ù . úú (5-6) 分析式5-5参数方程(组),该方程组有两个参数,各项的最高次数为2;方程中一共 有4个控制点的12个坐标值;3个方程的形式是相同的,只是分别使用了控制点的x、y 与z 坐标值。使u 与v 在0~1变化,对应每一个(u,v)都能得到一个空间点(X ,Y, Z)。 当u=0、v=0、u=1、v=1其中一个成立时,便得到一条边界直线段;所以一共有4 条边界直线段。当u 或者v 中一个不变,改变另外一个,得到的是一条直线段。 可以证明,双一次贝塞尔曲面是双曲抛物面。 下面编写程序绘制双一次贝塞尔曲面。 【例5-4】 绘制双一次贝塞尔曲面。 修改例5-2中相关语句如下。 double cv[4][3]={{20,10,110},{100,60,20},{90,20,10},{5,30,80}}; for(double u=0;u<1;u=u+0.05) { n=0; for(double v=0;v<1;v=v+0.05) { x[m][n][0]=(1-u)*(1-v)*cv[0][0]+u*(1-v)*cv[1][0]+(1- u)*v*cv[2] [0]+u*v*cv[3][0]; x[m][n][1]=(1-u)*(1-v)*cv[0][1]+u*(1-v)*cv[1][1]+(1- u)*v*cv[2] [1]+u*v*cv[3][1]; x[m][n][2]=(1-u)*(1-v)*cv[0][2]+u*(1-v)*cv[1][2]+(1- u)*v*cv[2] [2]+u*v*cv[3][2]; n++; } 1 70 计算机图形学(VC++ 实现)(第3 版) 绘制出的图形如图5-4(a)所示。 如果把控制点赋值语句修改为如下所示,每次运行,或者调整运行后文档窗口,都可 以重新绘制出新的曲面,图5-4(b)和图5-4(c)就是随机生成的两个曲面。 double cv[4][3]; for(int i=0;i<4;i++) for(int j=0;j<3;j++) cv[i][j]=rand()%300; //控制点坐标介于0~300 图5-4 双一次贝塞尔曲面 【注】 空间中的一些直线也可以构成曲面。 【例5-5】 绘制双一次贝塞尔曲面,并绘制出其4个控制点。 在例5-4(从例5-2修改而来)中的函数DrawCurve()的最后加入下面的语句。 CBrush b(RGB(255,0,0)); pDC->SelectObject(&b); for(int r=0;r<4;r++) { xx[r]=(cv[r][0]-p[0]/p[2]*cv[r][2])+100; yy[r]=(cv[r][1]-p[1]/p[2]*cv[r][2])+100; pDC->Ellipse(xx[r],yy[r],xx[r]+10,yy[r]+10); } 运行程序,除了绘制出双一次贝塞尔曲面外,还绘制出4个控制点。为了清楚,用小 椭圆代替了点。 5.2.3 双二次贝塞尔曲面 在式5-4中,令n=m =2,得到的曲面称为双二次贝塞尔曲面。 当n=m =2时,给定(n+1)×(m +1)=9个点Pij=(xij,yij,zij),其中,i=0,1,2; j=0,1,2。代入式5-7: P(u,v)=Σ2 i=0Σ2 j=0 PijBi,2(u)Bj,2(v) 0≤u ≤1,0≤v ≤1 (5-7) 其中,基函数: 第5 章 样条曲面1 71 B0,2(u)=u2 -2u +1, B1,2(u)=-2u2 +2u, B2,2(u)=u2 B0,2(v)=v2 -2v +1, B1,2(v)=-2v2 +2v, B2,2(v)=v2 把如式5-7所示双二次贝塞尔曲面的参数方程整理成矩阵表示形式为 P(u,v)=[u2 u 1] 1 -2 1 -2 2 0 1 0 0 é . êêêê ù . úúúú P00 P01 P02 P10 P11 P12 P20 P21 P22 é . êêêê ù . úúúú 1 -2 1 -2 2 0 1 0 0 é . êêêê ù . úúúú v2 v1 é . êêêê ù . úúúú (5-8) 其中,顶点矩阵实际上是3个矩阵,即9个控制点的X,Y,Z 矩阵。即矩阵 P00 P01 P02 P10 P11 P12 P20 P21 P22 é . êêêê ù . úúúú 相当于下面三个矩阵: x00 x01 x02 x10 x11 x12 x20 x21 x22 é . êêêê ù . úúúú , y00 y01 y02 y10 y11 y12 y20 y21 y22 é . êêêê ù . úúúú , z00 z01 z02 z10 z11 z12 z20 z21 z22 é . êêêê ù . úúúú (5-9) 对于每一个固定的(u,v),对于式5-9中的每一个矩阵(给定数值后),代入式5-8,都可以 得到一个数值;三个矩阵得到三个数值,便是一个空间点的坐标(x,y,z)。 式5-9中的数值就是贝塞尔曲面的控制点的坐标。 图5-5是借助于MATLAB软件绘制的双二次贝塞尔曲面。 图5-5 9个控制点的双二次贝塞尔曲面及其控制网格 其9个控制点的坐标的X 、Y、Z 值如下。 X =0 0.5000 1.0000 0 0.5000 1.0000 0 0.5000 1.0000 Y =0 0 0 0.5000 0.5000 0.5000 1.0000 1.0000 1.0000 Z =0.5468 0.5978 0.9053 0.7596 0.8144 0.1088 0.0963 0.0580 0.7884 其中有4个控制点在曲面(的4个角)上。 1 72 计算机图形学(VC++ 实现)(第3 版) 5.2.4 双三次贝塞尔曲面的16 个控制点 当n=m =3时,式5-4表示的曲面称为双三次贝塞尔曲面。 当n=m =3时,给定(n+1)×(m +1)=16个点Pij =(xij,yij,zij),其中,i=0,1, 2,3;j=0,1,2,3。代入式5-10: P(u,v)=Σ3 i=0Σ3 j=0 PijBi,3(u)Bj,3(v) 0≤u ≤1,0≤v ≤1 (5-10) 其中,基函数: B0,3(u)=u3 +3u2 -3u +1,B1,3(u)=3u3 +6u2 +3u B2,3(u)=-3u3 +3u2,B3,3(u)=u3 B0,3(v)=v3 +3v2 -3v +1,B1,3(v)=3v3 +6v2 +3v B2,3(v)=-3v3 +3v2,B3,3(v)=v3 把式5-10整理成矩阵形式为 P(u,v)= [u3 u2 u 1] -1 3 -3 1 3 -6 3 0 -3 1 0 0 0 0 0 0 é . êêêêê ù . úúúúú P00 P01 P02 P03 P10 P11 P12 P13 P20 P21 P22 P23 P30 P31 P32 P33 é . êêêêê ù . úúúúú -1 3 -3 1 3 -6 3 0 -3 1 0 0 0 0 0 0 é . êêêêê ù . úúúúú v3 v2 v1 é . êêêêê ù . úúúúú 通常在实际工作中,一般使用三次以下的贝塞尔曲面进行物体建模与图形设计。三 次贝塞尔曲面已经具有足够的形状变化。 图5-6就是一个16个控制点控制的三次贝塞尔曲面,同时(为了清晰)只绘制出了Y 轴方向的网格线。 图5-6 16个控制点的双三次贝塞尔曲面及其Y 轴方向上的控制网格 网格(控制)点的坐标点X 、Y、Z 分量如下。 X = 0 0.3333 0.6667 1.0000 0 0.3333 0.6667 1.0000 0 0.3333 0.6667 1.0000 0 0.3333 0.6667 1.0000