计算机图形学实验报告 课程设计 大作业.docx
- 文档编号:30134185
- 上传时间:2023-08-05
- 格式:DOCX
- 页数:22
- 大小:29.20KB
计算机图形学实验报告 课程设计 大作业.docx
《计算机图形学实验报告 课程设计 大作业.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验报告 课程设计 大作业.docx(22页珍藏版)》请在冰豆网上搜索。
计算机图形学实验报告课程设计大作业
安徽建筑工业学院
计算机图形学实验报告
院(系)名称:
专业:
班级:
姓名:
学号:
指导老师:
实验一实现任意直线的中点画线算法
【实验目的】
掌握直线的中点画线算法;
【实验环境】
VC++6.0
【实验内容】
利用任意的一个实验环境,编制源程序,实现直线的中点画线法。
【实验原理】
假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点P1(xp+1,yp)或P2(xp+1,yp+1)。
若P1与P2的中点(xp+1,yp+0.5)称为M,Q为理想直线与x=xp+1垂线的交点。
当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点。
这就是中点画线法的基本原理。
图2.1.2中点画线法每步迭代涉及的象素和中点示意图
下面讨论中点画线法的实现。
过点(x0,y0)、(x1,y1)的直线段L的方程式为F(x,y)=ax+by+c=0,其中,a=y0-y1,b=x1-x0,c=x0y1-x1y0,欲判断中点M在Q点的上方还是下方,只要把M代入F(x,y),并判断它的符号即可。
为此,我们构造判别式:
d=F(M)=F(xp+1,yp+0.5)=a(xp+1)+b(yp+0.5)+c
当d<0时,M在L(Q点)下方,取P2为下一个象素;
当d>0时,M在L(Q点)上方,取P1为下一个象素;
当d=0时,选P1或P2均可,约定取P1为下一个象素;
注意到d是xp,yp的线性函数,可采用增量计算,提高运算效率。
若当前象素处于d≥0情况,则取正右方象素P1(xp+1,yp),要判下一个象素位置,应计算d1=F(xp+2,yp+0.5)=a(xp+2)+b(yp+0.5)=d+a,增量为a。
若d<0时,则取右上方象素P2(xp+1,yp+1)。
要判断再下一象素,则要计算d2=F(xp+2,yp+1.5)=a(xp+2)+b(yp+1.5)+c=d+a+b,增量为a+b。
画线从(x0,y0)开始,d的初值d0=F(x0+1,y0+0.5)=F(x0,y0)+a+0.5b,因 F(x0,y0)=0,所以d0=a+0.5b。
由于我们使用的只是d的符号,而且d的增量都是整数,只是初始值包含小数。
因此,我们可以用2d代替d来摆脱小数,写出仅包含整数运算的算法程序。
【实验程序】
voidMidpointLine(intx0,inty0,intx1,inty1,intcolor)
{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 {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*(a+b)=6, xy d 00 1 10 -3 21 3 31 -1 42 5 52 15 2.1.3中点画线法 实验二实现任意一种线段的裁剪算法以及多边形裁剪算法 【实验目的】 1、掌握直线段裁剪的基本原理; 2、掌握多边形裁剪的基本原理; 【实验环境】 VC++6.0 【实验内容】 编制程序,完成直线段和多边形的裁减过程。 【实验原理】 1.算法基本思想 对每条直线段p1(x1,y1)p2(x2,y2)分三种情况处理: (1)直线段完全可见,“简取”之。 (2)直线段完全不可见,“简弃”之。 (3)直线段既不满足“简取”的条件,也不满足“简弃”的条件,需要对直线段按交点进行分段,分段后重复上述处理。 2.算法步骤 (1)编码 对于任一端点(x,y),赋予一个4位的二进制码D3D2D1D0。 编码规则如下: 若x 若x>wxr,则D1=1,否则D1=0; 若y 若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 //#include #include #include /////////////////////////////////////////////////////////////////////////// constwinLeftBitCode=0x1; constwinRightBitCode=0x2; constwinBottomBitCode=0x4; constwinTopBitCode=0x8; /////////////////////////////////////////////////////////////////////////// classwcPt2D{public: GLfloatx,y;}; /////////////////////////////////////////////////////////////////////////// inlineintinside(intcode){returnint(! code);} ////////////////////////////////////////////////////////////////////////// inlineintreject(intcode1,intcode2) { returnint(code1&code2); } ///////////////////////////////////////////////////////////////////////// inlineintaccept(intcode1,intcode2) { returnint(! (code1|code2)); } ///////////////////////////////////////////////////////////////////////// GLubyteencode(wcPt2Dpt,wcPt2DwinMin,wcPt2DwinMax) { GLubytecode=0x00; if(pt.x code=code|winLeftBitCode; if(pt.x>winMax.x) code=code+winRightBitCode; if(pt.y code=code|winBottomBitCode; if(pt.y>winMax.y) code=code|winTopBitCode; return(code); } //////////////////////////////////////////////////////////////////////////// voidswapPts(wcPt2D*p1,wcPt2D*p2) { wcPt2Dtmp; tmp=*p1; *p1=*p2; *p2=tmp; } ////////////////////////////////////////////////////////////////////////// voidswapCodes(GLubyte*c1,GLubyte*c2) { GLubytetmp; tmp=*c1;*c1=*c2;*c2=tmp; } //////////////////////////////////////////////////////////////////////// voiddraw_pixel(intix,intiy/*,intvalue*/) { glBegin(GL_POINTS); glVertex2i(ix,iy); glEnd(); } //////////////////////////////////////////////////////////////////////// intinlineround(constfloata){returnint(a+0.5);} ///////////////////////////////////////////////////////////////////////// voidlineDDA(intx0,inty0,intx_end,inty_end,doublea,doubleb,doublec) { glColor3f(a,b,c); intdx=x_end-x0; intdy=y_end-y0; intsteps,k; floatxIncrement,yIncrement,x=x0,y=y0; if(abs(dx)>abs(dy)) steps=abs(dx); else steps=abs(dy); xIncrement=float(dx)/float(steps); yIncrement=float(dy)/float(steps); draw_pixel(round(x),round(y)); for(k=0;k { x+=xIncrement; y+=yIncrement; draw_pixel(round(x),round(y)); } } //////////////////////////////////////////////////////////////////////////////////// voidlineClipCohSuth(wcPt2DwinMin,wcPt2DwinMax,wcPt2Dp1,wcPt2Dp2) { GLubytecode1,code2; GLintdone=false,plotLine=false; GLfloatm; while(! done) { code1=encode(p1,winMin,winMax); code2=encode(p2,winMin,winMax); if(accept(code1,code2)) { done=true; plotLine=true; } else if(reject(code1,code2)) done=true; else { if(inside(code1)) { swapPts(&p1,&p2); swapCodes(&code1,&code2); } if(p2.x! =p1.x) m=(p2.y-p1.y)/(p2.x-p1.x); if(code1&winLeftBitCode) { p1.y+=(winMin.x-p1.x)*m; p1.x=winMin.x; } else if(code1&winRightBitCode) { p1.y+=(winMax.x-p1.x)*m; p1.x=winMax.x; } else if(code1&winBottomBitCode) { if(p2.x! =p1.x) p1.x+=(winMin.y-p1.y)/m; p1.y=winMin.y; } else if(code1&winTopBitCode) { if(p2.x! =p1.x) p1.x+=(winMax.y-p1.y)/m; p1.y=winMax.y; } } } if(plotLine) lineDDA(round(p1.x),round(p1.y),round(p2.x),round(p2.y),0.0,0.0,1.0); } /////////////////////////////////////////////////////////////////////////////////////// voiddisplay() { glClear(GL_COLOR_BUFFER_BIT); wcPt2DwinMin,winMax,p1,p2,q1,q2,t1,t2,m1,m2; //裁剪窗口 winMin.x=80; winMin.y=100; winMax.x=290; winMax.y=500; /*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); */ /*//全图 winMin.x=0; winMin.y=000; winMax.x=500; winMax.y=500; */ /////////////////////// p1.x=0; p1.y=0; p2.x=400; p2.y=400; ////////////////////// q1.x=0; q1.y=0; q2.x=100; q2.y=400; ////////////////////// t1.x=100; t1.y=400; t2.x=400; t2.y=400; ////////////////////// m1.x=300; m1.y=200; m2.x=100; m2.y=400; //只显示裁剪框内的线段 lineClipCohSuth(winMin,winMax,p1,p2); lineClipCohSuth(winMin,winMax,q1,q2); lineClipCohSuth(winMin,winMax,t1,t2); lineClipCohSuth(winMin,winMax,m1,m2); //显示裁剪框和待剪线段 /* lineDDA(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); */ glFlush(); } voidmyinit() { glClearColor(0.8,1.0,1.0,1.0); //glColor3f(0.0,0.0,1.0); glPointSize(1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0,500.0,0.0,500.0); glViewport(0,0,200,500); } voidmain(intargc,char**argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(500,500); glutInitWindowPosition(200.0,200.0); glutCreateWindow("CG_test_CG_test_Cohen-Sutherland线段裁剪算法示例"); //glutFullScreen(); glutDisplayFunc(display); myinit(); glutMainLoop(); } 稍微修改源程序即可得到以下裁剪框以及被裁剪线段: 二: Sutherland_Hodgman多边形裁剪算法 #defineTRUE1 #defineFALSE0 typedefstruct{ floatx,y; }vertex; voidintersect(p1,p2,clipboundary,intersectp) vertexp1,p2,*clipboundary,*intersectpt; /*p1和p2为多边形的边的起点和终点,clipboundary为窗口边界,intersectpt中返回边与窗口边界的交点*/ { if(clipboundary[0].y==clipboundary[1].y)/*水平边界*/ { intersectpt->y=clipboundary[0].y; intersectpt->x=p1.x+(clipboundary[0].y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y); } else/*垂直边界*/ { intersectpt->x=clipboundary[0].x; intersectpt->y=p1.y+(clipboundary[0].x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x); } } intinside(testvertex,clipboundary) vertextestvertex,*clipboundary; /*如果顶点testvertex在窗口边界clipboundary的内部,那么返回TRUE;否则返回FALSE*/ { if(clipboundary[1].x if(testvertex.y<=clipboundary[0].y) returnTRUE; if(clipboundary[1].x>clipboundary[0].x)/*下边界*/ if(testvertex.y>=clipboundary[0].y) returnTRUE; if(clipboundary[1].y>clipboundary[0].y)/*右边界*/ if(testvertex.x<=clipboundary[0].x) returnTRUE; if(clipboundary[1].y if(testvertex.y<=clipboundary[0].x) returnTRUE; returnFALSE; } outputvertex(outvertex,outlength,outvertexlist) vertexoutvertex; int*outlength; vertex*outvertexlist /*向输出顶点序列中输出顶点outvertex*/ { outvertexlist[*outlength]=outvertex; (*outlength)++; } voidSutherland_Hodgman_Polygon_Clipping(invertexlist,outvertexlist,inlength,outlength,clipboundary) vertex*invertexlist,*outvertexlist; intinlength,*outlength; vertex*clipboundary; /*invertexlist为输入顶点序列,inlength为输入序列长度;outvertexlist为输出顶点序列,outlenght中返回输出序列长度;clipboundary为窗口边界*/ { vertexs,p,i; intj; *outlength=0; s=invertexlist[inlength-1];/*输入顶点序列的最后一个顶点*/ for(j=0;j { p=invertexlist[j]; if(inside(p,clip
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机图形学实验报告 课程设计 大作业 计算机 图形学 实验 报告 作业
![提示](https://static.bdocx.com/images/bang_tan.gif)