[互联网]计算机图形徐教程曲线和曲面1.doc

上传人:音乐台 文档编号:1967128 上传时间:2019-01-27 格式:DOC 页数:56 大小:931KB
返回 下载 相关 举报
[互联网]计算机图形徐教程曲线和曲面1.doc_第1页
第1页 / 共56页
[互联网]计算机图形徐教程曲线和曲面1.doc_第2页
第2页 / 共56页
[互联网]计算机图形徐教程曲线和曲面1.doc_第3页
第3页 / 共56页
亲,该文档总共56页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《[互联网]计算机图形徐教程曲线和曲面1.doc》由会员分享,可在线阅读,更多相关《[互联网]计算机图形徐教程曲线和曲面1.doc(56页珍藏版)》请在三一文库上搜索。

1、曲线和曲面第一节 Hermite多项式1.1 三次Hermite多项式Hermite多项式是非常有用的曲线形式。三次Hermite多项式就是一类常用的曲线,因为它们提供了对形状的局部控制,并且提供了C1连续性。若给定参数方程f(t)在起点和终点的位置、和一阶导数、,则可以利用下式构造一个三次Hermite多项式:式中式(t)就是对于函数f(t)的Hermite插值多项式,矩阵H称为Hermite矩阵绘制三次Hermite曲线,用户必须指定位置和导数,所以必须提供针对导数的特别界面。一种方式是通过用户通过鼠标确定曲线的起点和终点的位置,并给出起点和终点的导数,即可给出三次Hermite多项式所需

2、的插值信息。1.2 Hermite曲线绘制的程序设计根据给出的三次Hermite多项式,利用逐点绘制的方法即可实现三次Hermite多项式的绘制。程序“Hermite”的设计步骤如下:(1) 创建工程名称为“Hermite”单文档应用程序框架。(2) 添加消息处理函数。利用ClassWizard(类向导)为应用程序添加与菜单项相关的消息处理函数,ClassName栏中选择CHermiteView,根据表 1建立如下的消息映射函数,ClassWizard会自动完成有关的函数声明。表 1 菜单项的消息处理函数标示符ID消息消息处理函数CHermiteViewWM_LBUTTONDOWNOnLBut

3、tonDown(UINT nFlags, CPoint point);CHermiteViewWM_LBUTTONUPOnLButtonUp(UINT nFlags, CPoint point);CHermiteViewWM_MOUSEMOVEOnMouseMove(UINT nFlags, CPoint point);(3) 添加函数。在工程中添加应用函数的方法,这里先在HermiteView.h中声明需要使用的函数名称,然后再在HermiteView.cpp中定义此函数。/ HermiteView.h : interface of the CHermiteView class/const

4、int N=3;/N次Hermite曲线const int npoints=50;/由npoints+1个点构成的折线逼近Hermite曲线class Point/二维平面点Point类public:double x,y;/二维平面中的点坐标为双精度浮点小数Point()x=0;y=0;/构造函数Point(double _x,double _y)x=_x;y=_y;/构造函数Point(CPoint p)x=p.x;y=p.y;/构造函数inline Point operator =(Point p)x=p.x;y=p.y;return (*this);/Point对象的赋值运算inline

5、 Point operator =(CPoint p)x=p.x;y=p.y;return (*this);/CPoint对象的赋值运算inline Point operator +=(Point p)x+=p.x;y+=p.y;return (*this);/重载+=运算inline Point operator +=(CPoint p)x+=p.x;y+=p.y;return (*this);/重载+=运算inline Point operator -=(Point p)x-=p.x;y-=p.y;return (*this);/重载-=运算inline Point operator -=

6、(CPoint p)x-=p.x;y-=p.y;return (*this);/重载-=运算inline Point operator *=(double s)x*=s;y*=s;return (*this);/重载*=运算inline Point operator /=(double s)x/=s;y/=s;return (*this);/重载/=运算inline Point operator +(Point p)Point t;t.x=x+p.x;t.y=y+p.y;return (t);/重载+运算inline Point operator +(CPoint p)Point t;t.x=

