贝齐尔曲面绘制doc.docx
《贝齐尔曲面绘制doc.docx》由会员分享,可在线阅读,更多相关《贝齐尔曲面绘制doc.docx(25页珍藏版)》请在冰豆网上搜索。
![贝齐尔曲面绘制doc.docx](https://file1.bdocx.com/fileroot1/2023-2/3/f037eaa5-1ff6-4c87-ad69-e13166186f05/f037eaa5-1ff6-4c87-ad69-e13166186f051.gif)
贝齐尔曲面绘制doc
1绪论
1.1贝齐尔曲面的介绍
到了70年代,法国雷诺汽车公司的工程师贝齐尔(Bezier)创造出一种适用于几何体外形设计的新的曲线表示法。
这种方法的优越性在于:
对于在平面上随手勾画出的一个多边形(称为特征多边形),只要把其顶点坐标输入计算机,经过不到一秒钟的计算,绘图机就会自动画出同这个多边形很相像、又十分光滑的一条曲线。
这种方法被人们称为贝齐尔(Bezier)方法(以下统称为Bezier方法)。
贝齐尔曲线的形状是通过一组多边折线(也称为贝齐尔控制多边形)的各顶点惟一地定义出来的。
在该多边折线的各顶点中,只有第一点和最后一点在曲线上,其余的顶点则用来定义曲线的形状。
图1-1列举了一些Bezier多边折线和相应的Bezier曲线的形状关系。
图1-1Bezier曲线
曲线和曲面是计算机图形学中研究的重要内容之一,他们在实际工作中有着广泛的应用。
例如,实验数据的曲线表示,设计、优化的曲面表示等。
为了外形美观和物理性能最佳,汽车飞机等的外型设计十分重要。
由于实际问题不断对曲线和曲面提出新的要求,近几十年来,曲线和曲面理论及其应用得到了很大的发展。
1963年,波音飞机公司的Ferguson将曲线曲面表示成参数矢量形式,并用3次参数曲线来构造组合曲线,用4个角点的位置矢量及其两个方向的切向矢量来构造3次曲面。
1964年,麻省理工学院的coons用封闭的曲线的4条边界定义一个曲面。
同年,Schoenberg给出了参数样条曲线和曲面的形式。
1971年,法国雪铁龙汽车公司的DeVasteljau独立地研究出与Bezier类似的方法。
1972年,DeBoor给出了B样条的标准计算方法。
1974年,美国通用汽车公司的Gordon和Riesenfeld将B样条用于形状描述,提出了B样条曲线和B样条曲面。
1975年,美国锡拉丘兹大学的Versprill在其博士论文中提出了有理B样条方法。
19世纪80年代后期,美国的Piegl和Tiller将有理B样条发展成为非均匀有理B样条方法。
非均匀有理B样条方法已成为当今自由曲线和曲面描述的通用方法,可以统一表示初等解析曲线和曲面、有理与非有理Bezier曲线和曲面以及有理与非有理B样条曲线和曲面。
1.2贝齐尔曲面的应用
曲面造型(SurfaceModeling)是计算机辅助几何设计(ComputerAidedGeometricDesign,CAGD)和计算机图形学(ComputerGraphics)的一项重要内容,主要研究在计算机图像系统的环境下对曲面的表示、设计、显示和分析。
它起源于汽车、飞机、船舶、叶轮等的外形放样工艺,由Coons、Bezier等大师于二十世纪六十年代奠定其理论基础。
如今经过三十多年的发展,曲面造型现在已形成了以有理B样条曲面(RationalB-splineSurface)参数化特征设计和隐式代数曲面(ImplicitAlgebraicSurface)表示这两类方法为主体,以插值(Interpolation)、拟合(Fitting)、逼近(Approximation)这三种手段为骨架的几何理论体系。
曲面造型是指在产品设计中对于曲面形状产品外观的一种建模方法,曲面造型方法使用三维CAD软件的曲面指令功能构建产品的外观形状曲面并得到实体化模型。
在不同的三维软件比如ProE、UG、CATIA和Solidworks中所使用的指令有所差别,但基本的造型策略都是类似的。
形状信息的核心问题是计算机表示,即要解决既适合计算机处理,且有效地满足形状表示与几何设计要求,又便于形状信息传递和产品数据交换的形状描述的数学方法。
1971年法国雷诺汽车公司的Bezier提出一种由控制多边形设计曲线的新方法。
这种方法不仅简单易用,而且漂亮地解决了整体形状控制问题,把曲线曲面的设计向前推进了一大步,为曲面造型的进一步发展奠定了坚实的基础。
但Bezier方法仍存在连接问题和局部修改问题。
到1972年,de-Boor总结、给出了关于B样条的一套标准算法,1974年Gordon和Riesenfeld又把B样条理论应用于形状描述,最终提出了B样条方法。
这种方法继承了Bezier方法的一切优点,克服了Bezier方法存在的缺点,较成功地解决了局部控制问题,又轻而易举地在参数连续性基础上解决了连接问题,从而使自由型曲线曲面形状的描述问题得到较好解决。
但随着生产的发展,B样条方法显示出明显不足,不能精确表示圆锥截线及初等解析曲面,这就造成了产品几何定义的不唯一,使曲线曲面没有统一的数学描述形式,容易造成生产管理混乱。
曲面造型由于其实用性,在航空航天、汽车制造、造船、机械制造、电子、电器、消费品行业得到广泛应用。
它的集成解决方案覆盖所有的产品设计与制造领域,满足了工业领域各类大、中、小型企业的需要。
2贝齐尔曲面设计
2.1贝齐尔曲面定义
设
为
个空间点列,则m×n次Bezier曲面定义为:
(式2-1)
其中
,
是Bernstein基函数。
依次用线段连接点列中相邻两点所形成的空间网格,称之为特征网格。
Bezier曲面的矩阵表示式是:
(式2-2)
在一般实际应用中,n、m不大于4。
(1)双线性Bezier曲面
当m=n=1时
u,w∈[0,1](式2-3)
定义一张双线性Bezier曲面。
已知四个角点之后,则
(式2-4)
(2)双二次Bezier曲面
当m=n=2时
(式2-5)
由此式定义的曲面,其边界曲线及参数坐标曲线均为抛物线。
(3)双三次Bezier曲面
当m=n=3时
(式2-6)
(式2-7)
其矩阵表示为
(式2-8)
2.2贝齐尔曲面性质
1.Bezier曲面特征网格的四个角点正好是Bezier曲面的四个角点,即
P(0,0)=P00P(1,0)=PM0P(0,1)=P0NP(1,1)=PMN
2.Bezier曲面特征网格最外一圈顶点定义Bezier曲面的四条边界;Bezier曲面边界的跨界切矢只能与定义该边界的顶点及相邻一排顶点有关,且
P00P10P01,P0nP1nP0,n-1,Pm0Pm-1,0Pm1,
分别是四个角点的切平面;跨界二阶导矢只与定义该边界的及相邻两排顶点有关。
几何不变性、凸包性、对称性等性质可由Bezier曲线的相关性质容易推广得到。
图2-1阴影三角形
2.3贝齐尔曲面算法
Bezier曲线的递推(deCasteljau)算法,可以推广到Bezier曲面的情形。
若给定Bezier曲面特征网格的控制顶点:
和一对参数值(u,v),则:
式(2-9)
一条曲线可以表示成两条低一次曲线的组合,一张曲面可以表示成低一次的四张曲面的线性组合。
其中:
式(2-10)
或:
式(2-11)
上面给出了确定曲面上一点的两种方案。
当按
(1)式方案执行时,先以u参数值对控制网格u向的n+1个多边形执行曲线deCasteljau算法,m级递推后,得到沿v向由n+1个顶点
构成的中间多边形。
再以v参数值对它执行曲线的deCasteljau算法,n级递推以后,得到一个
,即所求曲面上的点。
也可以按
(2)式方案执行,先以v参数值对控制网格沿v向的m+1个多边形执行n级递推,得沿u向由m+1个顶点
构成的中间多边形。
再以u参数值对它执行n级递推,得所求点
。
2.4程序设计步骤
2.4.1Bezier曲面的生成
Bezier曲面是基于Beizer曲线而定义的,有特征网格决定其大致形状,而特征网格是由控制点确定的。
因而,绘制Bezier曲面的步骤与绘制Bezie曲面的步骤是一致的:
第一,定义控制点序列;
第二,定义一个二维评价器;
第三,激活二维评价器;
最后,创建网格。
定义一个二维评价器的函数为:
glMap2d()或glMap2f()函数,glMap2d()函数的原型为:
VoidglMap2d(GLenumtarget,GLdoubleu1,GLdoubleu2,Glintustride,
Glintuorder,GLdoublev1,GLdoublev2,Glintvorder,
Glintuorder,constGLdouble*points);
其中,target参数表示评价器最后生成的坐标类别,它可以取表2-1中的一个常量:
常量
含义
GL_MAP2_VERTEX_3
用(x,y,z)描述一个控制点
GL_MAP2_VERTEX_4
用(x,y,z,w)描述一个控制点
GL_MAP2_INDEX
控制点代表一个颜色素引值
GL_MAP2_COLOR_4
控制点是RGBA颜色值
GL_MAP2_NORMAL
控制点是一个法线向量
GL_MAP2_TEXTURE_COORD_1
控制点是一个纹理坐标的s分量
GL_MAP2_TEXTURE_COORD_2
控制点是一个(s,t)纹理坐标
GL_MAP2_TEXTURE_COORD_3
控制点是一个(s,t,r)纹理坐标
GL_MAP2_TEXTURE_COORD_4
控制点是一个(s,t,r,q)纹理坐标
表2-1
2.4.2绘制网格曲面
(1)添加一个菜单
添加一个名为Surface的菜单,在其属性对话框里的Caption栏中键入Surface。
为其增加一个菜单项,其名为Bezier,在其属性对话框的Caption栏中键入Bezier,勾选Pop-up属性。
按表2-2完成。
Caption
ID
&Meah
IDM_BZRSUFAC_MESH
&Fill
IDM_BZRSUFAC_FILL
&Texture
IDM_BZRSUFAC_TEXTURE
表2-2
(2)添加保护成员函数
添加一个保护成员函数:
BzeSufacMesh(),编辑如下:
{
IntI,j;
GLfloatpoints[4][4][3]=
{
{{-0.8f,-0.6f,0.8f},{-0.2f,-0.6f,1.6f},{0.2f,-0.6f,-0.4f},{0.6f,-0.6f,0.8f}},
{{-0.6f,-0.2f,0.8f},{-0.2f,-0.2f,1.6f},{0.2f,-0.2f,-0.4f},{0.6f,-0.2f,0.8f}},
{{-0.6f,0.2f,0.8f},{-0.2f,0.2f,0.4f},{0.2f,0.2f,0.0f},{0.3f,0.2f,-0.4f}},
{{-0.6f,0.6f,0.8f},{-0.2f,0.6f,0.4f},{-0.8f,0.6f,0.0f},{0.8f,0.6f,-0.4f}}
};}////控制点
glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints);//二维评价器
glEnable(GL_MAP2_VERTEX_3);
glColor3f(0,0,1);//激活
glPushMatrix();
glRotated(45,1,1,1);
for(j=0;j<8;j++){
glBegin(GL_LINE_STRIP);
for(i=0;i<30;i++){
glEvalCoord2f((float)i/30,(float)j/8);
}
glEnd();
glBegin(GL_LINE_STRIP);
for(i=0;i<30;i++){
glEvalCoord2f((float)j/8,(float)i/30);
}
glEnd();
}
glPopMatrix();//绘制
glDisable(GL_MAP2_VERTEX_3);//挂起
该函数将绘制一个网格曲面,因为glBegin()函数的参数为GL_LINE_STRIP。
(3)编辑DrawScenc()函数
在语句switch(m_typeControl){….}中添加语句:
CaseBezierSrufaceMesh:
BzrSufacMesh();break;
(4)运行程序,得到如图2-2的结果
图2-2Bezier网格曲面
2.4.3绘制一个填充曲面
(1)增加两个保护函数
Lighting()和BzrSufacFill()函数,Lighting()函数光照处理,BzrSufacFill()函数则绘制曲面。
Lighting();
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);//光照
glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints);//二维评价器
glMapGrid2f(30,0,1,30,0,1);//自动网格
glEnable(GL_MAP2_VERTEX_3);//激活
glPushMatrix();
glRotated(45,1,1,1);
glEvalMesh2(GL_FILL,0,30,0,30);
glPopMatrix();//绘制
glDisable(GL_MAP2_VERTEX_3);
glDisable(GL_AUTO_NORMAL);
glDisable(GL_NORMALIZE);
glDisable(GL_LIGHTING);//挂起
(2)编辑DrawScene()函数
在语句switch(m_typeControl){….}中添加语句;
CaseBezierSurfaceFill:
BzeSufacFill();break;
(3)运行程序,得到如图2-3的结果
图2-3Beizer填充曲面
2.4.4三次贝齐尔曲面
通过改变控制点坐标即可改变曲面的形状,这是Bezier曲面的一个特性。
说明:
程序输出的是斜二测投影图,X轴正方向向右,Y轴正方向向下,X、Y、Z三个轴正方成右手坐标系.曲面显示在Z轴负坐标的位置上。
图2-4中所示为轮船船艏,首柱线与设计水线交于曲面的右上角;最大横剖线与设计水线交于曲面左上角:
曲面右下角为首柱线与龙骨线的切点或交点:
曲面左下角为最大横剖线与底部龙骨起跑线的交点。
图2-4运行结果
2.5主程序
#include"StdAfx.h"
#include"OpenGL.h"/添加头文件名/
#include
#include"bitmap.h"
#definePI((double)3.1415926)
#defineRADIANS(fAngle)((double)(fAngle)*PI/180.0)
COpenGL:
:
COpenGL(void):
type(MESH)/类型网格/
{
//GLfloatpoints[4][4][3]=
//GLfloatpoints[4*4*3]=
//{
//{{-0.8f,-0.6f,0.8f},{-0.2f,-0.6f,1.6f},{0.2f,-0.6f,-0.4f},{0.6f,-0.6f,0.8f}},
//{{-0.6f,-0.2f,0.8f},{-0.2f,-0.2f,1.6f},{0.2f,-0.2f,-0.4f},{0.6f,-0.2f,0.8f}},
//{{-0.6f,0.2f,0.8f},{-0.2f,0.2f,0.4f},{0.2f,0.2f,0.0f},{0.3f,0.2f,-0.4f}},
//{{-0.6f,0.6f,0.8f},{-0.2f,0.6f,0.4f},{-0.8f,0.6f,0.0f},{0.8f,0.6f,-0.4f}}
//};/输入各点坐标/
//for(inti=0;i<4;i++){
//for(intj=0;j<4;j++){
//for(intm=0;m<3;m++){
//controlPoints[i][j][m]=points[i*4*3+j*3+m];
//}
//}
//}
}
COpenGL:
:
~COpenGL(void)/添加函数类型为void/
{
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
}
voidCOpenGL:
:
Init(void)
{
glClearColor(1.0,1.0,1.0,1.0);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
}
boolCOpenGL:
:
SetupPixelFormat(HDChDC0)
{
intnPixelFormat;
hDC=hDC0;
PIXELFORMATDESCRIPTORpfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,
0,
0,
0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};
if(!
(nPixelFormat=ChoosePixelFormat(hDC,&pfd)))
{MessageBox(NULL,"cannotfindpropermode","Error",MB_OK|MB_ICONEXCLAMATION);/若错误则显示cannotfindpropermodeerror/
returnFALSE;/返回FLASH/
}
SetPixelFormat(hDC,nPixelFormat,&pfd);
hRC=wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);
returnTRUE;/返回TURE/
}
voidCOpenGL:
:
Reshape(intwidth,intheight)
{
//glViewport(0,0,width,height);
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
//gluPerspective(60,(GLfloat)width/(GLfloat)height,0.1,3000.0);
//glMatrixMode(GL_MODELVIEW);
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,0.1,3000.0);
glMatrixMode(GL_MODELVIEW);
//glMatrixMode(GL_MODELVIEW);
}
enumAspect{FRONT,BACK,LEFT,RIGHT,UP,DOWN};
enumColor{BLUE,GREEN,RED,ORANGE,WHITE,YELLOW};/代表颜色索引值/
constGLubytecolorTable[6][3]={
{0,0,255},{0,255,0},{255,0,0},{255,102,0},{255,255,255},{255,255,0}
};
voidCOpenGL:
:
Render()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0,0,3,0,0,0,0,1,0);
switch(type){
caseMESH:
DrawMesh();/绘制网格/
break;
caseFILL:
DrawFill();/绘制填充曲面/
break;
caseTEXTURE:
DrawTexture();/绘制贴图曲面/
break;
default:
break;
}
//drawstuff
//drawcube
//GLintvertices[8][3]={
//{-1,-1,-1},{1,-1,-1},{-1,-1,1},{1,-1,1},
//{-1,1,-1},{1,1,-1},{-1,1,1},{1,1,1}
//};
////inorder:
front,back,left,right,top,bottom
//GLubytevertIndex[6][4]={
//6,2,3,7,
//5,1,0,4,
//4,0,2,6,
//7,3,1,5,
//7,5,4,6,
//2,0,1,3
//};
//for(inti=0;i<6;i++){
//glColor3ubv(colorTable[i]);
//glBegin(GL_QUADS);
//for(intj=0;j<4;j++){
//glVertex3iv(vertices[vertIndex[i][j]]);
//}
//glEnd();
//}
glFlush();
SwapBuffers(hDC);
}
voidCOpenGL:
:
DrawMesh()
{
GLfloatcontrolPoints[4][4][3]=
{
{{-0.8f,-0.6f,0.8f},{-0.2f,-0.6f,1.6f},{0.2f,-0.6f,-0.4f},{0.6f,-0.6f,0.8f}},
{{-0.6f,-0.2f,0.8f},{-0.2f,-0.2f,1.6f},{0.2f,-0.2f,-0.4f},{0.6f,-0.2f,0.8f}},
{{-0.6f,0.2f,0.8f},{-0.2f,0.2f,0.4f},{0.2f,0.2f,0.0f},{0.3f,0.2f,-0.4f}},
{{-0.6f,0.6f,0.8f},{-0.2f,0.6f,0.4f},{-0.8f,0.6f,0.0f},{0.8f,0.6f,-0.4f}}
};/定义控制点/
inti,j;