计算机图形学 二维裁剪算法CohenSutherland的实现.docx
- 文档编号:10575987
- 上传时间:2023-02-21
- 格式:DOCX
- 页数:18
- 大小:203.47KB
计算机图形学 二维裁剪算法CohenSutherland的实现.docx
《计算机图形学 二维裁剪算法CohenSutherland的实现.docx》由会员分享,可在线阅读,更多相关《计算机图形学 二维裁剪算法CohenSutherland的实现.docx(18页珍藏版)》请在冰豆网上搜索。
计算机图形学二维裁剪算法CohenSutherland的实现
实验六二维裁剪算法Cohen_Sutherland的实现
一、实验目的:
理解并掌握直线裁剪算法。
使用VisualC++实现二维直线的裁剪的Cohen_Sutherland算法。
对窗口进行编码,并实现相应的裁剪函数。
二、实验内容及要求:
1、要求用消息映射的方式,绘制出一个裁剪窗口,大小为200×150象素;
2、按照例程的步骤画出3条典型线段,分别对应于完全在裁剪窗口内、完全在裁剪窗口外、穿过裁剪窗口三种情况,并按照本实验例程的方法用颜色分别表示出裁剪后的情况;
3、按要求撰写实验报告,写出实验心得,并在实验报告中附上程序的核心算法代码。
三、实验设备:
微机,VisualC++6.0
四、实验内容及步骤:
1、打开VC,新建一个MFCAppwizard项目,选择创建单文档工程(SDI工程)。
假设工程名为Clip。
如图1和图2所示。
图1
图2
2、在图2的界面上点击Finish,完成工程的创建。
3、在视图类ClipView中定义变量CRectrect;用于记录裁剪窗口的位置;
4、在ClipView.cpp文件中定义四个宏,记录裁剪窗口的上下左右四个位置:
#defineLEFT100
#defineRIGHT300
#defineTOP150
#defineBOTTOM310
5、在视图类的构造函数中为rect赋值;
CClipView:
:
CClipView()
{
//TODO:
addconstructioncodehere
rect=CRect(LEFT,TOP,RIGHT,BOTTOM);
}
6、在视图类(类CFillView中)的OnDraw()函数中绘制裁剪矩形,OnDraw函数的代码如下:
voidCClipView:
:
OnDraw(CDC*pDC)
{
CClipDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
pDC->Rectangle(&rect);
}
7、在视图类(类CFillView中)添加成员函数intEncode(intx,inty),该函数用于对线段的两个顶点进行Cohen_Sutherland编码。
函数体如下:
intCClipView:
:
Encode(intx,inty)
{
intnCode=0;
if(x nCode=nCode|0x01; if(x>RIGHT) nCode=nCode|0x02; if(y>BOTTOM) nCode=nCode|0x04; if(y nCode=nCode|0x08; returnnCode; } 8、在视图类中添加Cohen_Sutherland裁剪算法的实现函数,函数体如下: voidCClipView: : CLIP_Line_Cohen_Sutherland(CPoint&P1,CPoint&P2) { intnCode1=0; intnCode2=0; nCode1=Encode(P1.x,P1.y); nCode2=Encode(P2.x,P2.y); if(nCode1==0&&nCode2==0) return;//直线在裁剪窗口内,直接返回 elseif((nCode1&nCode2)! =0) { P1=CPoint(0,0); P2=CPoint(0,0); return;//直线在裁剪窗口外,将直线的两个端点赋为0,返回 } doublewx=P2.x-P1.x; doublewy=P2.y-P1.y; doubledX=0; doubledY=0; while(nCode1! =0||nCode2! =0) { intnCode=nCode1; if(nCode1==0) nCode=nCode2; if((nCode&0x01)==0x01)//说明左边与边界有交点 { dX=LEFT; dY=P1.y+wy*(LEFT-P1.x)/wx; } elseif((nCode&0x02)==0x02)//说明右边与边界有交点 { dX=RIGHT; dY=P1.y+wy*(RIGHT-P1.x)/wx; } elseif((nCode&0x04)==0x04)//说明下边与边界有交点 { dX=(BOTTOM-P1.y)*wx/wy+P1.x; dY=BOTTOM; } elseif((nCode&0x08)==0x08)//说明上边与边界有交点 { dX=(TOP-P1.y)*wx/wy+P1.x; dY=TOP; } if(nCode==nCode1) { P1=CPoint((int)(dX+0.4),(int)(dY+0.4)); nCode1=Encode(P1.x,P1.y); } else { P2=CPoint((int)(dX+0.4),(int)(dY+0.4)); nCode2=Encode(P2.x,P2.y); } } } 9、映射菜单消息,方法是打开ResourceView菜单,依次展开MENU\IDR_MAINFRAME,添加“线段裁剪”主菜单项,在其下添加“Cohen_Sutherland算法”,如图3所示。 图3 10、在ClipView.cpp文件中(类CClipView中)映射“Cohen_Sutherland算法”的菜单消息,触发Cohen_Sutherland裁剪函数。 代码如下: voidCClipView: : OnClipLineCohenSutherland() { //TODO: Addyourcommandhandlercodehere CPointP1=CPoint(80,400); CPointP2=CPoint(200,80); CDC*pDC=this->GetDC(); CPennewPen(PS_SOLID,2,RGB(255,0,0));//用红色2个线宽绘制被裁剪初始直线 CPen*pOldPen=pDC->SelectObject(&newPen); pDC->MoveTo(P1); pDC->LineTo(P2); pDC->SelectObject(pOldPen); CLIP_Line_Cohen_Sutherland(P1,P2);//用窗口裁剪P1P2直线,裁剪后的顶点保存在P1P2中 CPenclipPen(PS_SOLID,2,RGB(0,0,255));//用蓝色2个线宽绘制窗口内裁剪之后的线段 pOldPen=pDC->SelectObject(&clipPen); pDC->MoveTo(P1); pDC->LineTo(P2); pDC->SelectObject(pOldPen); this->ReleaseDC(pDC); } 二维的Cohen_Sutherland算法实现完毕。 五、核心代码: 这里将自己编写的上机程序中的主要代码拷贝粘贴过来; 定义: #defineLEFT100 #defineRIGHT300 #defineTOP150 #defineBOTTOM310 OnDraw部分: voidCClipView: : OnDraw(CDC*pDC) { CClipDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); pDC->Rectangle(&rect); OnClipLineCohenSutherland(); //TODO: adddrawcodefornativedatahere } intCClipView: : Encode(intx,inty) { intnCode=0; if(x nCode=nCode|0x01; if(x>RIGHT) nCode=nCode|0x02; if(y>BOTTOM) nCode=nCode|0x04; if(y nCode=nCode|0x08; returnnCode; } 剪裁部分: voidCClipView: : CLIP_Line_Cohen_Sutherland(CPoint&P1,CPoint&P2) { intnCode1=0; intnCode2=0; nCode1=Encode(P1.x,P1.y); nCode2=Encode(P2.x,P2.y); if(nCode1==0&&nCode2==0) return;//直线在裁剪窗口内,直接返回 elseif((nCode1&nCode2)! =0) { P1=CPoint(0,0); P2=CPoint(0,0); return;//直线在裁剪窗口外,将直线的两个端点赋为0,返回 } doublewx=P2.x-P1.x; doublewy=P2.y-P1.y; doubledX=0; doubledY=0; while(nCode1! =0||nCode2! =0) { intnCode=nCode1; if(nCode1==0) nCode=nCode2; if((nCode&0x01)==0x01)//说明左边与边界有交点 { dX=LEFT; dY=P1.y+wy*(LEFT-P1.x)/wx; } elseif((nCode&0x02)==0x02)//说明右边与边界有交点 { dX=RIGHT; dY=P1.y+wy*(RIGHT-P1.x)/wx; } elseif((nCode&0x04)==0x04)//说明下边与边界有交点 { dX=(BOTTOM-P1.y)*wx/wy+P1.x; dY=BOTTOM; } elseif((nCode&0x08)==0x08)//说明上边与边界有交点 { dX=(TOP-P1.y)*wx/wy+P1.x; dY=TOP; } if(nCode==nCode1) { P1=CPoint((int)(dX+0.4),(int)(dY+0.4)); nCode1=Encode(P1.x,P1.y); } else { P2=CPoint((int)(dX+0.4),(int)(dY+0.4)); nCode2=Encode(P2.x,P2.y); } } } voidCClipView: : OnClipLineCohenSutherland() { CPointP1=CPoint(80,400); CPointP2=CPoint(200,80); CDC*pDC=this->GetDC(); CPennewPen(PS_SOLID,2,RGB(225,0,0));//用红色2个线宽绘制被裁剪初始直线 CPen*pOldPen=pDC->SelectObject(&newPen); pDC->MoveTo(P1); pDC->LineTo(P2); pDC->SelectObject(pOldPen); CLIP_Line_Cohen_Sutherland(P1,P2);//用窗口裁剪P1P2直线,裁剪后的顶点保存在P1P2中 CPenclipPen(PS_SOLID,2,RGB(0,145,146));//用蓝色2个线宽绘制窗口内裁剪之后的线段 pOldPen=pDC->SelectObject(&clipPen); pDC->MoveTo(P1); pDC->LineTo(P2); pDC->SelectObject(pOldPen); this->ReleaseDC(pDC); } 六、屏幕显示结果: 这里将绘出的图形界面拷贝下来; 穿过裁剪窗口 完全在裁剪窗口内改变线段坐标 CPointP1=CPoint(150,160); CPointP2=CPoint(200,280); 完全在裁剪窗口外 CPointP1=CPoint(400,460); CPointP2=CPoint(450,380); 七、思考题(尽量做,计入成绩): 1、如果要用鼠标绘制裁剪窗口和线段,应该如何编程? Cohen_Sutherland算法将窗口平面划分成九个区域,每个区域给予不同的编码。 格局线段端点落入不同的区域,给予线段端点不同编码。 基于线段端点编码,算法给出了一整套剪裁方法。 在剪裁过程中,窗口的参数要多次使用,线段端点需要多次编码,编码的计算需要多次与某些常数相“与”。 2、程序其它方面还有什么需要改进的? (提示: 如何调用裁剪函数? ) 在Ondraw加入调用函数: OnClipLineCohenSutherland(); 3、如果要用Liang-Barskey算法实现裁剪,如何修改程序? intClipT(floatp,floatq,float*u1,float*u2) { intflag=1; floatr; if(p<0.0) { r=q/p; if(r>*u2)flag=0; elseif(r>*u1) *u1=r; } elseif(p>0.0) { r=q/p; if(r<*u1)flag=0; elseif(r<*u2) *u2=r; } elseif(q<0.0)flag=0; returnflag; } voidLiang_Barsky(intxL,intyT,intxR,intyB,intx1,inty1,intx2,inty2) { floatdx,dy,u1,u2; u1=0.0;u2=1.0; dx=x2-x1; if(ClipT(-dx,x1-xL,&u1,&u2)) if(ClipT(dx,xR-x1,&u1,&u2)) { dy=y2-y1; if(ClipT(-dy,y1-yT,&u1,&u2)) if(ClipT(dy,yB-y1,&u1,&u2)) { if(u2<1.0) { x2=x1+u2*dx; y2=y1+u2*dy; } if(u1>0.0) { x1=x1+u1*dx; y1=y1+u1*dy; } line(x1,y1,x2,y2); } } } voidmain(void) { intgdriver=DETECT,gmode; intXL,XR,YB,YT; intx0,y0,x1,y1; do { registerbgidriver(EGAVGA_driver); initgraph(&gdriver,&gmode,""); cleardevice(); printf("\nLiang_Barsky\n"); printf("\n"); printf("Pleaseinputthelinenode(x0,y0,x1,y1): \n"); scanf("%d,%d,%d,%d",&x0,&y0,&x1,&y1); printf("\n"); cleardevice(); setcolor(LINE_COLOR); line(x0,y0,x1,y1); getch(); printf("\nLiang_Barsky\n"); printf("\n"); printf("Pleaseinputtherectanglepoint(XL,YT,XR,YB): \n"); scanf("%d,%d,%d,%d",&XL,&YT,&XR,&YB); printf("\n"); cleardevice(); line(x0,y0,x1,y1); setcolor(WINDOW_COLOR); rectangle(XL,YT,XR,YB); getch(); cleardevice(); rectangle(XL,YT,XR,YB); setcolor(LINE_COLOR); Liang_Barsky(XL,YT,XR,YB,x0,y0,x1,y1); getch(); printf("\n\nContinue? (y|n? )"); getchar(); }while(getchar()=='y'||getchar()=='Y'); printf("\n"); printf("pressanykeytoend! "); getch(); closegraph(); } 八、实验体会 这次试验我的收获只要有两个方面: 一个是编程水平的提高,还有一个是对计算机图形学理论知识的巩固。 首先,自此实验帮助我巩固了计算机图形学上课学习的内容,让我对算法的原理有了更为清晰的理解,并且能够根据算法,进行修改和添加,完成算法编出程序 而且,在和同学交流过程中,我学会了一些简单的技巧并且能够简单的调试程序,争取自己独立解决在编程过程中遇到的问题。 通过学习和实践,完成二维裁剪算法Cohen_Sutherland的实现3条典型线段,分别对应于完全在裁剪窗口内、完全在裁剪窗口外、穿过裁剪窗口三种情况,通过改变线段的坐标加以实现。 还不能忘记在Ondraw加入调用函数: OnClipLineCohenSutherland(); 总之,这次试验是我的编程水平有一定的提高,相信会对我以后的学习起到很大作用。 九、注意及特别说明: 如对VisualC++的编译环境不熟悉,请课下提前参考VisualC++的相关书籍和MSDN。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机图形学 二维裁剪算法CohenSutherland的实现 计算机 图形学 二维 裁剪 算法 CohenSutherland 实现