计算机图形学实验报告课程设计大作业_第1页
计算机图形学实验报告课程设计大作业_第2页
计算机图形学实验报告课程设计大作业_第3页
计算机图形学实验报告课程设计大作业_第4页
计算机图形学实验报告课程设计大作业_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

安徽建筑工业学院计算机图形学实验报告院(系)名称:专业:班级:姓名:学号:指导老师:实验一实现任意直线的中点画线算法【实验目的】掌握直线的中点画线算法;【实验环境】VC++6.0【实验内容】利用任意的一个实验环境,编制源程序,实现直线的中点画线法。【实验原理】假定直线斜率k在0~1之间,当前象素点为(x,y),则下一个象素点有两种可选择点ppP1(x+1,y)或P(x+1,y+1)。若P与P的中点(x+1,y+0.5)称为M,Q为理想直线M在Q的下方时,则取P应为下一个象素点;当M在Q的上方2pp2pp12pp与x=x+1垂线的交点。当p时,则取P为下一个象素点。这就是中点画线法的基本原理。1图2.1.2中点画线法每步迭代涉及的象素和中点示意图下面讨论中点画线法的实现。过点(x,y)、(xy)的直线段L的方程式为F(x,0011,y)=ax+by+c=0,其中,a=y0-y,b=x-x,c=xy-xy,欲判断中点M在Q点的上方还是下1100110方,只要把M代入F(x,y),并判断它的符号即可。为此,我们构造判别式:d=F(M)=F(x+1,y+0.5)=a(x+1)+b(y+0.5)+cpppp当d<0时,M在L(Q点)下方,取P为下一个象素;2当d>0时,M在L(Q点)上方,取P为下一个象素;1当d=0时,选P或P均可,约定取P为下一个象素;121注意到d是x,y的线性函数,可采用增量计算,提高运算效率。pp若当前象素处于d0情况,则取正右方象素P(x+1,y),要判下一个象素位置,应计1pp算d=F(x+2,y+0.5)=a(x+2)+b(y+0.5)=d+a,增量为a。1pppp若d<0时,则取右上方象素P(x+1,y+1)。要判断再下一象素,则要计算d=F(x+2,22pppy+1.5)=a(x+2)+b(y+1.5)+c=d+a+b,增量为a+b。画线从(x,y)开始,d的初值d=F(x+1,0000pppy+0.5)=F(x,y)+a+0.5b,因F(x,y)=0,所以d=a+0.5b。000000由于我们使用的只是d的符号,而且d的增量都是整数,只是初始值包含小数。因此,我们可以用2d代替d来摆脱小数,写出仅包含整数运算的算法程序。【实验程序】voidMidpointLine(intx0,inty0,intx1,inty1,in{inta,b,d1,d2,d,x,y;a=y0-y1;b=x1-x0;d=2*a+b;d1=2*a;d2=2*(a+b);x=x0;y=y0;drawpixel(x,y,color);while(x<x1){if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}drawpixel(x,y,color);}/*while*/}/*midPointLine*/举例:用中点画线方法扫描转换连接两点P0(0,0)和P1(5,2)的直线段。a=y0-y1=-2;b=x1-x0=5;d0=2*a+b=1;d1=2*a=-4;d2=2*(axyd00110-321331-14252.1.3中点画线法5215实验二实现任意一种线段的裁剪算法以及多边形裁剪算法【实验目的】1、掌握直线段裁剪的基本原理;2、掌握多边形裁剪的基本原理;【实验环境】VC++6.0【实验内容】编制程序,完成直线段和多边形的裁减过程。【实验原理】1.算法基本思想对每条直线段p1(x1,y1)p2(x2,y2)分三种情况处理:(1)直线段完全可见,“简取”之。(2)直线段完全不可见,“简弃”之。(3)直线段既不满足“简取”的条件,也不满足“简弃”的条件,需要对直线段按交点进行分段,分段后重复上述处理。2.算法步骤(1)编码对于任一端点(x,y),赋予一个4位的二进制码D3D2D1D0。编码规则如下:若x<wxl,则D0=1,否则D0=0;若x>wxr,则D1=1,否则D1=0;若y<wyb,则D2=1,否则D2=0;若y>wyt,则D3=1,否则D3=0。(2)裁剪先求出端点p1和p2的编码code1和code2,然后:若code1|code2=0,对直线段应简取之。若code1&code2≠0,对直线段可简弃之。若上述两条件均不成立。则需求出直线段与窗口边界的交点。在交点处把线段一分为二,其中必有一段完全在窗口外,可以弃之。再对另一段重复进行上述处理,直到该线段完全被舍弃或者找到位于窗口内的一段线段为。止(3)求交假定直线的端点坐标为(x1,y1)和(x2,y2)左、右边界交点的计算上、下边界交点的计算。3.算法实现(1)输入直线段的两端点坐标:p1(x1,y1)、p2(x2,y2),以及窗口的四条边界坐标:wyt、wyb、wxl和wxr。(2)对p1、p2进行编码:点p1的编码为code1,点p2的编码为code2。(3)若code1|code2=0,对直线段应简取之,转(6);否则,若code1&code2≠0,对直线段可简弃之,转(7);当上述两条均不满足时,进行步骤(4)。(4)确保p1在窗口外部:若p1在窗口内,则交换p1和p2的坐标值和编码。(5)按左、右、上、下的顺序求出直线段与窗口边界的交点,并用该交点的坐标值替换p1的坐标值。也即在交点s处把线段一分为二,并去掉p1s这一段。考虑到p1是窗口外的一点,因此可以去掉p1s。转(2)。(6)用直线扫描转换算法画出当前的直线段p1p2。(7)算法结束。【实验程序】一:Cohen-Sutherland线段裁剪算法#include<gl/glut.h>inlineintaccept(intcode1,intcode2)//#include<gl/wingdi.h>/*SetPixel()*/#include<math.h>{returnint(!(code1|code2));}#include<stdio.h>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////constwinLeftBitCode=0x1;constwinRightBitCode=0x2;constwinBottomBitCode=0x4;constwinTopBitCode=0x8;/////GLubyteencode(wcPt2Dpt,wcPt2DwinMin,wcPt2DwinMax){//////////////////////////////////////////////////////////////////////////////////////////GLubytecode=0x00;if(pt.x<winMin.x)code=code|winLeftBitCode;classwcPt2D{public:GLfloatx,y;};if(pt.x>winMax.x)code=code+winRightBitCode;///////////////////////////////////////////////////////////////////if(pt.y<winMin.y)code=code|winBottomBitCode;if(pt.y>winMax.y)inlineintinside(intcode){returnint(!code);}///////////////////////////////////////////////////////////////////code=code|winTopBitCode;return(code);}////////////////////////////////////////////////////////////////////inlineintreject(intcode1,intcode2)////////{returnint(code1&code2);}voidswapPts(wcPt2D*p1,wcPt2D*p2){wcPt2Dtmp;tmp=*p1;*p1=*p2;/////////////////////////////////////////////////////////////////////////*p2=tmp;draw_pixel(round(x),round(y));for(k=0;k<steps;k++){}///////////////////////////////////////////////////////////////////x+=xIncrement;y+=yIncrement;draw_pixel(round(x),round(y));}///////voidswapCodes(GLubyte*c1,GLubyte*c2)}{GLubytetmp;////////////////////////////////////////////////////////////////////tmp=*c1;*c1=*c2;*c2=tmp;////////////////}////////////////////////////////////////////////////////////////////////voidlineClipCohSuth(wcPt2DwinMin,wcPt2DwinMax,wcPt2Dp1,wcPt2Dp2)voiddraw_pixel(intix,intiy/*,intvalue*/){{GLubytecode1,code2;glBegin(GL_POINTS);GLintdone=false,plotLine=false;glVertex2i(ix,iy);GLfloatm;glEnd();}while(!done){code1=encode(p1,winMin,winMax);///////////////////////////////////////////////////////////////////intinlineround(constfloata){returnintcode2=encode(p2,winMin,winMax);/////if(accept(code1,code2)){done=true;(a+0.5);}plotLine=true;}///////////////////////////////////////////////////////////////////else//////if(reject(code1,code2))voidlineDDA(intx0,inty0,intx_end,intdone=true;y_end,doublea,doubleb,doublec){else{glColor3f(a,b,c);intdx=x_end-x0;intdy=y_end-y0;intsteps,k;if(inside(code1)){swapPts(&p1,&p2);floatxIncrement,yIncrement,x=x0,y=y0;if(abs(dx)>abs(dy))steps=abs(dx);swapCodes(&code1,&code2);}elseif(p2.x!=p1.x)steps=abs(dy);xIncrement=float(dx)/float(steps);yIncrement=float(dy)/float(steps);m=(p2.y-p1.y)/(p2.x-p1.x);if(code1&winLeftBitCode){////////////////////////////////////////////////////////////////////p1.y+=(winMin.x-p1.x)*m;///////////////////p1.x=winMin.x;}elsevoiddisplay(){if(code1&winRightBitCode)glClear(GL_COLOR_BUFFER_BIT);{wcPt2DwinMin,winMax,p1,p2,q1,q2,t1,t2,m1,m2;p1.y+=(winMax.x-p1.x)*m;p1.x=winMax.x;//裁剪窗口winMin.x=80;}winMin.y=100;elsewinMax.x=290;winMax.y=500;if(code1&winBottomBitCode)/*lineDDA(80,100,80,450,1.0,0.0,0.0);lineDDA(80,100,290,100,1.0,0.0,0.0);lineDDA(290,100,290,450,1.0,0.0,0.0);lineDDA(80,450,290,450,1.0,0.0,0.0);*/{if(p2.x!=p1.x)p1.x+=(winMin.y-p1.y)/m;p1.y=winMin.y;/*//全图winMin.x=0;winMin.y=000;winMax.x=500;winMax.y=500;*/}elseif(code1&winTopBitCode){///////////////////////p1.x=0;if(p2.x!=p1.x)p1.y=0;p2.x=400;p2.y=400;//////////////////////q1.x=0;p1.x+=(winMax.y-p1.y)/m;p1.y=winMax.y;}q1.y=0;}q2.x=100;q2.y=400;//////////////////////t1.x=100;}if(plotLine)lineDDA(round(p1.x),round(p1.y),round(p2.x),rt1.y=400;ound(p2.y),0.0,0.0,1.0);}t2.x=400;t2.y=400;////////////////////////glutFullScreen();glutDisplayFunc(display);myinit();m1.x=300;m1.y=200;m2.x=100;glutMainLoop();m2.y=400;//只显示裁剪框内的线段lineClipCohSuth(winMin,winMax,p1,p2);lineClipCohSuth(winMin,winMax,q1,q2);lineClipCohSuth(winMin,winMax,t1,t2);lineClipCohSuth(winMin,winMax,m1,m2)}稍微修改源程序即可得到以下裁剪框以及被裁剪线段:;二:Sutherland_Hodgman多边形裁剪算法#defineTRUE1//显示裁剪框和待剪线段/*#defineFALSE0lineDDA(300,200,100,400,0.0,0.0,1.0);lineDDA(0,0,100,400,0.0,0.0,1.0);lineDDA(100,400,400,400,0.0,0.0,1.0);lineDDA(0,0,400,400,0.0,0.0,1.0);typedefstruct{floatx,y;}vertex;*/glFlush();voidintersect(p1,p2,clipboundary,intersectp)vertexp1,p2,*clipboundary,*intersectpt;}/*p1和p2为多边形的边的起点和终点,voidmyinit(){clipboundary为窗口边界,intersectpt中返回边与窗口边界的交点*/glClearColor(0.8,1.0,1.0,1.0);{//glColor3f(0.0,0.0,1.0);glPointSize(1.0);if(clipboundary[0].y==clipboundary[1].y)/*水平边界*/glMatrixMode(GL_PROJECTION);glLoadIdentity();{intersectpt->y=clipboundary[0].y;gluOrtho2D(0.0,500.0,0.0,500.0);glViewport(0,0,200,500);intersectpt->x=p1.x+(clipboundary[0].y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y);}}else/*垂直边界*/{intersectpt->x=clipboundary[0].x;voidmain(intargc,char**argv){intersectpt->y=p1.y+(clipboundary[0].x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x);glutInit(&argc,argv);}}glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(500,500);intinside(testvertex,clipboundary)vertextestvertex,*clipboundary;glutInitWindowPosition(200.0,200.0);glutCreateWindow("CG_test_CG_test_Co/*如果顶点testvertex在窗口边界clipboundary的内部,那么返回TRUE;否则返回FALSE*/hen-Sutherland线段裁剪算法示例");{列的最后一个顶点*/if(clipboundary[1].x<clipboundary[0].x)/*上边界for(j=0;j<inlength;j++)*/{if(testvertex.y<=clipboundary[0].y)returnTRUE;p=invertexlist[j];if(inside(p,clipboundary))/*情况1和4if(clipboundary[1].x>clipboundary[0].x)*/*//*下边界*/{if(testvertex.y>=clipboundary[0].y)returnTRUE;if(inside(s,clipboundary))/*情况1if(clipboundary[1].y>clipboundary[0].y)outputvertex(p,outlength,outvertexlist);/*右边界*/else/*情况4*/if(testvertex.x<=clipboundary[0].x)returnTRUE;{intersect(s,p,clipboundary,&i);if(clipboundary[1].y<clipboundary[0].y)outputvertex(i,outlength,outvertexlist);/*左边界*/outputvertex(p,outlength,outvertexlist);if(testvertex.y<=clipboundary[0].x)returnTRUE;}}returnFALSE;else/*情况2和3*/}{if(inside(s,clipboundary))/*情况2*/{outputvertex(outvertex,outlength,outvertexlist)intersect(s,p,clipboundary,&i);vertexoutvertex;outputvertex(i,outlength,outvertexlist);}int*outlength;vertex*outvertexlist}/*情况3无输出*//*向输出顶点序列中输出顶点outvertex*/s=p;/*准备处理下一条边*/{}outvertexlist[*outlength]=outvertex;}(*outlength)++;}voidSutherland_Hodgman_Polygon_Clipping(invertexlist,outvertexlist,inlength,outlength,clipboundary)vertex*invertexlist,*outvertexlist;intinlength,*outlength;vertex*clipboundary;/*invertexlist为输入顶点序列,inlength为输入outvertexlist为输出顶点序列,outlenghtclipboundary为窗口边界序列长度;中返回输出序列长度;*/{vertexs,p,i;intj;*outlength=0;s=invertexlist[inlength-1];/*输入顶点序实验三实现任意一种区域填充算法【实验目的】1、掌握多边形填充的基本原理;2、掌握边界标志算法来实现多边形填充的思想。【实验环境】VC++6.0【实验内容】利用任意的一个实验环境,编制源程序,实现区域填充的描绘线算法【实验原理】这里讨论的区域指已经表示成点阵形式的填充图形,它是象素的集合。区域可采用内点表示和边界表示两种表示形式。在内点表示中,区域内的所有象素着同一颜色。在边界表示中,区域的边界点着同一颜色。区域填充指先将区域的一点赋予指定的颜色,然后将该颜色扩展到整个区域的过程。区域填充算法要求区域是连通的,因为只有在连通区域中,才可能将种子点的颜色扩展到区域内的其它点。区域可分为4向连通区域和8向连通区域。4向连通区域指的是从区域上一点出发,可通过四个方向,即上、下、左、右移动的组合,在不越出区域的前提下,到达区域内的任意象素;8向连通区域指的是从内一每象素出发

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论