1、实验三 图形裁剪算法 1. 实验目的: 理解 区域编码 (Region Code, RC) 设计 Cohen-Sutherland 直线裁剪算法 编程实现 Cohen-Sutherland 直线裁剪算法 2. 实验描述: 设置裁剪窗口坐标为: wxl=250;wxr=850;wyb=250;wyt=450;裁剪前如下图所示: 裁剪后结果为: 3.算法设计: Cohen-Sutherland 直线裁剪算法: 假设裁剪窗口是标准矩形,由上( y=wyt)、下( y=wyb)、左( x=wxl)、右( x=wxr)四条边组成,如下图 所示。 延长窗口四条边形成 9 个区域 。根据 被裁剪 直线的任一
2、端点 P(x, y)所处的窗口区域位置,可以赋予一组 4 位二进制区域码 C4C3C2C1。 为了保证窗口内直线端点的编码为零,编码规则定义如下: 第一位:若端点位于窗口之左侧,即 xwxr,则 C2=1,否则 C2=0。 第三位:若端点位于窗口之下侧,即 ywyt,则 C4=1,否则 C4=0。 裁剪步骤: 1. 若直线的两个端点的区域编码都为零,即 RC1|RC2=0(二者按位相或的结果为零,即 RC1=0 且 RC2=0),说明直线两端点都在窗口内,应“简取”之。 2. 若直线的两个端点的区域编码都不为零,即 RC1/用户绘制的直线 int wxl,wxr,wyb,wyt;/左上与右下
3、CDC Picture;/内存 (预存 )DC,防止屏幕闪烁 char m_i; /第一个点还是第二个点 BOOL m_Attatch; BOOL m_Draw; unsigned int RC,RC0,RC1; . 2) /TestView.cpp #define ROUND(a) int(a+0.5) #define LEFT 1 #define RIGHT 2 #define BOTTOM 4 #define TOP 8 CTestView:CTestView() /窗口位置坐标 wxl=250;wxr=850;wyb=250;wyt=450; m_Attatch=FALSE; m_i=
4、0; m_Draw=FALSE; RC0=0;RC1=0; void CTestView:OnDraw(CDC* pDC) CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); / TODO: add draw code for native data here CRect Rect; GetClientRect(/获得客户区的大小 CBitmap Bitmap,*pBitmap; Bitmap.LoadBitmap(IDB_BITMAP1); CDC MemDC; MemDC.CreateCompatibleDC(GetDC(); pBitm
5、ap=MemDC.SelectObject( MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(), MemDC.TextOut(wxl+wxr)/2,wyb-20,“窗口 “);/窗口标题 /绘制窗口和直线 CPen Pen3,*pOldPen3;/定义 3 个像素宽度的画笔 Pen3.CreatePen(PS_SOLID,3,RGB(0,0,0); pOldPen3=MemDC.SelectObject( MemDC.MoveTo(wxl,wyt);MemDC.LineTo(wxr,wyt); MemDC.LineTo(wxr,wyb);MemDC.Lin
6、eTo(wxl,wyb); MemDC.LineTo(wxl,wyt);MemDC.SelectObject(pOldPen3); Pen3.DeleteObject(); CPen Pen1,*pOldPen1;/定义 1 个像素宽度的画笔 Pen1.CreatePen(PS_SOLID,1,RGB(0,255,255); pOldPen1=MemDC.SelectObject( if(m_i=1) MemDC.MoveTo(ROUND(Pointx0),ROUND(Pointy0); MemDC.LineTo(ROUND(Pointx1),ROUND(Pointy1); MemDC.Sel
7、ectObject(pOldPen1); Pen1.DeleteObject(); CDC *dc=GetDC(); dc-BitBlt(0,0,Rect.Width(),Rect.Height(), MemDC.SelectObject(pBitmap); void CTestView:OnMENUClip()/裁剪菜 单函数 Cohen(); Invalidate(FALSE); unsigned int CTestView:EnCode(double LinePx,double LinePy)/端点编码函数 /顺序左右下上 RC=0; if(LinePxwxr) RC=RC | RIGH
8、T; if(LinePywyt) RC=RC | TOP; return RC; void CTestView:Cohen()/Cohen Sutherland 算法 BOOL Change; double x,y; RC0=EnCode(Pointx0,Pointy0); RC1=EnCode(Pointx1,Pointy1); while(TRUE) Change=FALSE; if(0 = (RC0|RC1) /简取之 return; else if(0!=(RC0 else if(0=RC0)/如果 P0 点在窗口内,交换 P0 和 P1,保证 p0 点在窗口外 /交换点的坐标值 do
9、uble TPointx,TPointy; TPointx=Pointx0;TPointy=Pointy0; Pointx0=Pointx1;Pointy0=Pointy1; Pointx1=TPointx;Pointy1=TPointy; /交换点的编码值 unsigned int TRC; TRC=RC0;RC0=RC1;RC1=TRC; /按左、右、下、上的顺序裁剪 if(RC0 /求交点 y y=Pointy0+(Pointy1-Pointy0)*(x-Pointx0)/(Pointx1-Pointx0); Pointx0=x;Pointy0=y; Change=TRUE; RC0=E
10、nCode(Pointx0,Pointy0);RC1=EnCode(Pointx1,Pointy1); if(RC0 /求交点 y y=Pointy0+(Pointy1-Pointy0)*(x-Pointx0)/(Pointx1-Pointx0); Pointx0=x;Pointy0=y; Change=TRUE; RC0=EnCode(Pointx0,Pointy0);RC1=EnCode(Pointx1,Pointy1); if(RC0 /求交点 x x=Pointx0+(Pointx1-Pointx0)*(y-Pointy0)/(Pointy1-Pointy0); Pointx0=x;P
11、ointy0=y; Change=TRUE; RC0=EnCode(Pointx0,Pointy0);RC1=EnCode(Pointx1,Pointy1); if(RC0 /求交点 x x=Pointx0+(Pointx1-Pointx0)*(y-Pointy0)/(Pointy1-Pointy0); Pointx0=x;Pointy0=y; Change=TRUE; RC0=EnCode(Pointx0,Pointy0);RC1=EnCode(Pointx1,Pointy1); if(FALSE=Change) return; void CTestView:OnMENUDrawLine()
12、/绘制直线菜单函数 / TODO: Add your command handler code here if(FALSE=m_Attatch) Picture.CreateCompatibleDC(GetDC(); CBitmap *Bitmap,*pBitmap; Bitmap=new CBitmap; Bitmap-LoadBitmap(IDB_BITMAP1); pBitmap=Picture.SelectObject(Bitmap); m_Attatch=TRUE; m_Draw=TRUE; m_i=0; Invalidate(FALSE); AfxGetMainWnd()-SetW
13、indowText(“Cohen-Sutherland 直线裁剪算法 “);/显示标题 MessageBox(“请使用鼠标在屏幕上绘制直线,然后点击裁剪按钮进行裁剪 “,“提示“,MB_OKCANCEL); void CTestView:OnLButtonDown(UINT nFlags, CPoint point) /单击鼠标左键函数 / TODO: Add your message handler code here and/or call default if(TRUE=m_Draw) if(m_i2) Pointxm_i=point.x;Pointym_i=point.y; m_i+;
14、 CView:OnLButtonDown(nFlags, point); void CTestView:OnMouseMove(UINT nFlags, CPoint point) /鼠标移动函数 / TODO: Add your message handler code here and/or call default if(TRUE=m_Draw) if(m_i2) Pointxm_i=point.x;Pointym_i=point.y; Invalidate(FALSE); CView:OnMouseMove(nFlags, point); 5.运行结果 : (屏幕截图 ) 序号 检查项目 分值 提交时间 得分 1 算法 设计( 40%) 0-40 2 算法的程序实现 ( 40%) 0-40 3 运行结果( 10%) 0-10 4 实验报告规范性 (10%) 0-10 成 绩