第 7章 曲线与曲面
曲线和曲面是计算机图形学中重要的研究内
容之一,在实际工作中有广泛的应用。实验、
统计数据的表示,设计、分析和优化的结果显
示,以及汽车、飞机的外型设计都需要用到曲
线和曲面的知识。本章主要介绍曲线和曲面的
基础知识、常用曲线、曲面的数学基础、性质
和分析,并且通过实验对所涉及到的算法进行
程序设计。
7.1 基础知识
所谓自由曲线和曲面, 指的是形状比较复杂,
不能用二次方程表示的曲线和曲面 。 在自
由曲线和曲面设计中,必须首先研究它的数
学表示形式,并通过计算机图形学的技术
将数学表示(模型)在计算机屏幕上以图
形的形式显示出来。
7.1.1 曲线的数学表示
曲线的数学表示形式有显式、隐式和参数
三种表示形式。
( 1)显式表示:对于一条平面曲线,显
式表示的一般形式是,y=f(x),即一个 x对
应一个 y值。例如,一条直线方程 y=mx+b。
显然,显式表示只能表示直线方程,而不
能表示封闭或多值曲线,如圆、椭圆等。
( 2)隐式表示,隐式表示的一般形式是:
f(x,y)=0。例如,圆锥曲线的一般方程为:
ax2+2bxy+cy2+2dx+2ey+f=0,通过定义不同
的方程系数,可得到不同的圆锥曲线,典
型的圆锥曲线是抛物线、双曲线和椭圆。
显式表示和隐式表示两种方式属于非参数
方程,在进行图形显示过程中会出现如下
问题:① 与坐标轴相关;② 会出现斜率为
无穷大的情况(如垂直线);③ 对于非平
面曲线、曲面难以用常系数的非参数化函
数表示;④ 不便于计算和编程序。因此,
在计算机图形显示中曲线和曲面经常用参
数方程来表示。
( 3)参数表示,在平面曲线的参数表示中,
曲线上每一点的坐标均要表示成一个参数
形式,参数表示的一般形式为:
x=x(t)
y=y(t)
曲线上点矢量表示为:
P(t)=[ x(t),y(t)]
参数曲线的切矢量(或导函数)是:
P’(t)=[ x’(t),y’(t)]
通常经过对参数变量的规格化,使 t在 [0,
1]闭区间内变化,对此区间内的参数曲线进
行研究。利用参数表示曲线具有很多
优越性,对曲线的形状也更容易控制,因
此自由曲线一般都是由参数方程来表示。
例如,通过两点 p1(x1,y1)和 p2(x2,y2)的直
线段参数方程表示为:
p(t)=p1+(p2-p1)t,其中 t∈ [0,1],
p(t)=[x(t),y(t)],p1=[x1,y1],p2=[x2,y2]
即 x(t)=x1+(x2-x1)t
y(t)=y1+(y2-y1)t
7.1.2 插值、逼近、拟合和光顺
在研究和应用曲线和曲面时,经常要用到值、
逼近、拟合和光顺技术,下面具体解释一
下这四个概念的含义及其所采用的技
术。
1.插值
插值是函数逼近的重要方法。设给定函
数 f(x)在区间 [a,b]中互异的 n个点(称为型值
点)的值 ? (xi),i=1,2,…,n,基于这个列表
数据,寻找某一函数 ?(x)去逼近 ?(x)。如果
要求 ?(x)在 xi处与 ? (xi)相等,就称这样的函
数逼近问题称为插值问题,称 ?(x)为 ? (x)的
插值函数。也就是说,?(x)在 n个插值点 xi
与 ? (xi)相等,而在别处就用去 ?(x)近似代
替 ? (x)。求给定型值点之间曲线上的
点称为曲线的插值。
在曲线和曲面中最常用的是线性插
值和抛物线插值。
( 1)线性插值
假设给定函数 ? (x)在两个不同点 x1和 x2的
值,y1=? (x1),y2=? (x2)。线型插值是用过
这两个点的直线段 y=?(x)=ax+b来近似代替
函数 y=? (x)。如图 7.1所示。
y=f(x)
y=?(x)
y
xx1 x2
y1 y2
图 7.1.1 线性插值
(x2-x1)
?(x)= y1+ (x-x1) (点斜式 )
例如,已知 f(x)=?x, x1=52.3,y1=7.232,
x2=52.4,y2=7.239,求 ?52.37 。
用过两点的直线段来代替函数 ? (x) 。线性插值函数
(7.239-7.232)
(52.4-52.3)
?(x)= 7.232+ (x-52.3)
(7.239-7.232)
(52.4-52.3)
?(52.37)= 7.232+ (52.37-52.3) =7.2369
( 2)抛物线插值
设已知函数 ? (x)上三个互异点 x1,x2,x3的函
数值,分别为 y1,y2,y3,要求构造一个抛物
线函数,?(x)=ax2+bx+c,使 ?(x)在三个型
值点上满足条件,?(xi)= ? (xi),i=1,2,3。通
过联立方程组,求出 a,b,c,即可以得到抛物
线函数 ?(x)的插值函数。如图 7.1.2所是。
y=f(x)
y=?(x)
y
xx1 x3
y1 y
2
图 7.1.2 抛物线插值
y3
x2
2.逼近
由于要求插值函数通过每个型值点,这使得构
造插值函数相当困难。另外,由于过多的型值点
也会有误差,没有必要寻找一个插值函数来通过
所有的型值点。因此,在实际应用中往往选择一
个次数较低的函数,在某种意义上最佳逼近这些
型值点。最常用的逼近方法就是最小二乘法。
假设已知一组型值点( xi,yi),i=0,1,2,…,n,要
求构造一个 m( m<n-1)次的多项式 y=F(x) 逼近这
些型值点,满足条件,y0=F(x0),yn=F(xn),并且使
各点偏差的平方和最小,
? 假设已知一组型值点( xi,yi),i=0,1,2,…,n,要求
构造一个 m( m<n-1)次的多项式 y=F(x) 逼近这些
型值点,满足条件,y0=F(x0),yn=F(xn),
? 并且使各点偏差的平方和最小,
? k=1
? n
? 即 ?=∑[F(xk)-yk)]2 为最小。
? 3.光顺
? 光顺是指曲线的拐点不能太多,曲线拐来拐去,
就会不顺眼。对于平面曲线,光顺的条件应该是:
( 1)具有二阶几何连续( G2);( 2)不存在多
余拐点和奇异点;( 3)曲率变化较小。
? 4.拟合
? 曲线的拟合是指在曲线、曲面的设计过程中,用
插值或逼近方法使生成的曲线、曲面达到某些设
计要求,如在允许的范围内贴近原始的型值点序
列,或要求曲线、曲面看上去要光滑等。对曲线、
曲面而言,光滑是指它们在切矢量上的连续性,
或更精确的要求是指曲率的连续性。
? 在实际应用中,特别是在试验、测量过程
中,往往得到多组实验数据,要求计算机
用一个曲线、曲面来表示。如果要求所构
造的函数通过每一个型值点,则需要用插
值方法。如果不要求通过每一个点,常常
采用曲线拟合方法。曲线拟合包括逼近技
术和光顺技术,其目的使得构造出的曲线
接近个型值点,并且曲线还比较光顺。
? 7.1.3 曲线段之间的连续性
? 曲线段本身的连续性是由其自身的参数方程来决
定的。下面给出参数曲线段之间的连续性的概念。
Q1(t)Q2(t)P图 7.1.3 曲线段之间的连续性
? 已知参数曲线段 Q1(t)和 Q2(t),t∈ [0,1]。如图 7.1.3
所示。如果:
? (1) Q1(1)和 Q2(0),即 Q1(t)的终点与 Q2(t)的起点重
合于 P,则称 Q1(t)和 Q2(t)在 P点处有 C0和 G0连续。
? (2) Q1(1)和 Q2(0)在 P点处重合,且其在 P点处的切
矢量方向相同,大小不等,则称 Q1(t)和 Q2(t)在 P
点处有 G1连续;若不仅切矢量方向相同,而且大
小也相等,则称 Q1(t)和 Q2(t)在 P点处有 C1连续。
? (3) Q1(1)和 Q2(0)在 P点处有 C0和 C1连续,且其 Q1”(1)和
Q2”(0) 方向相同,大小相等,则称 Q1(t)和 Q2(t)在 P点处有
C2连续;同理,如果 Q1(1)和 Q2(0)在 P点处有 G0和 G1连续,
且其 Q1”(1)和 Q2”(0) 方向相同,大小不等,则称 Q1(t)和
Q2(t)在 P点处有 G2连续。
? 在曲线段连接时,需要考虑连接点处的连续性。在曲线、
曲面造型中,一般只用到 C1,C2和 G1,G2连续,切矢量
(一阶导数)反映了曲线对参数 t的变化速度,曲率(二
阶导数)反映了曲线对参数 t变化的加速度。通常 C1连续
必能保证 G1连续,但 G1连续并不能保证 C1连续。曲线段
在连接处达到 G1连续和 C1连续的光滑程度是相同的,但
曲线的变化趋势在这两种情况下不一定相同。在实际应用
中,需要适当地选择曲线段、曲面片之间的连续性,使图
形既能保证光滑性的要求,又能达到美观性的要求。
7.2 抛物线
? 7.2.1 抛物线的参数拟合
? 1.抛物线的数学基础和几何意义
? 在数学基础中,我们知道:已知三个控制点可以
决定一条抛物线。因此,如果给定三个控制点
P0(x0,y0),P1(x1,y1)和 P2(x2,y2),如何绘制出相
应的抛物线呢?
? 抛物线的矢量方程为:
? Q(t) = at2 + bt + c,t∈ [0,1] (式 7-2-1)
? 所对应的代数方程为:
? { x(t)=axt2 + bxt + cx,
? y(t)=ayt2 + byt + cy,t∈ [0,1] (式 7-2-2)
? 通常给出下面抛物线的边界条件:
? ( 1)当 t=0时,抛物线过 P0点,且切于 P0 P1;
? ( 2)当 t=1时,抛物线过 P1点,且切于 P1 P2;
? 通过联立方程组和边界条件,可以求出抛物线参
数方程的系数:
? cx = x0
? cy = y0
? bx =2(x1 - x0)
? by =2(y1 - y0)
? ax = x2 - 2 x1 +
x0P0(x0,y0)P1(x1,y1)P2(x2,y2)Pm(xm,ym)C图 7.2.1
抛物线曲线
? ay = y2 - 2 y1 + y0
? 详细求解过程可以参阅文献 [2](清华大学
出版社,唐泽圣编著,第 72-74页)。当这
些系数求出后,式 7-2-2所表示的抛物线参
数方程也就确定了。通过 t∈ [0,1]取 100个离
散的值( dt=0.01),分别求出曲线上点的
坐标 [x(t),y(t)],曲线上相邻点用直线段相
连,就可以绘出相应的抛物线。如图 7.2.1
所示。
? 抛物线曲线的两个重要性质:
? 性质 1:抛物线在 t=1/2处的切线平行于 P0 P2 ;
? 性质 2,t=1/2时,抛物线上的点 Pm为 P1 C的中点,
其中 C为 P0 P2的中点;
? 证明:(略,可以参阅文献 [2])
? 2.抛物线程序设计
? 实现抛物线算法的 C语言程序段如下:(工程名:
parabola)
? Par(int xs,int ys,int xm,int ym,int xe,int ye) //已知起
点、中点和终点三个控制点的坐标
? {
? double t,dt,ax,ay,bx,by,cx,cy;
? int n,i;
? ax=xe-2*xm+xs;
? ay=ye-2*ym+ys;
? bx=2.0*(xm-xs);
? by=2.0*(ym-ys);
? cx=xs; cy=ys;
? n=sqrt(ax*ax+ay*ay);
? n=sqrt(n*100.0);
? moveto(xs,ys);
? dt=1.0/n; t=0;
? for (i=0;i<=n; i++)
? {
? lineto((int)(ax*t*t+bx*t+cx),(int)( ay*t*t+by*t+cy));
? t=t+dt;
? }
? lineto(xe,ye);
? }
7.2.2 抛物线参数样条曲线
? PiPi+1SiPi+3Si+1S图 7.2.1 抛物线参数样条曲线
? 抛物线参数样条曲线完全通过给定的每一个型值
点,是一种插值样条曲线。其基本思想如下:给
定 N个型值点 P1,P2,…, PN,对于相邻三点 Pi,
Pi+1,Pi+2,以及 Pi+1,Pi+2,Pi+3, i=1,2,…,N-
2,反复用抛物线插值算法,然后再对此相邻的抛
物线曲线在公共区间 Pi+1Pi+2部分,用权函数 t与
1-t进行调配,使其混合为一条曲线 S。如图 7.2.1
所示。
? N-2
S= ∑ [(1-t).Si+t.Si+1],t∈ [0,1] (式 7-2-1)
? i=1
其中,Si 是由 Pi,Pi+1,Pi+2三点决定的抛
物线,Si+1 是由 Pi+1,Pi+2,Pi+3三点决
定的抛物线。混合后的曲线 S在 Pi+1到 Pi+2
公共段内,是 Si的后半段与 Si+1的前半段加
权混合的结果。 S曲线在公共段内具体的参
数方程可写为:
? x(t’)=(1-t’)(a1xt12+ b1xt1+ c1x)+ t’(a2xt22+ b2xt2+
c2x)
? y(t’)=(1- t’)(a1yt12+ b1yt1+ c1y)+ t’(a2yt22+
b2yt2+ c2y) (式 7-2-2)
? 其中,t2∈ [0,0.5],t1= t2+0.5∈ [0.5,1],t’
∈ [0,1]=2 t2
? 式 7-2-2可以表示为:
? {
? x(t2)=(1- 2t2)(a1x (t2+0.5) 2+ b1x(t2+0.5)+
c1x)+ 2 t2 (a2xt22+ b2xt2+ c2x)
? y(t2)=(1- 2 t2)(a1y(t2+0.5)2+ b1y(t2+0.5)+ c1y)+ 2
t2 (a2yt22+ b2yt2+ c2y) (式 7-2-3)
? 显然,当 t1=0.5,t2=0时,S=Si; 当 t1=1,t2=0.5时,
S=Si+1;
? 用这种方法构造的自由曲线,在 P2到 PN-1各点左、
右侧都能达到一阶导数连续,即 C1连续。曲线两
端点是 S1段的前半段和 SN-2段的后半段。
t2∈ [0,0.5]按照 (式 7-2-3)取多个点可以求出公共区
间部分。通过迭代过程可以求出 (式 7-2-1)表示的
中间各段公共部分。生成的抛物线参数样条曲线
如图 7.2.2所示。
? 读者可以根据上述抛物线程序设计,写出抛物线
参数样条曲线的程序。
7.3 Hermite曲线
? 7.3.1 参数方程
? 一条三次参数曲线方程的代数形式可以表示为:
? x(t)=a3xt3+a2xt2+a1xt+a0x
? y(t)= a3yt3+a2yt2+a1yt+a0y,t∈ [0,1]
(式 7-3-1)
? z(t)= a3zt3+a2zt2+a1zt+a0z
? 为了用三次参数方程准确地描述一条自由曲线的
形状和位置,必须给出上式中的 12个系数。
? Hermite曲线是通过给出曲线段两个端点坐标 P0和
P1以及两端点处的切矢量 R0和 R1来描述的。如图
7.3.1所示。
? 式 7-3-1可以写成矢量形式,a3
? P(t)= a3t3+ a2 t2 + a1 t+ a0=[ t3 t2 t 1 ] a2
? a1
? a0,
? t∈ [0,1] (式 7-3-2)
? 其中,P(t)=[x(t) y(t) z(t)],a3 =[a3x a3y a3z ],a2
=[a2x a2y a2z ],
? a1 =[a1x a1y a1z ],a0 =[a0x a0y a0z ],
? 根据 Hermite曲线的已知条件,可得到如下四个方程组:
? P(0)= a0= P0 P(1)= a3 + a2 + a1 + a0 = P1
? P’(0)= a1 = R0 P’(1)= 3a3 +2 a2 + a1 = R1
? 求解上述四个方程组得到:
? a0= P0
? a1 = R0
? a2 = -3 P0+3 P1-2 R0- R1
? a3 = 2 P0-2 P1+ R0+ R1
? 将结果带入到式 7-3-2中,得到:
? P(t)=( 2 P0-2 P1+ R0+ R1) t3+ (-3 P0+3 P1-2 R0- R1) t2 + R0 t+ P0
? =(2 t3-3 t2+1) P0+(-2 t3+3 t2) P1+( t3-2 t2+t) R0+( t3- t2) R1
(式 7-3-3)
? 令,F1=2 t3-3 t2+1,F2=-2 t3+3 t2,F3= t3-2 t2+t,F4= t3- t2
? 则,式 7-3-3可以表示为:
? P(t)= F1 P0+ F2 P1+ F3 R0+ F4 R1, t∈ [0,1] (式 7-3-4)
? 式 7-3-4就是 Hermite曲线的几何形式,它表示 Hermite曲线上的点 P(t)只
与 P0,P1,R0,R1四个值有关,称为 Hermite曲线的几何系数。
F=[ F1,F2,F3,F4]表示四个仅仅与参数 t( t∈ [0,1])有关的函数,
称为 Hermite曲线的调和函数。
? Hermite曲线的矩阵表示:
? F=[ F1,F2,F3,F4]=[ 2 t3-3 t2+1,-2 t3+3 t2,t3-2 t2+t,
t3- t2]
? 2 -2 1 1
? =[ t3 t2 t 1 ] -3 3 -2 -1 = T M
? 0 0 1 0
? 1 0 0 0
? 则 P0
? P(t)= F1 P0+ F2 P1+ F3 R0+ F4 R1 =[ F1,F2,F3,F4] P1
? R0
? R1
? 令,B=[ P0 P1 R0 R1]T (转置矩阵 )
? 所以,
? P(t)=FB=TMB, t∈ [0,1] (式 7-3-5)
7.3.2 调和函数
? 在式 7-3-4中,Hermite曲线 P(t)将四个已知条件的
P0,P1,R0,R1对曲线的作用通过四个仅与 t有
关的函数表现出来。 我们把这四个函数 F=[ F1,
F2,F3,F4]=[ 2 t3-3 t2+1,-2 t3+3 t2,t3-2 t2+t,
t3- t2]称为调和函数。 Hermite曲线调和函数的作
用是通过端点及其切矢量产生整个 t值范围内的其
余各点的坐标,并且只与参数 t有关,由此便于通
过修改边界条件来改变曲线的形状。如图 7.3.2所
示,表示四条调和函数的曲线。
? 调和函数具有如下性质:
? ( 1)调和函数仅与参数值 t有关,而与初始条件
无关;
? ( 2)调和函数对于物体空间三个坐标值( x,y,z)
是相同的;
? ( 3)当处于参数的边界时,调和函数各分量中仅
有一个起作用。例如,当 t=0时,F1=1,
F2=F3=F4=0,即 P(t)在起点仅与 P0有关,而与 P1,
R0,R1无关;当 t=1时,F2=1,F1=F3=F4=0,即
P(t)在起点仅与 P1有关,而与 P0,R0,R1无关。
? 值得注意的是,此处讨论的是 Hermite参数曲线的
调和函数,对于不同的参数曲线构造条件,所得
到的调和函数不会是一样的,其调和函数的性质
也不相同。
7.3.3 Hermite 曲线程序设计
? Hermite 曲线方程为:
? 3 -2 1 1 P0
? P(t)=FB=TMB=[ t3 t2 t 1 ] -3 3 -2 -1 P1
? 0 0 1 0 R0
? 1 0 0 0 R1
?
? 程序设计时只考虑二维图形的显示,其代数形式为:
? x(t)=TMBx, Bx =[ P0x P1x R0x R1x]T
? y(t)= TMBy, By =[ P0y P1y R0y R1y]T
? 所以,只要给出 Hermite曲线的起点坐标( P0x,P0y),终点坐标
( P1x,P1y),以及起点处的切矢量( R0x,R0y)和终点处的切
矢量( R1x,R1y),参数变量 t在 [0,1]的范围内分别取 0.01,
0.02,…, 1,步长为 0.01,取 100个点,分别求出 P(t)=[ x(t),y(t)],
在计算机屏幕上显示出每个坐标点,即可绘出 Hermite曲线。
? 在 Tubro C或 Borland C++中程序如下:
? #include <graphics.h>
? #include <math.h>
? double h03(double);
? double h13(double);
? double h23(double);
? double h33(double);
? main()
? {
? int driver,mode,i,j;
? int i,px0,py0,px1,py1,curx,cury,k0,k1;
? float t,dt,rx0,ry0,rx1,ry1;
? //图形初始化
? driver=DETECT;
? initgraph(&driver,&mode,”c:\tc”);
? setbkcolor(BLUE);
? k0=300;k1=10;
? px0=40;py0=40;px1=240;py1=40;
? rx0=k0*0.8320;ry0=k0*0.5547;rx1=k1*0.8320;ry1=-0.5547;
? //画坐标轴线
? setcolor(WHITE);
? line(20,20,300,20);
? Line(20,20,20,150);
? //画曲线
? dt=0.01; t=0;
? moveto(px0,py0);
? for(i=0;i<=100;i++)
? {
? curx=(int)(h03(t)*px0+h13(t)*px1+h23(t)*rx0+h33(t)*rx1);
? cury=(int)(h03(t)*py0+h13(t)*py1+h23(t)*ry0+h33(t)*ry1);
? lineTo(curx,cury);
? t=t+dt;
? }
? getchar();
? closegraph();
? restorecrtmode();
? }
? //自定义函数
? double CHermite_curveView::h03(double t)
? {
? return (2*pow(t,3)-3*t*t+1);
? }
? double CHermite_curveView::h13(double t)
? {
? return (-2*pow(t,3)+3*t*t);
? }
? double CHermite_curveView::h23(double t)
? {
? return (pow(t,3)-2*t*t+t);
? }
? double CHermite_curveView::h33(double t)
? {
? return (pow(t,3)-2*t*t);
? }
? 读者可以用 VC++来实现。方法是将自定义
的函数定义为成员函数,并在 OnDraw()函
数中输入主程序,参见程序目录中的
Hermite_curve程序的实现。读者也可以模
仿 CoreDraw软件中画曲线的方法实现鼠标
交互式画曲线。
? 4.切矢量对曲线的影响
? 下面讨论两端点处的切矢量对曲线的影响。在 Hermite曲线
参数方程中,R0和 R1表示起始点及终止点的切矢量。令
单位矢量
? R0 R1
? E0=,E1=
? | R0| | R1|
? 于是有:
? | E0| = ? E0x 2+ E0y 2+ E0z2 =1,
? | E1| = ? E1x 2+ E1y 2+ E1z2 =1
? 如果令:
? | R0| = k0, | R1| = k1
? 则有:
? R0 = k0 ? E0,R1 = k1 ? E1
? 切矢量包括切线的方向和长度两个方面,如果切
矢量的方向和长度都是已知的,则切矢量在三维
空间中的三个分量也就全部是确定的,从而
Hermiter曲线也就可以确定。如果仅仅给出切矢量
的方向,而未给出切矢量的长度,就不能确定
Hermite曲线。下面举例说明由于切矢量长度的不
同,Hermite曲线会具有完全不同的形状。
? 设 Hermite曲线的构造条件为:
? P0 = [x0 y0 z0] = [4.0 4.0 0.0]
? P01= [x1 y1 z1] = [24.0 4.0 0.0]
? R0 = k0 [E0x E0y E0z ] = k0 [0.8320 0.5547 0.0]
? R1 = k1 [E1x E1y E1z ] = k1 [0.8320 -0.5547 0.0]
? 当 k1=10,而 k0由 10变化到 80时对 Hermite曲线的
影响。如图 7.3.3所示。
? 5.自由曲线的连接
? 设两条互不相连的 Hermite曲线段 1和 3的边
界条件分别为:
? B1=[P1(0) P1(1) P1’(0) P1’(1)]T;
? B3=[P3(0) P3(1) P3’(0) P3’(1)]T;
? 如果要使参数曲线段 2与曲线 1,3的连接均
为 C1连续,那么曲线 2的边界条件 B2应该满
足什么条件?如图 7.3.4所示。
? 为了保证曲线段 1,2之间,以及 2,3之间的 C1连续,必有
下面关系:
? P2(0) = P1(1), P2(1) = P3(0)132图 7.3.4 Hermite曲线的
连接
? P1 ‘(1)
? P2‘(0)= a ?
? | P1 ‘(1)|
? P3 ‘(0)
? P2‘(1)= b ?
? | P3 ‘(0)|
? 从而构造 B2的几何系数为:
? B2=[P1(1) P3(0) P2’(0) P2’(1)]T;
? 其中,a,b>0,即正的比例因子,通过 a,b的变化来改变 B2
曲线的内部形状。
7.4 Bezier曲线
? 在产品的外形设计中,更多的要求是曲线
光滑美观。用样条曲线精确地插值各型值
点,曲线的形状难以修改和控制。针对这
一问题,1962年法国雷诺汽车公司的
P.E.Bezier构造了一种以逼近为基础的参数
曲线,称为 Bezier曲线。 Bezier方法将函数
逼近同几何表示结合起来,使得设计师在
计算机上绘制曲线就像常规的作图工具一
样得心应手,在计算机图形系统中得到广
泛的应用。
? 7.4.1 Bezier曲线的基本思想和数学表达式
? Bezier曲线是通过一组多边形折线(称为
Bezier特征多边形)的各顶点唯一定义出来
的。在多边形的各顶点中,只有第一点和
最后一点与曲线的起点和终点重合,其余
的定点则用来定义曲线的阶次和形状,并
且第一条和最后一条折线表示出曲线在起
点和终点处的切矢量方向。曲线的形状趋
于特征多边形的形状。 N次 Bezier曲线是通
过( N+1)各特征点来定义的。图 7.4.1是典
型的三次 Bezier曲线的示例图。
? Bezier曲线段参数方程表达式为:
? n
? Q(t)=∑Pi?Bi,n(t),t∈ [0,1] ( 7-4-1)
? i=0
?
? 其中,Pi为多边折线的控制点的位置矢量,i=0,1,…,n,共 n+1个控制
点,定义了 n次 Bezier曲线 Q(t)。 Bi,n(t)为伯恩斯坦( Bernstrin)多项式,
称为基函数,也是 Bezier曲线上各点位置矢量的调和函数。
? n!
? Bi,n(t)= ti(1-t)n-i= C in ti(1-t)n-I
? i! (n-i)!
? 注:当 i=0,t=0时,ti=1,0! =1。
? 从式( 7-4-1)可以看出:只要给定 n+1个控制点 Pi
(i=0,1,…,n),就可以唯一的确定一个 n次多边形 Q(t)。
Bezier曲线上的点 Q(t)=[x(t),y(t),z(t)],控制点 Pi =[ xi,yi,zi],
所以其代数方程形式为:
? n
? x(t)=∑xi?Bi,n(t)
i=0
? n
? y(t)=∑yi?Bi,n(t),t∈ [0,1] ( 7-4-2)
? i=0
? n
? z(t)=∑zi?Bi,n(t)
i=0
? 当 t在 [0,1]区间中取多个离散值时,就可以得到曲线 Q(t)
上各个点的位置,相邻点用直线段相连,就可以得到由
n+1个控制点定义的 Bezier曲线。
7.4.2 Bezier曲线的矩阵表示和几何
意义
? 由 Bezier曲线的数学定义公式( 7-4-1),我们可以很
容易地推出常用的一次、二次、三次 Bezier曲线的矩
阵形式表示,分析出三种 Bezier曲线的几何意义。
? ( 1)一次 Bezier曲线
? 当 n=1时,表示一次 Bezier曲线,需要两个控制点 P0
和 P1。代入公式( 7-4-1),得到:
? 1
Q(t)=∑Pi?Bi,1(t) = P0?B0,1(t)+ P1?B1,1(t),t∈ [0,1]
? i=0
? B0,1(t)= C 01 t0(1-t)1-0=1-t,B1,1(t)= C 11 t1(1-t)1-
1=t,
? 所以,P0P1图 7.4.2 一次 Bezier曲线
? Q(t)= P0?( 1-t) + P1?t= P0+( P1- P0) t
? =[t 1] -1 1 P0
? 1 0 P1
? 结论:一次 Bezier曲线是连接起点 P0与终点 P1
的直线段。如图 7.4.2所示。
? 2)二次 Bezier曲线
? 当 n=2时,表示二次 Bezier曲线,需要三个控制点
P0,P1,P2。代入公式( 7-4-1),得到:
? 2
? Q(t)=∑Pi?Bi,1(t)=P0?B0,2(t)+P1?B1,2(t)+P2?B2,2(t)
I i =0, t∈ [0,1]
? B0,2(t)= C 02 t0(1-t)2-0=(1-t)2
? B1,2(t)= C 12t1(1-t)2-1=2t(1-t)
? B2,2(t)= C 22 t2(1-t)2-2=t2
? 所以,
? Q(t)= (1-t)2 P0+2t(1-t) P1+ t2 P2
? =( P2 - 2 P1 + P0) t2+2( P1 - P0) t+ P0
? 表示二次 Bezier曲线是一条抛物线。
? 二次 Bezier曲线的矩阵表示:
? 1 -2 1 P0
? Q(t)=[ t2 t 1 ] -2 2 0 P1, t∈ [0,1]
? 1 0 0 P2
?
? 下面分析二次 Bezier曲线的几何意义。首先分析二次 Bezier
曲线的端点和中点性质。
? 当 t=0时,Q(0) = P0 ;
? 当 t=1时,Q(1) = P2 ;
? 说明二次 Bezier曲线的起点 Q(0)和终点 Q(1)与控制点的第
一点 P0和最后一点 P2重合。
? 1 1 1 1
? 当 t= 时,Q( )= [P1 + (P0+ P2)]
? 2 2 2 2
? P0P1P2SM图 7.4.3 二次 Bezier曲线
? 二次 Bezier曲线几何意义如图 7.4.3所示。
? M点是 P0P2的中点,M=( P0+ P2)/2; S是 P1M的中
点,S=( P1+M)/2=( P1+( P0+ P2)/2)/2。
? 结论:二次 Bezier曲线是一条抛物线,它的起点和
终点与控制点的第一点和最后点重合,曲线的中
点( t=0.5)通过特征多边形的中线 P1M的中点。
? ( 3)三次 Bezier曲线
? 当 n=3,表示三次 Bezier曲线,它需要四个控制点 P0,P1、
P2,P3。来定义。这是实际工程中最常使用的 Bezier曲线。代
入公式( 7-4-1),得到:
? 3
? Q(t)=∑Pi?Bi,1(t)=P0?B0,3(t)+P1?B1,3(t)+P2?B2,3(t)+P3?B3,3(t)
,i=0 t∈ [0,1]
? 其中:
? B0,3(t)= C 03 t0(1-t)3-0=(1-t)3
? B1,3(t)= C 13t1(1-t)3-1=3t(1-t)210tB0,3(t)B1,3(t)B2,3(t)B3,3(t)
? B2,3(t)= C 23 t2(1-t)3-2=3t2(1-t)
? B3,3(t)= C 33 t3(1-t)3-3=t3
? 称为三次 Bezier曲线的调和函数。四条曲线如图 7.4.4所示。
? 当 t=0时,B0,3(t)=1,
? B1,3(t)= B2,3(t)= B3,3(t)=0
? 表示 P0对曲线影响最大,与 P1,P2,P3无关;
? 当 t=1时,B3,3(t)=1
? B0,3(t)= B1,3(t)= B2,3(t)=0
? 表示 P3对曲线影响最大,与 P0,P1,P2无关;
? 曲线上中间各点 Q(t)与 P0,P1,P2,P3
? 四个控制点都有关。三次 Bezier曲线形状如
? 图 7.4.1所示。
? 三次 Bezier曲线方程的矩阵表示:
? -1 3 -3 1 P0
? Q(t)= [t3 t2 t 1 ] 3 -6 3 0 P1
? -3 3 0 0 P2
? 1 0 0 0 P3
?
,t∈ [0,1]
? =T?M?PT
? 其中,P=[ P0 P1 P2 P3 ],PT表示 P的转置矩阵。
7.4.3 Bezier曲线的性质
? ( 1)端点及端点处的切矢量
? n
? 当 t=0时,Q(0)= ∑Pi?Bi,1(0)= P0 ;
? i=0
? n
? 当 t=1时,Q(1)= ∑Pi?Bi,1(1)= Pn ;
? i=0
?
? 说明,Bezier曲线的起点与终点与控制点的第一点和最后
点重合。
? ‘
? 对伯恩斯坦多项式求导数,得:
? Bi,’n(t)= C in ti(1-t)n-I
? = C in i.ti-1(1-t)n-i-(n-i) ti(1-t)n-i-1
? =n(Bi-1,n-1(t)- Bi,’n-1(t))
? n
? 即,Q’ (t)= n∑Pi ?((Bi-1,n-1(t)- Bi,’n-1(t));
? i=0
? =n{(P1- P0) B0,n-1(t)+ (P2- P1) B1,n-1(t)+… +(Pn- Pn-1)
Bn-1,n-1(t)}
? n
? = n∑(Pi- Pi-1) Bi-1 n-1(t)
? i=0
? 在起始点,t=0,B0,n-1(0)=1,其余项均为 0,故有,Q’
(0)=n(P1 - P0)
? 在终止点,t=1,Bn-1,n-1(1)=1,其余项均为 0,故有,Q’
(1)=n(Pn - Pn-1)
? 对于三次 Bezier曲线,n=3,所以有:
? Q’ (0)=3(P1 - P0)
? Q’ (1)=3(P3 - P2)
? 说明,Bezier曲线在起始点和终止点处的切线方向与特征
多边形第一条边和最后一条边的走向一致。
? ( 2)对称性
? 由伯恩斯坦多项式可以导出:
? n!
? Bi,n(t)= ti(1-t)n-i= Bn-i,n(1-t)
? i! (n-i)!
? n
由 Q(t)=∑Pi?Bi,n(t) = P0?B0,n(t)+
P1?B1,n(t)+… +
? i=0
? Pn?Bn,n(t)
? = Pn?B0,n(t)+ Pn-1?B1,n(t)+… +
P0?Bn,n(t)
? 也就是说:当特征多边形的各顶点取 Pn,Pn-
1,…,P0时与取 P0,P1,…,Pn所得到的 Bezier曲
线完全相同,只不过曲线的走向相反。
? 3)凸包性
? n n
? 因为 ∑Bi,n(t)= ∑C in ti(1-t)n-i =[(1-t)+t]n=1
? i=0 i=0
? 并且 Bi,n(t)= C in ti(1-t)n-i ≥0,t∈ [0,1]
? 因此,Bi,n(t)是 Bezier曲线的权函数。对于某一个 t
值,Q(t)是特征多边形各顶点 Pi的加权平均,权因
子依次是 Bi,n(t)。在几何图形上,这意味着 Bezier
曲线上的各点均落在特征多边形各顶点构成的凸
包之中。(注:凸包是指包含所有顶点的最小凸
多边形)
? ( 4)几何不变性
? 几何不变性是指曲线的形状仅与特征多边形各顶
点的相对位置有关,而与坐标系的选择无关。
7.4.4 Bezier曲线的拼接及其连续性
? P0P1P2P3 (R0)R1R2R3图 7.4.5 Bezier曲线的连接
? 从 Bezier曲线的数学表示式及其性质可以看出,对
于形状比较复杂的曲线来说,只用一段三次 Bezier
曲线来描述就不够了。一种办法是增加顶点的个
数,从而也就增加了 Bezier曲线的阶次,但是由于
高次 Bezier曲线计算比较复杂,而且还有许多问题
有待理论上解决,因此,这种办法一般不采用。
另一种办法是用分段三次 Bezier曲线来描述,然后
将分段的三次 Bezier曲线连接起来,构成一条复杂
的曲线。这种办法的关键问题是如何保证连接点
处具有 C1及 C2连续。
? 设有两段 Bezier曲线 Q1(t) 和 Q2(t),其特征多边形
顶点分别为 P0,P1,P2,P3及 R0,R1,R2,R3,
而且 P3= R0。若要求两个曲线段在连接点 P3( R0)
处实现 C1连续,应该具有什么条件呢?
? 因 Q1’ (1)=3(P3 - P2)
? Q2’ (0)=3(R1 - R0)
? 为了实现 C1连续,应使
? Q2’ (0)=α Q1’ (1)
? 即 (R1 - R0)= α(P3 - P2) (式 7-4-3)
? 式 7-4-3中的 α为一比例因子。说明实现 C1连续的
条件是 P2,P3( R0),R1在一条直线上,而且 P2,
R1在 P3( R0)的两侧。
? 7.4.5 Bezier曲线的算法实现
? ( 1)算法描述 n
? n
? 根据 Q(t)= ∑Pi?Bi,n(t) = ∑Pi? C in ti(1-t)n-i
? i=0
? n-k+1
? 并且 C in =C(n,k)= C(n,k-1)
? n
? Bezier曲线的 C语言算法描述如下:
? #include <math.h>
? #include <graphics.h>
? void computeCoefficients(int n,int *c)
? {
? int k,i;
? n*(n-1)… (k+1)
? for (k=0;k<=n;k++) /*求 C kn =n!/(k!(n-k)!= )*/
? (n-k)!
?
? {
? int c[k]=1;
? for (i=n; i>=k+1; i--) /*求 c[k]=n*(n-
1)… (k+1) */
? c[k]*=i;
? for (i=n-k; i>=2; i--) /*求 c[k]/(n-k)!*/
? c[k]/=i;
? }
? }
? void computepoint(float t,wcPt3 *pt,int ncontrols,wcPt3
*controls,int *c)
? {
? int i,n=ncontrols-1;
? float blend;
? pt->x=0.0; pt->y=0.0; pt->z=0.0;
? for (i=0; i<ncontrols; i++)
? {
? blend = c[k]*powf(t,i)*powf(1-t,n-i); /*求 C kn ti(1-t)n-i */
? pt->x+=controls[i].x*blend; /*求 x(t)*/
? pt->y+=controls[i].y*blend; /*求 y(t)*/
? pt->z+=controls[i].z*blend; /*求 z(t)*/
? }
? }
? void Bezier(wcPt3 *controls,int ncontrols,int
m,wcPt3 *curve)
? {
? int *c=(int *) malloc(ncontrols *sizeof(int));
? int i;
? computecoefficients(ncontrols-1,c);
? for (i=0; i<=m; i++)
? computepoint(i/(float)m,&curve[i],ncontrols,c
ontrols,c);
? free(c);
? }
? 在主程序中提供特征多边形的各个顶点坐标放入controls[]数组中,ncontrols为顶点的个数,m为曲
线上取的样点数,比如 m=100表示取 100个样点。
计算出曲线上的各个样点坐标放入 curve[]数组中,
这样可以通过相邻点连线绘出生成的 Bezier曲线。
? 程序实现步骤:(工程名,BezierCurve)
? ( ⅰ ) C m n的函数实现,定义成成员函数,命名
为 Multiply_n。
? n! ( m+1) (m+2)… (n-1).n
? C mn = =
? m!(n-m)! (n-m)!
? int Multiply_n(int m,n)
? {
? int i,j,a;
? if (m!=0)
? {
? a=1;
? for (i=m+1;i<=n;i++) //求( m+1)
(m+2)… (n-1).n
? a=a*i;
? for (j=1;j<=n-m;j++) //求 (n-m)!和 C mn
? a=a/j;
? return a;
? }
? else
? return 1;
? }
? ( ⅱ )伯恩斯坦多项式 Bm,n(t)的函数实现
? Bm,n(t)= C mn tm(1-t)n-m
? Double Bernstein(int m,int n,double t)
? {
? int i,j;
? double sum;
? sum=Multiply_n(m,n); //求 C mn
? for (i=1;i<=m;i++)
? sum=sum*t; // C mn tm
? for (j=1;j<=n-m;j++)
? sum=sum*(1-t); // C mn tm(1-t)n-m
? return sum;
? }
? (ⅲ ) 在 OnDraw(CDC* pDC)函数中添加如下代码:
? int i,j,k,n=3; //n=3 表示三次 Bezier曲线
? double curx,cury,t,b;
? double dt=0.01;
? int array[4][2]={{30,100},{100,30},{50,150},{200,40}};
? CPen PenRed(PS_SOLID,1,RGB(255,0,0));//定义红色笔
? CPen PenBlue(PS_SOLID,1,RGB(0,0,255));//定义蓝色笔
? //首先绘出特征多边形
? pDC->SelectObject(&PenBlue);
? pDC->MoveTo(array[0][0],array[0][1]);
? for (i=0;i<=n;i++)
? pDC->LineTo(array[i][0],array[i][1]);
? //绘制 Bezier曲线
? pDC->MoveTo(array[0][0],array[0][1]); //回到起点
? pDC->SelectObject(&PenRed);
? t=0.0;
? for (i=0;i<=(int)1/dt;i++)
? {
? curx=0; cury=0;
? for(j=0;j<=n;j++)
? {
? b=Bernstein(j,n,t);
? curx=curx+array[j][0]*b;
? cury=cury+array[j][1]*b;
? }
? pDC->LineTo(curx,cury);
? t=t+dt;
? }
? 编译、运行后查看结果,如图 7.4.6所示。
? 图 7.4.6 Bezier曲线程序结果
? 这时 Bezier曲线的通用程序设计。通过这个程序,我
们绘出二次、三次甚至高次 Bezier曲线。读者可以通
过修改程序来实现,并观察程序的结果。
? ( 2)三次 Bezier曲线的绘制
? 如果仅仅是绘制三次 Bezier曲线,可以通过
? 3
? Q(t)=∑Pi?Bi,3(t)=P0?B0,3(t)+P1?B1,3(t)+P2?B2,3(t)+
? i=0
? P3?B3,3(t), t∈ [0,1]
? 来简化程序设计。
? 程序如下,(工程名,Bezier)
? 将调和函数设计成成员函数:
? double CBezierView::b03(double t)
? {
? return(pow(1-t,3));
? }
? double CBezierView::b13(double t)
? {
? return(3*t*pow(1-t,2));
? }
? double CBezierView::b23(double t)
? {
? return(3*(1-t)*t*t);
? }
? double CBezierView::b33(double t)
? {
? return(t*t*t);
? }
? 在 OnDraw()函数中输入下面代码:
? void CBezierView::OnDraw(CDC* pDC)
? {
? CBezierDoc* pDoc = GetDocument();
? ASSERT_VALID(pDoc);
? // TODO,add draw code for native data here
? int i;
? int x0,y0,x1,y1,x2,y2,x3,y3,curx,cury;
? double t,dt;
? // 创建两个不同颜色的画笔
? CPen PenRed(PS_SOLID,1,RGB(255,0,0));
? CPen PenBlue(PS_SOLID,1,RGB(0,0,255));
? // 设置控制点,绘出特征多边形
? x0=220;y0=10;x1=410;y1=10;x2=225;y2=150;x3=410;y3=10
0;
? pDC->SelectObject(PenBlue); //使用蓝色画笔
? pDC->MoveTo(x0,y0);
? pDC->LineTo(x1,y1);
? pDC->LineTo(x2,y2);
? pDC->LineTo(x3,y3);
? //绘制 Bezier曲线
? pDC->MoveTo(x0,y0);
? t=0; dt=0.01; //t从 0到 1,每步增加 0.01,取 100个点
? pDC->SelectObject(PenRed); //使用红色画笔
? for (i=0;i<=100;i++)
? {
? curx=(int)(b03(t)*x0+b13(t)*x1+b23(t)*x2+b33(t)*x3);
? cury=(int)(b03(t)*y0+b13(t)*y1+b23(t)*y2+b33(t)*y3);
? pDC->LineTo(curx,cury);
? t=t+dt;
? }
? }
? 读者可以使用鼠标实现交互式绘制 Bezier曲
线。使用数组 ControlsPoints[3]记录鼠标选
择的 P0,P1,P2,P3 四个控制点,然后根
据算法,当 t从 0到 1取 100个值,分别求出
Bezier曲线上的点的坐标( curx,cury)。相
邻点通过直线段连接构成 Bezier曲线。
7.5 B样条曲线
? 以 Bernstein多项式为基础的 Bezier曲线有许多
优点,但是存在以下两个问题:第一,特征多边形顶点的数量决定了 Bezier曲线的阶数,
即 n个顶点的特征多边形必然产生 n-1次 Bezier
曲线,这使得曲线不够灵活。当 n取值较大
时( n>3),特征多边形对曲线的控制减弱;
第二,Bezier曲线不能做局部修改,即改变
某一个控制点的位置对整条曲线都有影响,
这是因为调和函数 Bi,n(t)在开区间( 0,1)
内均不为零。
? 为了克服 Bezier曲线的缺点,1972-1974年
Gordon,Rie-senfeld等人提出了用 B样条函
数来替代 Bernstein函数,构造出了等距节点
的 B样条曲线( B-Spring)。 B样条曲线除
了保持 Bezier曲线的直观性和凸包性等优点
之外,还可以进行局部修改,而且曲线更
逼近特征多边形。此外,曲线的阶数也与顶点数无关,因而更为方便灵活。因此,B
样条曲线和曲面得到了广泛的应用。
7.5.1 B样条曲线的数学表达式
? 若给定 N=m+n+1个顶点( m为最大段号,n为阶数),则
第 i段( i=0,1,2,…,m),n次等距分割的 B样条曲线可以表
示为:
? n
? Qi,n(t)=∑Pi+l Fl,n(t),l=0,1,…,n,t∈ [0,1] (式 7-5-1)
? l =0
? 其中,基底函数
? 1 n-l j
? Fl,n(t)= ∑(-1)jCn+1 (t + n – l - j)n
? n! j=0
? j n!
? 而 Cn+1=
? j! (n-j)!
? Pi+l 为定义第 i段曲线特征多边形的 n+1个顶点
( l=0,1,…,n)。
7.5.2 B样条曲线的矩阵表示和几何
意义
? ( 1)一次 B样条曲线
? n=1,所以 l=0,1,则第 i段曲线的控制点取 Pi和
Pi+1 。
? 基底函数:
? 1 1-0 j
? F0,1(t)= ∑(-1)jC1+1 (t + 1 – 0 - j)1 =(t+1)+(-
1).2t=1-t
? 1! j=0
? 1 1-1 j
? F1,1(t)= ∑(-1)jC1+1 (t + 1 – 1- j)1 =t
? 1! j=0
?
? 所以 Qi,1(t)= Pi, F0,1(t) + Pi+1, F1,1(t)
? = Pi, (1-t) + Pi+1, t
? =( Pi+1- Pi).t + Pi
? 为一条从 Pi到 Pi+1的直线段 Pi Pi+1。
? 当多个型值点 Pn (n>2)用一次 B样条构成
曲线时,相当于用直线段连接各个型值点
所构成的折线段。如图 7.5.1所示。
? ( 2)二次 B样条曲线
? n=2,所以 l=0,1,2,则第 i段曲线的控制点取 Pi,Pi+1
和 Pi+2。
? 1 2-0 j 1
? F0,2(t)= ∑(-1)jC2+1 (t + 2 – 0 - j)2 = (t-1)2
? 2! j=0 2
? 1 2-1 j 1
? F1,2(t)= ∑(-1)jC2+1 (t + 2 – 1 - j)2 = (-
? 2! j=0 2
? 2t2+2t+1)2
? 1 2-2 j 1
? F2,2(t)= ∑(-1)jC2+1 (t + 2 – 2 - j)2 = t2
? 2 j=0 2
? 二次 B样条曲线的矩阵表示为:
? 2 0.5 -1 0.5 Pi
? Qi,2(t)=∑Pi+l Fl,2(t)=[ t2 t 1 ] -1 1 0 Pi+1
? l =0 0.5 0.5 0 Pi+2,t∈ [0,1] (式
7-5-2)
? 求导数 Pi
? Qi,2`(t)=[t 1] 1 -2 1 Pi+1
? 1 1 0 Pi+2
? 分析曲线端点处的性质:
? 1 1
? Qi,2(0)= (Pi + Pi+1); Qi,2(1)= (Pi+1 + Pi+2);
? 2 2
? Pi+1PiPi+2Qi,2(0)Qi,2(1)MQi,2(0.5)
? Qi,2`(0)=(Pi+1 - Pi); Qi,2`(1)=(Pi+2 - Pi+1); 212121
1 1 1
? Qi,2( )= [ ( Qi,2(0) + Qi,2(1)) + Pi+1 ];
? 2 2 2

? Qi,2`( )= Qi,2(1) - Qi,2(0);
? 2
? 二次 B样条曲线的几何意义如图 7.5.2所示。曲线的起点
Qi,2(0)是 Pi Pi+1的中点,曲线的终点 Qi,2(1)是 Pi+1 Pi+ 2的
中点,并且边 Pi Pi+1和 Pi+1 Pi+2是曲线在起点和终点处的
切线。曲线中点 Qi,2(0.5)是中线 Pi+1M的中点,其中 M是
曲线起点 Qi,2(0)和终点 Qi,2(1)连线的中点。二次 B样条曲
线是一条抛物线。
? 由以上关系可知,第 i条二次 B样条曲线仅与 Pi,Pi+1和
Pi+2 三个顶点有关,当型值点的个数 S取多个时 (S>3),相
邻三点都可以确定一段二次 B样条曲线,并且可以保证在
连接处满足 C1连续(因为两条曲线连接处的切矢量相等)。
如图 7.5.3所示。
? ( 2)三次 B样条曲线
? 由于 n=3,所以 l=0,1,2,3,则第 i段曲线的控制点取 Pi,Pi+1, Pi+2和
Pi+3。
? 1 3-0 j 1
? F0,3(t)= ∑(-1)jC3+1 (t + 3 – 0 - j)3 = (-t3 + 3t2 - 3t + 1)
? 3! j=0 6
? 1 3-1 j 1
? F1,3(t)= ∑(-1)jC3+1 (t + 3 – 1 - j)3 = (3t3 - 6t2 + 4)
? 3! j=0 6
? 1 3-2 j 1
? F2,3(t)= ∑(-1)jC3+1 (t + 3 – 2 - j)3 = (-3t3 + 3t2 + 3t + 1)
? 3! j=0 6
? 1 3-3 j 1
? F3,3(t)= ∑(-1)jC3+1 (t + 3 – 3 - j)3 = t3
? 3! j=0 6
? 则第 i段三次 B样条曲线的矩阵表示为:
? 3 1 -1 3 -3 1 Pi
? Qi,3(t)=∑Pi+l Fl,3(t)= [t3 t2 t 1] 3 -6 3 0 Pi+1
? l =0 6 -3 0 3 0 Pi+2
? 1 4 1 0 Pi+3
(式 7-5-3)
? 三次 B样条曲线的端点性质:
? 对 Qi,3(t)求导数,得到:
? 1 -1 3 -3 1 Pi
? Qi,3`(t)= [t2 t 1] 2 -4 2 0 Pi+1
? 2 -1 0 1 0 Pi+2
? Pi+3
?
? 求 Qi,3(t)的二阶导数 Pi
? Qi,3``(t)=[t 1] -1 3 -3 1 Pi+1
? 1 -2 1 0 Pi+2
? Pi+3
? 当 t=0和 1时,分别求出曲线 Qi,3(t)的端点、一阶导数 Qi,3`(t)
和二阶导数 Qi,3``(t)。
? 1 1 *
? 6 3
? Qi,3(0)= ( Pi + 4Pi + 1 + Pi+2 ) = (Pi + 1 + 2 Pi+1 )
? (式 7-5-4)
? 1 1 *
? Qi,3(1)= ( Pi+1 + 4Pi + 2 + Pi+3) = (Pi + 2 + 2 Pi+2 )21
? 6 3
? 1
? Qi,3`(0)= (Pi + 2 - Pi )
? 2
? 1 (式 7-5-5)
? Qi,3`(1)= (Pi + 3 - Pi+1 )
? 2 *
? Qi,3``(0)= 2(Pi - 2Pi + 1 + Pi+2)=2(Pi + 1 - 2 Pi+1)
? *
? Qi,3``(1)= 2(Pi+1 - 2Pi + 2 + Pi+3)=2(Pi + 2 - 2 Pi+2)
(式 7-5-6)
? 其中,
? 三次 B样条曲线的几何意义如图 7.5.4所示。
? 从以上分析可知:
? ( 1)三次 B样条曲线起始点在 Pi+1 P*i+1
的 1/3处,终止点在 Pi+2 P*i+2的 1/3处;
? ( 2)端点处的切线分别平行于 PiPi+2 和
Pi+1 Pi+3;
? ( 3)端点处的二阶导数等于两个平行四
边形的对角线 Pi+1Ri+1和 Pi+2Ri+2 ;
? 7.5.3 三次 B样条曲线性质
? ( 1)连续性
? 为了考查 B样条曲线在连接处的连续性,不仅需要计算
出第 i段曲线终点处的 Qi,3(1),Qi,3`(1),Qi,3``(1),而且还
要求出第 i+1段曲线起始点处的 Qi+1,3(0),Qi+1,3`(0),
Qi+1,3``(0)。将 i+1代入到三次 B样条曲线端点性质公式中,
可以得到下面式子:
? 1
Qi+1,3(0)= ( Pi+1 + 4Pi + 2 + Pi+ 3 )
? 6
? 1
? Qi+1,3`(0)= (Pi + 3 - Pi+1 ) (式 7-5-7)
? 2
? Qi+1,3``(0)= 2(Pi+1 - 2Pi + 2 + Pi + 3)
? 和上面式子进行比较,可知 Qi,3(1)= Qi+1,3(0),Qi,3`(1)=
Qi+1,3`(0),Qi,3``(1)= Qi+1,3``(0)。因此可以得出结论:
三次 B样条曲线在连接处一阶导数、二阶导数都是连续的,
既具有 C0,C1和 C2连续。
? ( 2)局部性
? 从三次 B样条曲线定义的矩阵表示公式 (式 7-5-3)可
以看出,每一段三次 B样条曲线由四个控制点的
位置矢量来决定,而与其它的控制点无关。同时,
在三次 B样条曲线中,改变一个控制点的位置,
最多影响四个曲线段。因而,可以实现对 B样条
曲线的局部修改。
? ( 3)可扩展性
? 从 (式 7-5-3)可以看出,如果增加一个控制点,
就相应地增加一段 B样条曲线。而此时,原
有的 B样条曲线不受影响,并且新增加的一
段曲线与原曲线段的连接处具有 C2连续。
所以,B样条曲线扩展起来很方便。当型值
点的个数为 n时,可以生成( n-3)段连续的
B样条曲线段,从而构成一个复杂而且光滑
的曲线。如图 7.5.5所示,增加一个控制点,
同时生成另一段 B样条曲线。
7.5.4 三次 B样条曲线的程序设计
? 从三次 B样条曲线的定义可知:当 n=3时,
? 3
? Qi,3(t)= ∑Pi+l Fl,3(t)= Pi F0,3(t)+ Pi+1 F1,3(t)+ Pi+2
? l =0
? F2,3(t)+ Pi+ 3 F3,3(t)
? 因为四个调和函数 F0,3(t),F1,3(t),F2,3(t)和 F3,3(t) 已知
(参看公式 7-5-3)因此只要给出四个控制点的位置矢量的
坐标,当 t在 [0,1]范围内取离散地取 100个点时
( dt=0.01),分别求出每一个曲线上点,相邻点用直线段
连接起来,就可以得到相应的 B样条曲线。
? 设控制点的个数为 PointNum,要求 PointNum≥4,则可以生
成( PointNum-3)段三次 B样条曲线。其中第 i段三次 B样
条曲线的代数形式为:
? Qi,3(t)x= Pi x F0,3(t)+ P (i+1) x F1,3(t)+ P
(i+2) x F2,3(t)+ P (i+3) x F3,3(t)
? Qi,3(t)y= Pi y F0,3(t)+ P (i+1) y F1,3(t)+ P
(i+2) y F2,3(t)+ P (i+3) y F3,3(t)
? 其中,i=1,2,…,PointNum-3
? 程序算法如下:(工程名,BSpring)
? (1)将调和函数定义为成员函数,函数形式
如下:
? double CBSpringView::f03(double t)
? {
? return ((-pow(t,3)+3*pow(t,2)-3*t+1)/6);
? }
? double CBSpringView::f13(double t)
? {
? return ((3*pow(t,3)-6*pow(t,2)+4)/6);
? }
? double CBSpringView::f23(double t)
? {
? return ((-3*pow(t,3)+3*pow(t,2)+3*t+1)/6);
? }
? double CBSpringView::f33(double t)
? {
? return (pow(t,3)/6);
? }
? ( 2)编写 OnDraw()函数,程序如下:
? int n,m,pointnum,i,j;
? int x[10],y[10],curx,cury; //(x[i],y[i])为顶点坐标
? double t,dt;
?
? n=3; pointnum=5; //5个顶点,则绘制( 5-3) =2段 B样
条曲线
? x[1]=10;y[1]=200;x[2]=40;y[2]=100;x[3]=100;y[3]=100;
? x[4]=150;y[4]=150;x[5]=150;y[5]=200;
? //绘出特征多边形
? pDC->MoveTo(x[1],y[1]);
? for (i=2;i<=pointnum;i++)
? pDC->LineTo(x[i],y[i]);
? //绘制 B样条曲线
? m=pointnum-n; dt=0.01;
? for (i=1;i<=m;i++) //绘制 m条 B样条曲线
? {
? t=0;
? for (j=0;j<=100;j++) // 绘制每一条 B样条曲线
? {
?
curx=f03(t)*x[i]+f13(t)*x[i+1]+f23(t)*x[i+2]+f33(t)*x[i+3];
?
cury=f03(t)*y[i]+f13(t)*y[i+1]+f23(t)*y[i+2]+f33(t)*y[i+3];
? if (j==0)
? pDC->MoveTo(curx,cury);
? else
? {
? pDC->LineTo(curx,cury);
? t+=dt;
? }
? }
? }
? ( 3)编译程序,查看运行结果。结果与图
7.5.5相似。
? 读者可以添加鼠标功能,进行交互式绘制
三次 B样条曲线。当用鼠标选择四个点时,
绘出第一条 B样条曲线,以后每增加一个点,
就会增加一段 B样条曲线。 Esc键表示鼠标
选择点结束。
7.5.5* 均匀和非均匀 B样条曲线
? 式 7-5-1定义了等距节点的 B样条曲线,即要求 dt=ti+1-ti为
常数,称为均匀 B样条曲线。但是在实际应用中还经常用到
非均匀 B样条曲线,下面给出 B样条曲线通用的定义。
? 定义 1,K阶( K-1次) B样条曲线的数学表达式为:
? n
? C(u)=∑PiNi,k(u) (式 7-5-8)
? i=0
? 其中,Pi为 n+1个控制点中的一个。 Ni,k(u)为调和函数,
也称为基函数,按照 Cox-deBoor递归公式可定义为:
? Ni,1(u)= 1 若 ti≤u<ti+1
? 0 其它
? (u-ti) Ni,k-1(u) (ti+k - u) Ni+1,k-1(u)
? Ni,k(u)= +,
? ti+k-1 –ti ti+k -ti+1
? ( tk-1 ≤u≤tn+k) (式 7-5-9)
? 其中 ti是节点值,T=[t0,t1,…,tn+k构成了 K阶 B样
条函数的节点矢量,其中的节点是非减序列,且
L=n-k+1,表示曲线的段数,如 n=5为控制点个数,
k=4表示 4阶(即三次) B样条曲线,则曲线段数
L=5-4+1=2。
? 当节点沿参数轴是均匀等距分布,即 ti+1-ti=常数,
则表示均匀 B样条函数;当节点沿参数轴的分布
是不等距的,即 ti+1-ti≠常数,则表示非均匀 B样
条函数。
? ( 1)均匀周期 B样条曲线
? 节点的取值 ti =i (0≤i≤n+k),节点向量为
T=[0,1,2,…,n+k]。在此情况下,所有的 Ni,1(u)的
形状是相同的,Ni,1(u)可由 Ni -1,1(u)向右移动一
个单位得到。由此可知,所有的 Ni,k(u)形状也是
相同的,即 Ni,k(u)由 Ni -1,k(u)向右移动一个单位
得到,也就是可由 N0,k(u)向右移位得到。均匀 B
样条的调和函数如图 7.5.6所示。
? 按照均匀 B样条的节点取值,可以得到前面所述
的 B样条简化公式。
? ( 2)均匀非周期 B样条曲线
? 节点的取值规律为
? ti =0, 当 i≤k-1;
? ti =i-k+1, 当 k≤i≤n; (注,n=L+k-1)
? ti =L+1 =n-k+2, 当 i≥L+k=n+1;
? K阶均匀非周期 B样条函数的节点向量 T=[t0,t1,…,
tL+2k-1]= [t0,t1,…,tn+k]
=[0,0,…,0,1,2,…,L,L+1,…,L+1]。例如,对于
k=3,n=6的均匀非周期 B样条函数的节点向量
T=[0,0,0,1,2,3,4,5,5,5]。
? 下面以 n=5,k=3为例,分析其调和函数。节点向量
T=[ t0,t1,…,t8]=[0,0,0,1,2,3,4,4,4],带入 (式 7-5-9)可
得到调和函数 N0,3(u)~ N5,3(u),六个调和函数的
曲线如图 7.5.7所示。
? 参数 t从 0变到( n-k+2) =4,六个调和函数
中可以看到,对于任一 t值,至多有三个调
和函数为非零。因此,六个控制点中至多
有三个影响曲线的局部形状。
7.6 常用的参数曲面
? 7.6.1 曲面的表示
? 曲面是由曲面片拼合而成的。一个曲面片是以曲线为边
界的点的集合。在三维空间中,点的坐标( x,y,z)可用双
参数的单值函数来表示,即:
? x=x(u,w),y=y(u,w),z=z(u,w)
? 曲面片可用三次参数方程来表示为:
? 3 3
? Q(u,w)= ∑ ∑ aijuiwj,其中 u,w∈ [0,1] (式 7-6-1)
? j=0 i=0
? 分析:
? 令 u=w=0,则 Q(0,0)=a00,记为 P00 ;
? u=0,w=1,得到 P01 ;
? u=1,w=0,得到 P10 ;
? u=1,w=1,得到 P11 ;
? ( 2)令 u,w两个参数之一等
于其极限值 0或 1,而另一个
参数在 [0,1]之间变化,就可
以得到 4条边界。
? ( 3)如果令 u=ui,而 w在 [0,1]
之间变化,就可以得到曲面
上的一条曲线 Pui;而如果令
w=wi,而 u在 [0,1]之间变化,
就可以得到曲面上的一条曲
线 Pwi;
? 如果在每个方向上分别采用
Hermite曲线,Bezier曲线或 B
样条曲线,则可以分别得到
三种不同的三次曲面。
7.6.2 孔斯( Coons)曲面
? 由式 7-3-5可知,Hermiter曲线可表示为:
? P(t)=FB=TMB
? 其中,F(t)为调和函数,B=[ P0 P1 R0 R1]T 为
几何矢量。 如果用 Hermite曲线的方式来给定曲
面片四条边界的初始条件,所形成的曲面称为孔
斯( Coons)曲面。 孔斯曲面的四条边界表示为:
? P(u,0)=F(u)[ P00 P10 P00u P10u ] T
? P(u,1)=F(u)[ P01 P11 P01u P11u ] T
? P(0,w)=F(w)[ P00 P01 P00w P01w ] T
(式 7-6-2)
? P(1,w)=F(w)[ P10 P11 P10w P11w ] T
? 式中 F(u)和 F(w)为 Hermite曲线的调和函数,P00u
表示在 u=0,w=0处对 u的切矢量 ? Q(u,w)/?u,
P00w表示在 u=0,w=0处对 w的切矢量 ? Q(u,w)/
?w,为了联立方程求出式 7-6-1中 a00到 a33 共 16个
系数,还需要定义四个端点处的扭矢量。扭矢量
定义为:
? ?2 Q(u,w)
? Puw= ?u?w
? 因此,孔斯曲面的已知条件是四个位置矢量 [P00
P01 P10 P11]和八个切矢量 [P00u P10u P01u
P11u P00w P01w P10w P11w]和四个扭矢量
[P00uw P10uw P01uw P11uw],通过求出式 7-6-1
中 a00到 a33 共 16个系数,就可以确定出一个双三
次曲面片方程。如图 7.6.2所示。
7.6.3 贝塞尔( Bezier)曲面
? Bezier曲线段是由它的特征多边形顶点来决定的,
而 Bezier曲面片则是由特征多面体的顶点来决定的,
其数学表示式如下,
? m n
? Q(u,w)=∑ ∑PijBi,m(u)Bj,n(w), u,w∈ [0,1] (式 7-6-3)
? i=0 j=0
? 其中,Pij是特征多面体各顶点的位置矢量,共计
(m+1)× (n+1)各顶点。 Bi,m(u)和 Bj,n(w)是伯恩斯
坦多项式。 m和 n不一定相等,如果 m=n=3,则由
4× 4=16个顶点构造特征多面体,其相应的 Bezier
曲面片称为双三次 Bezier 曲面片。如图 7.6.3所示。
双三次 Bezier曲面片可以用矩阵表示为:
? Q(u,w)=Fb(u)PFb(w)T
? 其中,P11 P12 P13 P14
? P= P21 P22 P23 P24
? P31 P32 P33 P34
? P41 P42 P43 P44
? Fb(u)=[ Fb1(u) Fb2(u) Fb3(u) Fb4(u)]
? =[(1-u)3 3u(1-u)2 3u2(1-u) u3 ]
? -1 3 -3 1
? =[u3 u2 u 1] 3 -6 3 0 = UMb
? -3 3 0 0
? 1 0 0 0
? Fb(w)=[ Fb1(w) Fb2(w) Fb3(w) Fb4(w)]
? =[(1-w)3 3w(1-w)2 3w2(1-w) w3 ]
? -1 3 -3 1
? =[w3 w2 w 1] 3 -6 3 0 = WMb
? -3 3 0 0
? 1 0 0 0
? 矩阵 P表示出双三次 Bezier曲面片的特征多
面体 16个控制点的位置矢量。显而易见,
只有 4个顶点 P11,P14,P41,P44位于
Bezier曲面上,P矩阵中周围的 12个控制点
定义了 4条三次 Bezier曲线,即边界曲线。
其余的 4个点 P22,P32,P23,P33与边界曲
线无关,但是它们的影响曲面片的形状。
7.6.4 B样条曲面
? B样条曲面是 B样条曲线的拓广。一块 m× n次 B样
条曲面片的数学表示式如下:
? m n
? Q(u,w)=∑∑PijFi,m(u)Fj,n(w), u,w∈ [0,1] (式 7-
6-4)
? i=0 j=0
? 其中,Pij( i=0,1,…,m;j=0,1,…,n)是定义此曲面
片的顶点位置矢量,共计( m+1) (n+1)个顶点。
Fi,m(u)Fj,n(w)是 B样条的调和函数,u,w为参数。
m与 n不一定相等,当 m=n=3时,则由 4× 4个顶点
构成特征多面体,相应的 B样条曲面片称为双三
次 B样条曲面片。如图 7.6.4所示。
? 已知曲面的控制点 Pij( i,j=0,1,2,3),构造
双三次 B样条曲面的步骤如下:
? ( 1)沿 w方向构造 Pi( w)均匀三次 B样条
曲线,i=0,1,2,3。
? P0( w) =[P00 P01 P02 P03 ]MBTWT
? P1( w) =[P10 P11 P12 P13 ]MBTWT
? P2( w) =[P20 P21 P22 P23 ]MBTWT
? P3( w) =[P30 P31 P32 P33 ]MBTWT
? (2) 再沿着 u方向构造均匀三次 B样条曲线。
此时可以认为顶点沿 Pi( w)滑动,每组顶
点对应相同的 w,当 w值由 0到 1连续变化,
即形成 B样条曲面。表达式为:
? P0( w)
? Q(u,w)= UMB P1( w) = UMBP MBTWT,
? P2( w)
? P3( w)
P00 P01 P02 P03
? P = P10 P11 P12 P13
? P20 P21 P22 P23
? P30 P31 P32 P33
? 1 1 3 -3 1
? MB = 3 -6 3 0
? 6 -3 0 3 0
? 1 4 1 0