7、x+p.x;t.y=y+p.y;return (t);/重载+运算inline Point operator -(Point p)Point t;t.x=x-p.x;t.y=y-p.y;return (t);/重载-运算inline Point operator -(CPoint p)Point t;t.x=x-p.x;t.y=y-p.y;return (t);/重载-运算inline Point operator *(double s)Point t;t.x=x*s;t.y=y*s;return (t);/重载*运算inline Point operator /(double s)Point

8、 t;t.x=x/s;t.y=y/s;return (t);/重载/运算inline operator CPoint()return CPoint(int)x,(int)y);/类型强制转换运算;class CHermiteView : public CView. .public:int m_nCount;/记录鼠标左键按下的次数CPoint m_Newpoint;/记录鼠标移动时的位置坐标Point ptControlPtsN+1;/曲线控制点坐标Point ptPtsnpoints+1;/逼近曲线的折线点坐标public:void hermite_to_points(Point CP, P

9、oint pts, int npoints);/计算Hermite曲线上各点的坐标值Point hermite(Point V, double u);/计算Hermite曲线在参数为u的坐标值. ./ Generated message map functionsprotected:/AFX_MSG(CHermiteView)afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT

10、nFlags, CPoint point);/AFX_MSGDECLARE_MESSAGE_MAP();/ HermiteView.cpp : implementation of the CHermiteView class/CHermiteView:CHermiteView()m_nCount=0;/鼠标左键按下的次数初始化为0void CHermiteView:OnLButtonDown(UINT nFlags, CPoint point) ptControlPtsm_nCount=point;/保存鼠标左键按下的当前位置m_Newpoint=point;/存放画线的起始位置m_nCoun

11、t=(+m_nCount)%(N+1);/记录鼠标左键按下的次数,次数=N+1时,归零CView:OnLButtonDown(nFlags, point);void CHermiteView:OnLButtonUp(UINT nFlags, CPoint point) int i;if(m_nCount=0)/m_nCount为0时,说明鼠标左键按下的次数为N+1的整数倍,绘制曲线CClientDC dc(this);CPen pen,*oldpen;pen.CreatePen (PS_SOLID,1,RGB(255,0,0);/创建红色实线画笔,线宽为1oldpen=dc.SelectObj

12、ect (&pen);/选择新画笔hermite_to_points(ptControlPts, ptPts, npoints);/当控制点的个数满足要求时,计算Hermite曲线上各点位置dc.MoveTo (ptPts0);/将Hermite曲线上各点位置相连,绘制Hermite曲线for(i=1;i0&m_nCount=N&m_nCount%2=1)/绘制曲线起点和终点的切向量CClientDC dc(this);dc.SetROP2(R2_NOT); /设置绘图模式,以屏幕颜色的相反色绘图 /以重绘的方式擦除前一个OnMouseMove绘制的直线dc.MoveTo(CPoint)ptC

13、ontrolPtsm_nCount-1);/擦除前面刚绘制的一条直线dc.LineTo(m_Newpoint);dc.MoveTo(CPoint)ptControlPtsm_nCount-1);/从起始位置到当前位置绘制一条新的直线dc.LineTo(point);m_Newpoint=point; /存放当前鼠标位置CView:OnLButtonUp(nFlags, point);/输入参数CP为控制点坐标/控制点CP的个数为N+1/输出参数为Hermite曲线上的离散点序列pts/离散点pts的个数为npoints+1void CHermiteView:hermite_to_points(

14、Point CP, Point pts, int npoints)double u,delt;Point PN+1,VN+1;delt=1/(double)(npoints);/将参数u变化区间进行npoints等分u=0;/Hermite矩阵与控制点坐标相乘,得到VP0 = CP0;P1 = CP2;P2 = CP1 - CP0;P3 = CP3 - CP2;V0 = P0 * 2 - P1 * 2 + P2 + P3;V1 = P0 * (-3) + P1 * 3 - P2 * 2 - P3;V2 = P2;V3 = P0;for(int i=0;i=0;i-)Ui = Ui+1 * u;

