计算机图形学期末课程设计.docx
- 文档编号:30187831
- 上传时间:2023-08-05
- 格式:DOCX
- 页数:24
- 大小:291.40KB
计算机图形学期末课程设计.docx
《计算机图形学期末课程设计.docx》由会员分享,可在线阅读,更多相关《计算机图形学期末课程设计.docx(24页珍藏版)》请在冰豆网上搜索。
计算机图形学期末课程设计
图形学课程设计报告
题目:
系别:
班级:
学号:
姓名:
指导老师:
目录
诚信说明1
目录2
一、项目描述3
1.1项目的目的3
二、项目需求3
2.1需求分析3
2.2功能描述3
三、项目设计4
3.1直线扫描算法4
3.1.1DAA扫描线算法4
3.1.2中点扫描线算法4
3.1.3Bresenham扫描线算法4
3.2圆的扫描算法5
3.2.1中点画圆扫描算法5
3.2.2Bresenham画圆扫描算法5
3.3种子填充算法5
3.4图形的基本几何变换算法5
3.4.1平移5
3.4.2旋转6
3.4.3伸缩6
3.5Bezier曲线算法6
四、项目效果6
五、项目总结11
六、参考文献12
七、附录12
1、项目描述
1.1项目的目的
通过本次课程设计,使自己了解计算机图形学的有关原理、算法及系统,掌握基本图形显示程序设计方法,及二维和三维图形基本几何变换程序设计方法,为进一步学习计算机辅助设计方面的技术知识打下基础。
1.掌握图形学直线扫描算法:
DDA,中点扫描线算法,Bresenham扫描线算法
2.掌握图形学画圆扫描算法:
中点画圆算法和Bresenham扫描算法
3.掌握简单的几何图形的填充算法:
种子填充和扫描线填充算法
4.掌握简单图形的基本几何变换:
平移,旋转和伸缩
5.掌握Bezier曲线的生成算法
6.熟悉并掌握vc6.0中的MFC使用方法
7.掌握C/C++语言编程方法
8.在学习基础上设计一个基于MFC的画图软件
1.2项目内容
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的画图设计工具也越来越多,类似CAD和CDM及Photoshop的画图软件和图片处理软件的发展也日新月异,因此产生了制作一个类似的画图软件;而且通过制作该程序还能更好的学习图形学编程知识。
通过一个学期的学习,对于图形学的知识也有了些了解!
为了更好的巩固和运用所学的知识,希望通过设计一个基于MFC的画图软件,达到自己想要的结果!
2、项目需求
2.1需求分析
随着计算机科学技术的发展,近30年来,计算机图形学得到迅猛发展,人们可以通过计算机高速,有效,真实的生成图形,计算机图形学作为利用计算机生成图形的技术,已经越来越广泛地在各个领域得到了应用。
计算机图形学应用水平的提高和应用领域的拓宽,使得人们越来越重视对计算机图形学的研究和利用。
因此,通过一个学期有关图形学课程的学习之后,为了巩固所学的知识,将所学的知识运用到实践中,我决定设计一个小型画图软件,可以实现简单的画图功能和图片存储,编辑功能。
2.2功能描述
通过一个学期图形学课程的学习,基于所学的知识,我设计了一个简单的画图软件,该软件主要具备以下几个功能:
1、画图功能:
点击画图菜单,可以选择画直线,画圆,或者填充;也可以通过菜单下面的快捷键直接实现以上功能。
2、选择算法的功能:
由于课本上介绍的算法比较多,经过总结分类之后,我添加了一个算法选择的功能,可以通过单击算法,选择画图时采用不同的算法来实现相同的画图操作。
3、画图方式:
考虑到交互功能,我设计了画图方式的功能,用户可以选择鼠标画图或者对话框画图,都能达到做要求的目的。
4、图像变换:
基于所学的基本几何变换,我设计和该图像变换功能,可以实现图形的平移,旋转和伸缩等操作。
三、项目设计
3.1直线扫描算法
3.1.1DAA扫描线算法
直线DDA算法就是取直线起点(x0,y0)作为初始坐标,x每递增1,通过公式:
yi+1=yi+kdx计算出y轴坐标。
直线DDA算法也称数值微分算法。
直线DDA算法的本质,是用数值方法解微积分方程,通过同时对X,y各增加一个小增量,计算出下一步的x,y的值,以此确定该点的位置及属性。
最后画出直线。
3.1.2中点扫描线算法
假设x轴坐标为xi的与直线最近的像素已经决定为P(xi,yi),则下一个与直线最接近的像素只能是正右方的P1(xi+1,yi)或右下方的P2(xi+1,yi+1).以M(xi+1,yi+0.5)表示p1与p2的中点,用Q表示该直线与x=xi+1直线的交点。
当M在Q的下方,取P2为下一个直线上的点;当M在Q的上方,取P1为下一个直线上的点。
这是中点画线算法的基本思想。
中点画线算法得实现,关键是判断M和Q的位置关系。
直线方程采用隐式方程表示为F(x,y)=ax+by+c=0,将M坐标带入方程,判断di=F(Mi)=F(xi+1,yi+0.5)的大小。
当di>0时,则下一像素的判别式为di+1=F(xi+2,yi+0.5)=di+a;当di<0时,则下一像素的判别式为di+1=F(xi+2,yi+1.5)=di+a+b。
d0=F(x0+1,y0+0.5)=a+0.5b。
其中,a=y0-y1,b=x1-x0,c=x0y1-x1y0.
3.1.3Bresenham扫描线算法
假设已经确定的像素为P(xi,yi),那么下一个可选择的像素点为P1(xi+1,yi)和P2(xi+1,yi+1)中的一个。
用Q表示该直线与x=xi+1直线的交点,Q点到P1(xi+1,yi)和P2(xi+1,yi+1)的距离分别为a1,a2,则有a1-a2=2k(xi+1)-2yi+2b-1.当a1>a2,下一像素点应取P2;当a1 为了简化a1-a2,利用新变量di=Δx(a1-a2)=2Δy*xi-2Δx*yi+1+C,其中,C为后面的常量。 di+1=2Δy*xi+1-2Δx*yi+1+C.故di+1-di=2Δy-2Δx(yi+1-yi).当di>=0时,di+1=di+(2Δy-2Δx),当di<0时,di+1=di+2Δy。 d0=2Δy-Δx。 3.2圆的扫描算法 3.2.1中点画圆扫描算法 中点画圆算法从点(0,R)至(R/ R/ )的1/8圆周顺时针的确定最佳逼近与圆弧的像素序列。 假设已经确定的像素为P(xi,yi),那么下一个可选择的像素点为P1(xi+1,yi)和P2(xi+1,yi-1)中的一个。 构造原函数为F(x,y)=x2+y2-R2 对于圆上的点(x,y),有F(x,y)=0;对于圆外的点(x,y),有F(x,y)>0;对于圆内得点(x,y),有F(x,y)<0.构造判别式di=F(Mi)=(xi+1)2+(yi-0.5)2-R2.若di<0,则取P1,下一个像素的判别式为di+1=F(xi+2,yi—0.5)=di+2xi+3;若di>=0,取P2,下一个像素的判别式为di+1=F(xi+2,yi—1.5)=di+2(xi-yi)+5.d0=1.25-R。 用ei=di-0.25代替di,若ei>=0,取P1为下一像素,e的增量为2xi+3;若ei<0,取P2为下一像素,e的增量为2xi-2yi+5. 3.2.2Bresenham画圆扫描算法 假设已经确定的像素为P(xi,yi),那么下一个可选择的像素点为Hi(xi+1,yi)和Di(xi+1,yi-1)中的一个。 分别计算这两点到圆周的距离,即|Б(Hi)|=|(xi+1)2+yi2-R2|,|Б(Di)|=|(xi+1)2+(yi-1)2-R2.引判别式di=Б(Hi)+Б(Di)=[(xi+1)2+yi2]-R2+[(xi+1)2+(yi-1)2]-R2.如果di<0,取Hi,则下一点(xi+1,yi)的判别式为di+1=Б(Hi+1)+Б(Di+1)=d+4xi+6;如果di>0,取Di,则下一点为(xi+1,yi-1)的判别式为di+1=Б(Hi+1)+Б(Di+1)=d+4(xi-yi)+10.初值d0=Б(H0)+Б(D0)=3-2R。 3.3种子填充算法 种子填充算法可以采用递归算法。 递归的基本方法是设种子像素为(x,y)是四向连通区域内的一点,old_color为区域内的原有像素颜色,new_color是要填充的颜色,递归填充的过程是如果种子像素是区域内的原有颜色old_color,说明该种子像素在区域内,则像素置为被填充颜色new_color,同时将种子像素的上、下、左、右像素当作种子递归调用填充递归算法;否则说明该像素已被填充,不再处理。 3.4图形的基本几何变换算法 3.4.1平移 平移变换是将对象从一个位置(x,y)移到另一个位置(x1,y1)的变换。 tx,ty称为平移距离,tx=x1-1,ty=y1-y。 得到平移变换公式: x1=x+tx;y1=y+ty。 3.4.2旋转 旋转变换是以某个参考点为圆心,将对象上的各点(x,y)围绕圆心转动一个逆时针角度θ,变为新的坐标(x1,y1)的变换,当参考点为(0,0)时,旋转变换的公式为: X1=x*cosθ-y*sinа Y1=y*cosθ+x*sinа 3.4.3伸缩 比例变换是使对象按比例因子(sx,sy)放大或缩小的变换。 X1=x*sx,y1=y*sy。 当(sx,sy)取特定值时,比例变换可看作是将图形按x轴或者y轴或者原点对称。 3.5Bezier曲线算法 Bezier曲线是由多项式混合函数推导出来的,对于给定空间n+1个点的位置向量Pk(k=0,1,2…,n)可定义一个n次Bezier参数曲线,其各点坐标的插值公式是 P(t)= [0,1]Эt 其中,Pk构成该曲线的特征多边形,BENk,n(t)是n次Bernstein基函数。 4、项目效果 画图软件主界面包括菜单栏和快捷键两部分: 菜单栏主要有文件,画图,算法,画图方式和图形变换几个功能。 在文件中可以实现新建,打开,保存和另存为图片的功能。 画图中可以选择所需要的实现的图形,比如直线,圆以及填充和曲线等。 对应于画图中不同的图形,用户还可以选择不同的画图算法。 为了增强交互功能和多样性,我们还结合了不同的画图方式,常用的是鼠标画图和坐标画图。 选择坐标画图时会有对应的对话框弹出,提示用户输入相应的数据。 在图形变换中,用户可以选择图形平移和旋转。 快捷键主要包括画直线,画圆和填充以及颜色的选取的功能。 主要方便用户实现画图的功能。 主要界面如下 (1)画线: 坐标输入画线 鼠标拖动画线 (2)画圆 (3)填充 (4)Bezier曲线 (5)几何变换 平移 旋转 五、项目总结 这学期刚开始的时候,由于课程比较少,所以空闲的时间很多。 但是相反,相比较而言,花在学习的时间却打了很大的折扣。 看到大家有的考研,有的找工作,大部分精力都不放在学习上了。 所以,自己也有点懈怠了,上课的时候很容易走神,课上老师布置的练习也没有好好的做。 最多只是每次实验的时候临时抱佛脚,把书本上的算法看一下,写个程序和报告就交上去了,但很多时候都不理解课本上的算法,只是照葫芦画瓢,学的很浮躁。 但是,开始课程设计之后,觉得自己应该静下心来好好做一下,不管怎么样,自己浪费的时间已经够多的了,不能在让自己这么放肆下去。 通过这次课程设计我受益匪浅,不仅巩固了所学的知识,而且还学到了很多课本上涉及不到的知识,而且也很好的锻炼的自己的动手实践能力。 但由于知识有限,而且对编程技术掌握的不是很熟练,因此做的结果不太好,与我原来的设想有些差距。 这次课程设计可以说是在理解图形学的基础上对编程的一次学习过程,虽然做的不好,但也学到了很多知识,对自己以后进行图形学设计有很大的帮助。 在做本次课程设计时,我们尽可能的将以前所学的编译原理思想运用到这次课程设计中来。 在进行详细设计之前,先进行需求功能分析,在功能分析的基础上,划分程序的框架,创建类来分担不同的功能,并根据类的功能加入函数和变量,这对详细设计有一个总纲的作用。 这收到了很好的效果。 这对我这次课程设计帮助很大! 而且对所有的知识也起到了很好的巩固作用! 但是我们这个实验还有很多不足的地方,功能也不是很完善,期待以后更好的改进。 6、参考文献 1.张曦煌杜俊俐.计算机图形学.北京邮电出版社 2.孔令德计算机图形学基础教程.清华大学出版社 7、附录 输入坐标画圆: voidCMydrawView: : Circle(POINTpc,intr,CDC*pDC) { intx,y; floatp; pDC->SetViewportOrg(pc); x=0; y=r; p=1.25-r; while(x<=y+1) { //第1象限 pDC->SetPixel(x,y,m_lPenColor); pDC->SetPixel(y,x,m_lPenColor); //第2象限 pDC->SetPixel(-x,y,m_lPenColor); pDC->SetPixel(-y,x,m_lPenColor); //第3象限 pDC->SetPixel(-y,-x,m_lPenColor); pDC->SetPixel(-x,-y,m_lPenColor); //第4象限 pDC->SetPixel(x,-y,m_lPenColor); pDC->SetPixel(y,-x,m_lPenColor); x++; if(p>=0) { y--; p+=2*x+1-2*y; } else p+=2*x+1; } pDC->SetViewportOrg(0,0); } 鼠标拖动画圆: voidCMydrawView: : CirPort(intx0,inty0,intx,inty,CDC*pCD) { pCD->SetPixel(x0+x,y0+y,m_lPenColor); pCD->SetPixel(x0+y,y0+x,m_lPenColor); pCD->SetPixel(x0+y,y0-x,m_lPenColor); pCD->SetPixel(x0+x,y0-y,m_lPenColor); pCD->SetPixel(x0-x,y0-y,m_lPenColor); pCD->SetPixel(x0-y,y0-x,m_lPenColor); pCD->SetPixel(x0-y,y0+x,m_lPenColor); pCD->SetPixel(x0-x,y0+y,m_lPenColor); } 坐标画直线: voidCMydrawView: : Line_Mda(POINTp1,POINTp2,CDC*pDC) { intx; floaty,a,b,d,dt1,dt2,ystp; if(abs(p2.x-p1.x)>abs(p2.y-p1.y)) { if(p1.x>p2.x) {x=p1.x;p1.x=p2.x;p2.x=x; y=p1.y;p1.y=p2.y;p2.y=y; } if(p2.y==p1.y) { for(x=p1.x;x<=p2.x;x++) pDC->SetPixel(x,p1.y,m_lPenColor); } a=p1.y-p2.y; b=p2.x-p1.x; if(a>0) {a=-a;ystp=-1;} else ystp=1; d=2*a+b; dt1=2*a; dt2=2*(a+b); for(x=p1.x,y=p1.y;x<=p2.x;x++) { if(d>=0) d+=dt1; else { d+=dt2; y=y+ystp; } pDC->SetPixel(x,(int)y,m_lPenColor); } } else { if(p1.y>p2.y) {x=p1.x;p1.x=p2.x;p2.x=x; y=p1.y;p1.y=p2.y;p2.y=y; } if(p1.x==p2.x) { for(y=p1.y;y<=p2.y;y++) pDC->SetPixel(p1.x,y,m_lPenColor); } a=p1.x-p2.x; b=p2.y-p1.y; if(a>0) {a=-a;ystp=-1;} else ystp=1; d=2*a+b; dt1=2*a; dt2=2*(a+b); for(x=p1.x,y=p1.y;y<=p2.y;y++) { if(d>=0) d+=dt1; else { d+=dt2; x+=ystp; } pDC->SetPixel(x,(int)y,m_lPenColor); } } } 鼠标画直线: voidCMydrawView: : Line_Dda(POINTp1,POINTp2,CDC*pDC) { intx,tx,ty; floatdx,dy,y,k; if(abs(p2.x-p1.x)>abs(p2.y-p1.y)) { if(p1.y==p2.y) { for(x=p1.x;x<=p2.x;x++) pDC->SetPixel(x,int(p1.y+0.5),m_lPenColor); } if(p2.x { tx=p1.x;p1.x=p2.x;p2.x=tx; ty=p1.y;p1.y=p2.y;p2.x=ty; } dx=p2.x-p1.x; dy=p2.y-p1.y; k=dy/dx; y=p1.y; for(x=p1.x;x<=p2.x;x++) { pDC->SetPixel(p1.x,int(y+0.5),m_lPenColor); y=y+k; } } else { if(p1.x==p2.x) { for(y=p1.y;y<=p2.y;y++) pDC->SetPixel(p1.x,int(y+0.5),m_lPenColor); } if(p2.y { tx=p1.x;p1.x=p2.x;p2.x=tx; ty=p1.y;p1.y=p2.y;p2.x=ty; } dx=p2.x-p1.x; dy=p2.y-p1.y; k=dx/dy; x=p1.x; for(y=p1.y;y<=p2.y;y++) { pDC->SetPixel(int(x+0.5),y,m_lPenColor); x=x+k; } } } 图形变换的算法: voidCMydrawView: : OnChange() { //TODO: Addyourcommandhandlercodehere cchangedlg; CClientDCpDC(this); if(dlg.DoModal()==IDOK) { CRectrect; this->GetClientRect(&rect); pDC.SetMapMode(MM_ANISOTROPIC); pDC.SetViewportOrg(rect.right/2,rect.bottom/2); pDC.SetViewportExt(rect.right,rect.bottom); pDC.SetWindowOrg(0,0); pDC.SetWindowExt((rect.right-rect.left),(rect.top-rect.bottom)); pDC.MoveTo(0,0); pDC.LineTo(0,rect.top-rect.bottom); pDC.MoveTo(0,0); pDC.LineTo(0,rect.bottom-rect.top); pDC.MoveTo(0,0); pDC.LineTo(rect.right-rect.left,0); pDC.LineTo(rect.left-rect.right,0); POSITIONpos=m_sharpList.GetHeadPosition(); while(pos! =NULL) { CSharp*pSharp=m_sharpList.GetNext(pos); pSharp->change(dlg.m_pingyix,dlg.m_pingyiy,dlg.m_xuanzhuang); pSharp->DrawSharp(&pDC); } pos=m_fillList.GetHeadPosition(); while(pos! =NULL) { CFill*pSharp=m_fillList.GetNext(pos); pSharp->change(dlg.m_pingyix,dlg.m_pingyiy,dlg.m_xuanzhuang); pSharp->DrawFill(&pDC); } } this->xzflag=1; } 种子填充的算法: voidCMydrawView: : Seedfill(intx,inty,intoldcolor,intnewcolor,CDC*pDC) { if(pDC->GetPixel(x,y)==oldcolor) { pDC->SetPixelV(x,y,newcolor); Seedfill(x,y+1,oldcolor,newcolor,pDC); Seedfill(x,y-1,oldcolor,newcolor,pDC); Seedfill(x-1,y,oldcolor,newcolor,pDC); Seedfill(x+1,y,oldcolor,newcolor,pDC); } } 函数填充的算法: this->Seedfill(point.x,point.y,RGB(255,255,255),this->m_lPenColor,pDC); Beizer算法生成曲线: voidCBeizer: : DrawSharp(CDC*pDC) { CPenpenStroke; penStroke.CreatePen(PS_SOLID,1,RGB(255,0,0)); CPen*pOldPen=pDC->SelectObject(&penStroke); inti,k; floatt,x,y; floatpx[100],py[100]; intn=this->pointarray.GetSize(); k=this->rate; for(i=0;i { px[i]=this->pointarray[i].x; py[i]=this->pointarray[i].y; } n=n-1; pDC->MoveTo(this->pointarray[0]); for(i=0;i<=k;i++) {t=(float)i/k; x=decas(px,t,n);y=decas(py,t,n
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 期末 课程设计