




已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
课程设计实验报告实验课程名称: 计算机图形学 实验项目名称: 图形学算法演示 学院: 信息科学与工程学院 专业: 计算机科学与技术2011-3 姓名: 林开春 学号: 201101052009 指导教师: 实验内容:学会对计算机图形学中涉及的各种图形的绘制方法,并熟悉掌握所用的的函数和方法,实现对图形的绘制,演示。l 基本图元绘制算法:DDA绘直线、Bresenham绘直线、Bresenham绘圆l 多边形扫描转换算法和区域填充算法实现(扫描线算法为必做,基于求余运算的边缘填充和边标志算法为任选; l 线段裁剪和多边形裁剪算法的动画演示实现。(两种线段裁剪算法和H-S多边形逐边裁剪算法)多边形裁剪算法的动画演示要求先画出一个封闭的多边形,再画矩形的裁剪窗口,然后选择裁剪按钮(或命令),按下“上边裁剪”按钮(或执行“上边裁剪”命令),多边形相对裁剪窗口的上边进行裁剪,显示上边裁剪后的多边形,依此进行其它各边裁剪。l 用动画实现二维图形变换的各种算法,实现对指定形体的平移、旋转和缩放。(包括类似自行车行走和绕固定点旋转的自旋转物体动画。)l 简单三维图形系统:凸多面体的建模、透视投影,隐藏面的消除及基本图形变换(平移、旋转、缩放)实验说明:方法、步骤编程语言: C+IDE版本: Microsoft Visual C+ 6.0实验方法:使用MFC进行编程,参照实验指导书,一步一步操作,就可以基本完成整个实验的操作了。1、建立程序框架:创建MFC单文档应用程序2、添加绘图菜单项通过更改各个菜单选项属性,设置好ID号,并标明,如图所示3、在创建的View中添加个消息函数添加对应消息WM_CREAT的消息函数OnCreate()函数添加对应鼠标消息的WM_LBUTTONDOWN的消息函数OnLButtonDown();添加对应鼠标消息的WM_MOUSEMOVE的消息函数OnMouseMove ();添加对应鼠标消息的WM_RBUTTONDOWN的消息函数OnRButtonDown();添加对应鼠标消息的WM_MOUSEWHEEL的消息函数OnMouseWheel();4、声明变量和函数5、添加各菜单项的消息映射函数主要添加的响应有,鼠标右键、鼠标右键、鼠标滑轮、鼠标移动、键盘按键响应。每个工程的建立大同小异,下面将不对工程的建立和设置进行描述和说明。主要讨论程序的算法和实现。具体的设置参见程序。基本图元一、实验内容本实验程序实现的主要函数及其说明关于绘制图形的算法的函数:void DDALine(CPoint start,CPoint end,long color);/用DDA算法绘制直线void MiddleLine(CPoint start, CPoint end,long color);/用中点算法绘制直线void BresenhamLine(CPoint start, CPoint end,long color);/用Bresenham算法绘制直线void Rectangle(CPoint start,CPoint end, long color);/绘制多边形void BresenhamCircle(CPoint center,CPoint t,long color);/ 用Bresenham算法绘制圆void MiddleCircle(CPoint center,CPoint t,long color);/用中点算法绘制圆void MiddleEllipse(CPoint start,CPoint end, long color);/用中点算法绘制椭圆二、程序设计说明及源代码: 1、绘制直线的算法1)、DDA算法解:这个算法代码是直接抄写实验书上面的呀,算法比较明显,通过计算x方向和y方向的增量依次画出各个点,而这个代码也写得比较精炼step的应用大大减少代码量。代码如下:void CExercise1View:DDALine(CPoint start, CPoint end,long color)CClientDC dc(this);dc.SetPixel(start.x,start.y,color);dc.SetPixel(end.x,end.y,color);/dx和dy分别是x方向和y方向的增量int dx=end.x-start.x, dy=end.y-start.y, steps,k;float xIncrement,yIncrement,x=start.x,y=start.y;/选择增量大的方向作为每次前进的方向if(fabs(dx)fabs(dy) steps = fabs(dx);else steps = fabs(dy);/计算每个方向的前进增量xIncrement = float(dx)/float(steps);yIncrement = float(dy)/float(steps);dc.SetPixel(int)(x+0.5),(int)(y+0.5),color);for(k=0;kend.x) TempPoint=start;start=end;end=TempPoint;dc.SetPixel(start.x,start.y,color);dc.SetPixel(end.x,end.y,color);int a,b,d1,d2,d,x,y,flag=0,temp;if(fabs(start.x-end.x)fabs(start.y-end.y) flag=1;x=start.x; y=start.y;dc.SetPixel(x,y,color);a=start.y-end.y;b=end.x-start.x;if(start.yend.y) b=-b;if(flag=0) temp=a;a=b;b=temp;d=2*a+b;d1=2*a;d2=2*(a+b);if(start.y=end.y)if(flag=1)while(xend.x) if(d0) x+;y+;d+=d2;else x+;d+=d1;dc.SetPixel(x,y,color);elsewhile(y0) y+;x+;d+=d2;else y+;d+=d1;dc.SetPixel(x,y,color);elseif(flag=1)while(x0) x+;y-;d+=d2;else x+;d+=d1;dc.SetPixel(x,y,color);elsewhile(yend.y)if(dend.x) TempPoint=start;start=end;end=TempPoint;dc.SetPixel(start.x,start.y,color);dc.SetPixel(end.x,end.y,color);int dx=fabs(end.x-start.x),dy=fabs(end.y-start.y);int d,twoDy,twoDyMinusDx;int x,y,t=1,count;if(start.yend.y) t=-1;x=start.x;y=start.y;dc.SetPixel(x,y,color);if(dx=dy)d=2*dy-dx;twoDy=2*dy,twoDyMinusDx=2*(dy-dx);while(xend.x)x+;if(d0) d+=twoDy;else y+=t;d+=twoDyMinusDx;dc.SetPixel(x,y,color);else d=2*dx-dy;twoDy=2*dx,twoDyMinusDx=2*(dx-dy);count=0;while(countdy)count+;y+=t;if(d0) d+=twoDy;else x+;d+=twoDyMinusDx;dc.SetPixel(x,y,color);2、多边形绘制1)、三角形三角形画法很简单只是用鼠标点三个点,然后将三个点连线就可以了。这个难点在于交与方面和实现橡皮筋功能方面。2)、矩形矩形的画法也比教简单,只是选择两个点(XA,YA),(XB,XY),然后组合后画出对应的4条线段就可以了。3)、多边形通过鼠标点击的点依次画出各个点间的连线就可以了,最后结束的时候只要点击鼠标右键就可以了。3、圆的绘制算法1)、中点算法解:这个算法的原理和直线的中点算法原理一样,代码完全参照课本给的程序,修改下就可以使用了,也结合了实验指导书的例程。void CExercise1View:MiddleCircle(CPoint center, CPoint t, long color)CClientDC dc(this);CPoint temp;float radius=sqrt(center.x-t.x)*(center.x-t.x) + (center.y-t.y)*(center.y-t.y);int p=1-(int)radius;temp.x=(int)radius;temp.y=0;circlePlotPoint(center,temp,color);while(temp.ytemp.x)temp.y+;if(p0) p+=2*temp.y+3;else temp.x-;p+=2*(temp.y-temp.x)+5;circlePlotPoint(center,temp,color);2)、Bresenham算法解:也是参照书上的例程,修改下,对这个算法的理解还不是很深刻。void CExercise1View:BresenhamCircle(CPoint center, CPoint t, long color)CClientDC dc(this);CPoint temp;int R=(int)sqrt(center.x-t.x)*(center.x-t.x) + (center.y-t.y)*(center.y-t.y);int d=3-2*R;temp.x=0;temp.y=R;circlePlotPoint(center,temp,color);while(temp.xtemp.y)circlePlotPoint(center,temp,color);if(d0) d = d + 4*temp.x + 6;else d = d + 4*(temp.x-temp.y) +10; temp.y-;temp.x+;if(temp.x=temp.y) circlePlotPoint(center,temp,color);4、椭圆绘制算法解:首先将椭圆分成两个区域,以切线斜率为-1作为分界。由及算出分界点,初值为,从(0,b)开始画到(x,y)到(a,0)切线斜率,当,当,切线斜率,当,当,代码如下:void CExercise1View:MiddleEllipse(CPoint start, CPoint end, long color)CClientDC dc(this);CPoint t,k;CPoint temp;temp=start;int a=fabs(start.x-end.x),b=fabs(start.y-end.y);if(a=0 | b=0) return;int aa=a*a,bb=b*b;k.x=(int)(float)aa/sqrt(float)(aa+bb)+0.5);k.y=(int)(float)aa/sqrt(float)(aa+bb)+0.5);t.x=0;t.y=b;int d=4*(bb-aa*b)+aa;ellipsePlotPoint(temp,t,color);while(t.x=k.x)if(d0)if(d=0) d += 4*aa*(3-2*t.y);else d += 4*(2*bb*(t.x+1) + aa*(3-2*t.y); t.x+;t.y-;ellipsePlotPoint(temp,t,color);区域填充一、实验内容本实验程序实现的主要函数及其说明关于绘制图形的算法的函数:void LineFill();/用扫描线算法填充多边形void SideNotFill();/用边取反算法填充多边形void SeedFill(CPoint temp); /用种子填充算法填充区域void LineSeedFill(CPoint seed); /用扫描线种子填充算法填充区域二、程序设计说明及源代码: 1、多边形填充算法1)、扫描线填充算法用到的数据结构:桶ET和边的活性边表AEL算法的描述如下:for(y=ymin;iNodeCount;memset(pdoc-PolygonNodeJudge,0,100*sizeof(pdoc-PolygonNodeJudge0);moreLeft=pdoc-PolygonNode0.x;/判断第0个点是内点还是外点if(pdoc-PolygonNoden-1.ypdoc-PolygonNode0.y & pdoc-PolygonNode1.yPolygonNode0.y ) |(pdoc-PolygonNoden-1.yPolygonNode0.y & pdoc-PolygonNode1.ypdoc-PolygonNode0.y)pdoc-PolygonNodeJudge0=1;/判断最后一个点是内点还是外点if(pdoc-PolygonNode0.ypdoc-PolygonNoden-1.y & pdoc-PolygonNoden-2.yPolygonNoden-1.y ) | (pdoc-PolygonNode0.yPolygonNoden-1.y & pdoc-PolygonNoden-2.ypdoc-PolygonNoden-1.y)pdoc-PolygonNodeJudgen-1=1;/对其他点进行判断是内点还是外点for(i=1;iPolygonNodei-1.ypdoc-PolygonNodei.y & pdoc-PolygonNodei+1.yPolygonNodei.y ) | (pdoc-PolygonNodei-1.yPolygonNodei.y & pdoc-PolygonNodei+1.ypdoc-PolygonNodei.y)pdoc-PolygonNodeJudgei=1;/找出多边形中“最右”的那个点的y值for(i=1;iNodeCount;i+)if(pdoc-PolygonNodei.x moreLeft) moreLeft=pdoc-PolygonNodei.x;moreLeft=moreLeft+10m_rect.right?m_rect.right:moreLeft+10;if(pdoc-PolygonNode0.y != pdoc-PolygonNodepdoc-NodeCount-1.y)LineDDA2(pdoc-PolygonNodeJudge0,pdoc-PolygonNode0,pdoc-PolygonNodepdoc-NodeCount-1,pdoc-PenColor);for(i=1;iNodeCount;i+)if(pdoc-PolygonNodei.y != pdoc-PolygonNodei-1.y)LineDDA2(pdoc-PolygonNodeJudgei,pdoc-PolygonNodei,pdoc-PolygonNodei-1,pdoc-PenColor);二维裁剪一、实验内容本实验程序实现的主要函数及其说明关于裁剪的算法的函数:void CohenClip(CPoint &,CPoint &);/用Sutherland-Cohen算法裁剪直线void MidPointClip(CPoint &,CPoint &);/用中点算法裁剪直线void LiangClip(CPoint &,CPoint &);/用梁友栋算法裁剪直线void PolygonClipLeft(CPoint ,int&);/用Sutherland-Hodgmans算法对多边形进行左边裁剪void PolygonClipRight(CPoint ,int&);/用Sutherland-Hodgmans算法对多边形进行右边裁剪void PolygonClipBottom(CPoint ,int&);/用Sutherland-Hodgmans算法对多边形下边裁剪void PolygonClipTop(CPoint ,int&);/用Sutherland-Hodgmans算法对多边形进行上边裁剪二、程序设计说明及源代码: 对每个点进行编码,函数返回值为这个点的编码unsigned int CLabView:Encode(double x, double y)unsigned int c = 0;if (x ClipWindow_Right) c = c|2;if (y ClipWindow_Bottom) c = c|8;return c;编号后如果两个点的编码的逻辑或为0,则这条线段在裁剪窗口中;逻辑与后不为0,则两个点在裁剪窗口的某条边的外侧,故与窗口无交点。1、线段裁剪算法1)、Sutherland-Cohen算法解:先对每个点进行编号,先判断线段是在裁剪窗口外或者在窗口内,如果不能够确定则依次算出这条线段的在与窗口的某一条边的交点,替换原来的顶点。void CLabView:CohenClip(CPoint &pstart,CPoint &pend) BOOL Change;double x,y;double Pointx2,Pointy2;Pointx0=pstart.x;Pointy0=pstart.y;Pointx1=pend.x;Pointy1=pend.y;Recode0=Encode(Pointx0,Pointy0);/对起点进行编码Recode1=Encode(Pointx1,Pointy1); /对终点进行编码while(true)Change=false;if(0=(Recode0|Recode1) break ; /两个点在窗口内else if(0!=(Recode0&Recode1) break ; /两个点在窗口的一侧elseif(0=Recode0) /第一个点设置为在窗口外double tempx,tempy;tempx=Pointx0;tempy=Pointy0;Pointx0=Pointx1;Pointy0=Pointy1;Pointx1=tempx;Pointy1=tempy;unsigned int tRC;tRC=Recode0;Recode0=Recode1;Recode1=tRC;if(Recode0 & LEFT) /如果第一个点在窗口的左侧x=ClipWindow_Left; /计算与左边界的交点y=Pointy0+(Pointy1-Pointy0)*(x-Pointx0)/(Pointx1-Pointx0);Pointx0=x;Pointy0=y;Change=true;Recode0=Encode(Pointx0,Pointy0);Recode1=Encode(Pointx1,Pointy1);if(Recode0 & RIGHT) /如果第一个点在窗口的右侧x=ClipWindow_Right; /计算与右边界的交点y=Pointy0+(Pointy1-Pointy0)*(x-Pointx0)/(Pointx1-Pointx0);Pointx0=x;Pointy0=y;Change=true;Recode0=Encode(Pointx0,Pointy0);Recode1=Encode(Pointx1,Pointy1);if(Recode0 & TOP) /如果第一个点在窗口的下侧y=ClipWindow_Top; /计算与下边界的交点x=Pointx0+(Pointx1-Pointx0)*(y-Pointy0)/(Pointy1-Pointy0);Pointx0=x;Pointy0=y;Change=true;Recode0=Encode(Pointx0,Pointy0);Recode1=Encode(Pointx1,Pointy1);if(Recode0 & BOTTOM) /如果第一个点在窗口的上侧y=ClipWindow_Bottom; /计算与上边界的交点x=Pointx0+(Pointx1-Pointx0)*(y-Pointy0)/(Pointy1-Pointy0);Pointx0=x;Pointy0=y;Change=true;Recode0=Encode(Pointx0,Pointy0);Recode1=Encode(Pointx1,Pointy1);if(false=Change) break ;pstart.x=Pointx0;pend.x=Pointx1;pstart.y=Pointy0;pend.y=Pointy1;2)、中点算法3)、梁友栋算法这个算法参考书上的代码,不用说明了。int CLabView:ClipTest(double u,double v,double * tmax,double *tmin)double t;int ReturnValue=TRUE;if(u*tmin) ReturnValue=FALSE;else if(t*tmax) *tmax=t;elseif(u0.0)t=v/u;if(t*tmax) ReturnValue=FALSE;else if(t*tmin) *tmin=t;elseif(v0.0) ReturnValue=FALSE;return (ReturnValue);void CLabView:LiangClip(CPoint &pstart,CPoint &pend)double tmax,tmin,dx,dy;double x1,y1,x2,y2;x1=pstart.x;y1=pstart.y;x2=pend.x;y2=pend.y;dx=x2-x1;dy=y2-y1;tmax=0.0;tmin=1.0;if(ClipTest(-dx,x1-ClipWindow_Left,&tmax,&tmin) if(ClipTest(dx,ClipWindow_Right-x1,&tmax,&tmin) if(ClipTest(-dy,y1-ClipWindow_Top,&tmax,&tmin)if(ClipTest(dy,ClipWindow_Bottom-y1,&tmax,&tmin)if(tmin0.0)x1+=tmax*dx;y1+=tmax*dy;pstart.x=x1;pend.x=x2;pstart.y=y1;pend.y=y2;2、多边形裁剪算法Sutherland-Hodgmans算法在窗口的一条边界及其延长线上裁剪一个多边形,该边界将平面分成两个部分:一个部分是边界的内侧,一部分是边界的外侧。多边形的每一条边与这个边界有四种情况:A、S在外侧,P在内测,则交点Q、当前点P保存在新多边形中;B、S,P都在内测,则当前点P保存到新多边形中;C、S在内测,P在外侧,则交点Q保存到新多边形中;D、S,P都在外侧,则没有点被保存到新多边形中。实验的代码参考实验指导书上的(由于四个边界的判断基本一样符故只贴出多边形左边裁剪的代码部分)。核心代码如下:void CLabView:PolygonClipLeft(CPoint p,int &M)int i,k;int code1,code2;CPoint ptemp100;pM=p0;k=0;for(i=0;iM;i+)int c=0;if(pi.xClipWindow_Left)c=0;code1=c;c=0;if(pi+1.xClipWindow_Left)c=0;code2=c;if(code1!=0&code2=0)/当前点在外侧,下一个点在内侧,保存交点和下一个点到新多边形中ptempk.x=ClipWindow_Left;ptempk.y=pi.y+(pi+1.y-pi.y)*(ptempk.x-pi.x)/(pi+1.x-pi.x);ptempk+1.x=pi+1.x;ptempk+1.y=pi+1.y;k=k+2;if(code1=0&code2=0)/两个点都在内测,保存下一个点if(k=0)/如果是第一个点,则也保存第一个点ptempk.x=pi.x;ptempk.y=pi.y;ptempk+1.x=pi+1.x;ptempk+1.y=pi+1.y;k=k+2;if(k!=0)ptempk.x=pi+1.x;ptempk.y=pi+1.y;k=k+1;if(code1=0&code2!=0)/当前点在内侧,下一个点在外侧,保存交点ptempk.x=ClipWindow_Left;ptempk.y=pi.y+(pi+1.y-pi.y)*(ptempk.x-pi.x)/(pi+1.x-pi.x);k+;for(i=0;ik;i+) pi=ptempi; /替换到原先的多边形的数组中M=k; /顶点个数改变二维变换一、实验内容二维的平移变换:二维旋转变换:二维缩放变换:void Tmove(double x,double y,CPoint temp);/平移void Tscale(double x,double y,CPoint temp);/缩放void Trotate(CPoint); /旋转二、程序设计说明及源代码: 解:按照上面的算法,直接算出变换后点的点平移:void CLabView:Tmove(double x,double y,CPoint PolygonNode)for(int i=0;iPolygonNodeCount;i+)PolygonNodei.x=PolygonNodei.x+x;PolygonNodei.y=PolygonNodei.y+y;/Draw(P,ntype);缩放:void CLabView:Tscale(double x,double y,CPoint PolygonNode)/放大for(int i=0;iPolygonNodeCount;i+)PolygonNodei.x=PolygonNodei.x*x;PolygonNodei.y=PolygonNodei.y*y;旋转:其中BasePoint为旋转的中心void CLabView:Trotate(CPoint temp)CClientDC dc(this);int dx=temp.x-BasePoint.x;int dy=temp.y-BasePoint.y;double x,y;double dd=sqrt(dx*dx+dy*dy);double dcos=dx/dd;double dsin=dy/dd;for(int i=0;iPolygonNodeCount;i+)x=PolygonNodei.x-BasePoint.x;y=PolygonNodei.y-BasePoint.y;TempPolygoni.x=(int)(x*dcos-y*dsin+0.5);TempPolygoni.y=(int)(x*dsin+y*dcos+0.5);使用OpenGL的函数直接完成平移旋转等变换glTranslatef(glfloat, glfloat, glfloat);glRotatef(glfloat, glfloat, glfloat, glfloat );glScalef(glfloat , glfloat, glfloat, glfloat);三维变换一、实验内容本实验程序实现的主要函数及其说明bool Painter(CDC *mdc);/用画家算法对正方体进行消隐void DrawObject ();/用后向面判别算法对正方体进行消隐二、程序设计说明及源代码: 1、画家算法,将面片按深度递减方向排序,由深度最大的面片开始,逐个对面片进行扫描转换,即对面片的绘制。程序的代码参考实验指导书上的画家消隐算法,核心代码如下:bool CLabView:Painter(CDC *mdc)/Sign(mdc);Rotate();for(Face=0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年安全生产GMP认证模拟练习题及答案
- 2025年健康管理顾问资格认证考试试题及答案解析
- 2025年建筑施工现场监理员专业能力测评试题及答案解析
- 2025年家政服务员职业技能考试试题及答案解析
- 机电行业外贸知识培训班课件
- 2025年宠物音乐疗愈师初级面试模拟题及答案
- 2025年广告文案策划师职业水平评定试题及答案解析
- 中学语文教学通讯课件
- 如何写好讲解课件教学
- 课件上的秘密
- 统编版二年级《语文》上册新教材解读课件
- 公务用车管理制度与车辆维护
- 医院二甲设备管理PDCA应用
- 江苏省苏州市2025年中考语文试卷(含答案解析)
- 河南大学河南戏剧学院招聘考试真题2024
- 《无人机结构与系统(第2版)》全套教学课件
- 胃肠外科健康教育
- 2026版创新设计高考总复习数学人教A版学生用-学生答案一~五章
- 慢性支气管炎个案护理
- 1.2地球与地球仪(第1课时)课件七年级地理上册人教版
- 《幼儿园保育教育质量评估指南》理论考试试卷(附答案)
评论
0/150
提交评论