15、 /形成多项式中的各项pts += Vi * Ui; /与系数矩阵V相乘,并与前面得到的多项式值相累加return pts;Hermite曲线绘制的运行结果如图 1所示。图中的直线为起点和终点的切向量,曲线为相应的Hermite曲线。图 1 Hermite曲线绘制的运行结果第二节 Coons曲面2.1 Coons双三次曲面片Hermite多项式处理曲线的方法可以加以推广,用以处理曲面,即若给定参数曲面在四个角点处的位置向量、切向量、跨界切向量和扭曲向量,则利用张量积方法对Hermite多项式在二维曲面上加以扩展,即可给出Coons曲面的表达式,构造Coons曲面片。对于二维曲面P(u,w),指

16、定四个角点的位置向量P(0,0),P(0,1),P(1,0),P(1,1),以及在这些点上的切向量P w(0,0),P w(0,1),P w(1,0),P w(1,1),P u(0,0),P u(0,1),P u(1,0),P u(1,1)和扭曲向量P uw(00),P uw(0,1),P uw(1,0),P uw(1,1),然后,通过Hermite插值计算出边界曲线和跨界切向量,再采用张量积方法来构造曲面片,得到:式中矩阵H为Hermite矩阵,M是关于角点的信息矩阵,HT是H的转置,0u1,0w1。不难看出,式中的Hermite矩阵H定义了边界切向量所用的混合函数。此时曲面片完全由四边形域

17、角点信息矩阵所确定。这种类型的曲面片由三次Hermite基来张成,称之为张量积曲面片。又因固定u或w时对w或u而言是三次,因而它被称为Coons双三次曲面片。式可用于定义双三次的参数曲面片。这种方法有广泛的应用,但也有不足之处,主要是要求事先给出的信息较多。位置向量、切向量和跨界切向量几何意义清楚。但是,插值角点处的扭曲向量很难指定并缺乏直观含义,使数据调整比较困难。用多个这样的曲面片拼接形成大的曲面时,彼此拼接的两个曲面片的信息矩阵要满足一定的约束条件。可以证明,在曲面拼接时,只要具有相同的角点信息,就能保证曲面拼接的结果达C2连续。2.2 Coons曲面绘制的程序设计下面给出了构造双三次C

18、oons曲面的主要的程序代码和注释。在该例子中,观察点设为(-10,-10,10),投影平面与原点间的距离设为5。绘制Coons曲面时,程序预先给出Coons曲面的四个角点以及在该角点上的切向量和扭曲向量。设在平面上有四点,其位置向量分别为(0,0,0),(0,0.75,0),(0.75,0,0),(0.75,0.75,0)。该四点的位置向量、切向量、跨界切向量和扭曲向量,定义在角点的信息矩阵M中,这些信息在视图类的构造函数中被初始化:程序“Coons”的设计步骤如下:(1) 创建工程名称为“Coons”单文档应用程序框架。(2) 添加函数。在工程中添加应用函数的方法,这里先在CoonsVie

19、w.h中声明需要使用的函数名称,然后再在CoonsView.cpp中定义此函数。/ CoonsView.h : interface of the CCoonsView class/const int N=3;/双3次Coons曲面const int npoints=50;/由(npoints+1)*(npoints+1)个点构成的网格逼近Coons曲面class Point3D/三维空间点Point3D类public:double x,y,z;/三维空间中的点坐标为双精度浮点小数Point3D()x=0;y=0;z=0;/构造函数Point3D(double _x,double _y,doub

20、le _z)x=_x;y=_y;z=_z;/构造函数Point3D(double s)x=s;y=s;z=s;/构造函数Point3D operator =(Point3D p)x=p.x;y=p.y;z=p.z;return (*this);/Point3D对象的赋值运算Point3D operator +=(Point3D p)x+=p.x;y+=p.y;z+=p.z;return (*this);/重载+=运算Point3D operator -=(Point3D p)x-=p.x;y-=p.y;z-=p.z;return (*this);/重载-=运算Point3D operator

21、*=(double s)x*=s;y*=s;z*=s;return (*this);/重载*=运算Point3D operator /=(double s)x/=s;y/=s;z/=s;return (*this);/重载/=运算Point3D operator +(Point3D p)Point3D t;t.x=x+p.x;t.y=y+p.y;t.z=z+p.z;return (t);/重载+运算Point3D operator -(Point3D p)Point3D t;t.x=x-p.x;t.y=y-p.y;t.z=z-p.z;return (t);/重载-运算Point3D opera

22、tor *(double s)Point3D t;t.x=x*s;t.y=y*s;t.z=z*s;return (t);/重载*运算Point3D operator /(double s)Point3D t;t.x=x/s;t.y=y/s;t.z=z/s;return (t);/重载/运算friend Point3D operator *(double s,Point3D p)Point3D t;t.x=p.x*s;t.y=p.y*s;t.z=p.z*s;return (t);/重载*运算;class CCoonsView : public CView. .public:Point3D ptC

23、ontrolPts(N+1) * (N+1);/曲面角点的信息矩阵Point3D ptPts(npoints+1) * (npoints+1);/逼近曲面的网格点坐标public:void coons_to_points(Point3D CP, Point3D pts);/计算Coons曲面上各点的坐标值Point3D coons(Point3D V, double u, double w);/计算Coons曲面在参数为u和w时的坐标值void DrawSurface(CDC* pDC,Point3D ptPts,Point3D VLoca,double Vz);/绘制Coons曲面templ

24、ate void Transpose(T ptPts);/矩阵转置运算void Product(double V, double p);/矩阵乘积运算CPoint worldtoview(Point3D pt, Point3D VLoca,double Vz);/由世界坐标到观察坐标,再到屏幕坐标的变换long dtxs(double x);/由观察坐标到屏幕坐标的变换(x轴)long dtys(double y);/由观察坐标到屏幕坐标的变换(y轴). .;/ CoonsView.cpp : implementation of the CCoonsView class/#include ma

25、th.hCCoonsView:CCoonsView()/角点信息矩阵初始化double k=0.75;ptControlPts0 = Point3D(0,0,0) * k;ptControlPts1 = Point3D(0,1,0) * k;ptControlPts2 = Point3D(-1,1,1) * k;ptControlPts3 = Point3D(1,1,1) * k;ptControlPts4 = Point3D(1,0,0) * k;ptControlPts5 = Point3D(1,1,0) * k;ptControlPts6 = Point3D(-1,1,1) * k;pt

26、ControlPts7 = Point3D(-1,1,1) * k;ptControlPts8 = Point3D(1,1,0) * k;ptControlPts9 = Point3D(1,1,0) * k;ptControlPts10 = Point3D(-1,-1,-1) * k;ptControlPts11 = Point3D(1,1,1) * k;ptControlPts12 = Point3D(1,-1,0) * k;ptControlPts13 = Point3D(1,-1,0) * k;ptControlPts14 = Point3D(1,1,1) * k;ptControlPt

27、s15 = Point3D(-1,-1,-1) * k;void CCoonsView:OnDraw(CDC* pDC)coons_to_points(ptControlPts, ptPts);/计算Coons曲面上各点的坐标值Point3D viewpoint=Point3D(-10,-10,10);/给定观察点viewpointDrawSurface(pDC,ptPts,viewpoint,5);/绘制Coons曲面/输入参数CP为角点信息矩阵/信息矩阵CP的个数为(N+1)*(N+1)/输出参数为Coons曲面上的离散点网格pts/网格点pts的个数为(npoints+1)*(npoin

28、ts+1)void CCoonsView:coons_to_points(Point3D CP, Point3D pts)double u,w,delt;delt=1/(double)npoints;/将参数u和w变化区间进行npoints等分u=w=0;for(int i=0;i=npoints;i+)u=0;for(int j=0;j=npoints;j+)pts i*(npoints+1)+j= coons (CP, u, w); /分别求出(npoints+1)*(npoints+1)个离散点网格pts的坐标u+=delt;w+=delt;/输入参数V为角点信息矩阵,作为系数矩阵/u和

29、w为参数值,其变化区间为0,1/函数返回值为Coons曲面在参数为u和w时的坐标值Point3D CCoonsView:coons(Point3D V, double u, double w)Point3D ptsN+1,pt;double UN+1,WN+1;int i,j;Product(U, u);/U为Hermite矩阵与u为参数的多项式中的各项相乘的乘积Product(W, w);/W为Hermite矩阵与w为参数的多项式中的各项相乘的乘积pt=Point3D(0,0,0);for(i=0;i=N;i+)ptsi=Point3D(0,0,0);for(j=0;j=N;j+)ptsi+

30、=Vi*(N+1)+j*Wj;/与系数矩阵W相乘,并与前面得到的多项式值相累加pt+=ptsi*Ui;/与系数矩阵U相乘,并与前面得到的多项式值相累加return pt;/绘制Coons曲面/pDC为设备环境指针/ptPts为Coons曲面上的网格点/VLoca为观察点/Vz为投影平面与原点间的距离void CCoonsView:DrawSurface(CDC* pDC,Point3D ptPts,Point3D VLoca,double Vz)int i;CPoint ptDrawPts(npoints+1) * (npoints+1);for(i=0;i(npoints+1) * (npo

31、ints+1);i+)ptDrawPtsi = worldtoview(ptPtsi, VLoca, Vz);/将Coons曲面上的网格点ptPts全部转换为屏幕坐标for(i=0;iPolyline(&ptDrawPtsi*(npoints+1),npoints+1);/绘制u方向的网格线Transpose(ptDrawPts);/对网格点ptPts转置for(i=0;iPolyline(&ptDrawPtsi*(npoints+1),npoints+1);/绘制w方向的网格线Transpose(ptDrawPts);/对网格点ptPts再次转置,恢复为原来的网格点/矩阵转置运算templa

32、te void CCoonsView:Transpose(T ptPts)T temp;for(int i=0;i=npoints;i+)for(int j=i+1;j=0;i-)Pi = Pi+1 * p;/Pi保存多项式中的各项/Hermite矩阵与多项式中的各项相乘,得到VV0 = P0 * 2 - P1 * 3 + P3;V1 = P0 * (-2) + P1 * 3;V2 = P0 - P1 * 2 + P2;V3 = P0 - P1;/由世界坐标变为观察坐标,并透视投影到视平面,最后转换为屏幕坐标CPoint CCoonsView:worldtoview(Point3D pt, P

33、oint3D VLoca,double Vz)double s=1800;CPoint qt;double aa,bb,cc,xw,yw,zw,xe,ye,ze,uu,vv;xw=pt.x;yw=pt.y;zw=pt.z;aa=VLoca.x;bb=VLoca.y;cc=VLoca.z;uu=sqrt(aa*aa+bb*bb+cc*cc); vv=sqrt(aa*aa+bb*bb);if( !uu ) xe=xw;ye=yw;ze=zw;else if( !vv ) xe=xw;ye=yw;ze=zw+cc;else xe=-bb*xw/vv+aa*yw/vv;ye=-aa*cc*xw/(uu

34、*vv)-bb*cc*yw/(uu*vv)+vv*zw/uu;ze=-aa*xw/uu-bb*yw/uu-cc*zw/uu+uu; qt.x=(long)dtxs(s*xe*Vz/ze);qt.y=(long)dtys(s*ye*Vz/ze);return qt;/由观察坐标变为屏幕坐标long CCoonsView:dtxs(double x)CRect rect;GetClientRect(&rect);return(long)(rect.right/2 +x);/由观察坐标变为屏幕坐标long CCoonsView:dtys(double y)CRect rect;GetClientRe

35、ct(&rect);return(long)(rect.bottom-y);Coons曲面绘制的运行结果如图 2所示。图 2 Coons曲面绘制的运行结果第三节 Bzier曲线在计算机图形学中,最重要的两类拟合曲线是Bzier曲线和B样条曲线。Bzier曲线是自由形式曲线最普遍的一种表示方法。曲线以Pierre Bzier的名字命名。Bzier曲线是一条多项式的曲线,近似地表示它的控制点。曲线可以是任何次数的多项式。一条n次曲线由n+1个控制点来控制。曲线对第一个点和最后一个点插值,其形状直接受其它的控制点的影响。Bzier曲线的绘制有多种方法,下面分别加以介绍。3.1 直接绘制法绘制Bzie

36、r曲线最直接的办法就是根据其定义式来加以绘制。给定型值点P0,P1,Pn,它们所确定的n次Bzier曲线是:式中基函数Bi,n(t)是Bernstein多项式:式中可能涉及到的0!及00,按约定均为1。这里Bzier曲线可以看做是n+1个混合函数混合给定的n+1个顶点而产生的,混合函数用Bernstein多项式,所生成曲线是n次多项式。通常n+1个顶点也称为控制点,依次连接各控制点得到的多边形称为控制多边形。在n=3时,式成为:这是一条三次参数多项式曲线。三次(n=3)Bzier曲线通常被用来组成复杂的曲线。三次Bzier曲线易于控制,有大量有用的性质,并且使用Bzier曲线有许多非常有效的算

37、法。通常,复杂的形状是通过连接许多低次的Bzier曲线形成的。绘制Bzier曲线时,给定各控制点,则可以利用其定义式,对参数t选取足够多的值,计算曲线上的一些点,然后用折线连接来近似画出实际的曲线。随着选取点增多,折线和曲线可以任意接近。3.2几何作图法除了前面介绍的直接绘制法之外,可以利用Bzier曲线的性质得到其它一些绘制Bzier曲线的方法,首先介绍几何作图法。几何作图法也称为de Casteljau算法,它利用了Bzier曲线的分割递推性实现Bzier曲线的绘制。为了说明几何作图法,需要注意到以下事实。记点Pk,Pk+l,Pk+n可以生成的Bzier曲线为,0t1,则下面的递推关系成立

38、:式的含义是:由点P0,P1,Pn所确定的n次Bzier曲线在点t的值,可以由点P0,P1,Pn-1所确定的n-1次Bzier曲线在点t的值,与由点P1,P2,Pn所确定的n-1次Bzier曲线在点t的值,通过式给出的线性组合简单地求得。式可以改写为:式和式表明n次Bzier曲线上控制点在t时的值P(t),可以归结为计算两个n-1次Bzier曲线在t的值的线性组合,这一过程可以继续下去。图 3可看做是实施这一做法的示意图。图中己知三次Bzier曲线的控制顶点为P0,P1,P2,P3,将其设为初始值P0(0),P1(0),P2(0) ,P3(0)。递归计算先按t的比例在控制多边形各边上求得P0(

39、1),P1(1),P2(1),再求得P0(2),P1(2),最后求得P0(3),即为P(t)对应的点。图 3 Bzier曲线的几何作图法下面是依据式写出的Bzier曲线几何作图算法。/输入参数P为控制点坐标/控制点P的个数为n+1/输出参数为采用几何作图算法生成的Bzier曲线上的离散点序列pts/离散点序列pts的个数为npoints+1void bez_to_points(Point P, int n, Points pts, int npoints)double t,delt;delt=1.0/(double)npoints;/将参数t变化区间进行npoints等分t=0.0;for(i

40、nt i=0;i=npoints;i+)pts i=decas(P, n, t); /分别求出npoints+1个离散点pts的坐标t+=delt;/输入参数为控制点坐标/控制点P的个数为n +1/t为参数值,其变化区间为0,1/函数返回值为Bzier曲线在参数为t的坐标值Point decas(Point P, int n, double t)int m,i;Point *R, *Q, P0;R = new Point n +1;Q = new Point n +1;for(i=0;i0;m-)/作m次内部循环,/每次循环计算控制多边形上一条边以参数t为分割比例的坐标值for(i=0;i= m -1;i+)/n次Bzier曲线在点t的值,可由两条n-1次Bzier曲线/在点t的值通过线性组合而求得Qi= Ri +t*( Ri+1

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1