实验六 二维裁剪算法Cohen_Sutherland的实现 一、实验目的:
理解并掌握直线裁剪算法。使用Visual C++实现二维直线的裁剪的Cohen_Sutherland算法。对窗口进行编码,并实现相应的裁剪函数。
二、实验内容及要求:
1、 2、 3、
要求用消息映射的方式,绘制出一个裁剪窗口,大小为200×150象素;
按照例程的步骤画出3条典型线段,分别对应于完全在裁剪窗口内、完全在裁剪窗口外、穿过裁剪窗口三种情况,并按照本实验例程的方法用颜色分别表示出裁剪后的情况; 按要求撰写实验报告,写出实验心得,并在实验报告中附上程序的核心算法代码。
三、实验设备:
微机,Visual C++6.0
四、实验内容及步骤:
1、 打开VC,新建一个MFC Appwizard项目,选择创建单文档工程(SDI工程)。假设工程名为Clip。
如图1和图2所示。
图1
图2
2、 在图2的界面上点击Finish,完成工程的创建。
3、 在视图类ClipView中定义变量CRect rect; 用于记录裁剪窗口的位置; 4、 在ClipView.cpp文件中定义四个宏,记录裁剪窗口的上下左右四个位置: #define LEFT 100 #define RIGHT 300 #define TOP 150
#define BOTTOM 310
5、 在视图类的构造函数中为rect赋值; CClipView::CClipView() {
// TODO: add construction code here
rect = CRect(LEFT, TOP, RIGHT, BOTTOM); }
6、 在视图类(类CFillView中)的OnDraw()函数中绘制裁剪矩形,OnDraw函数的代码如下:
void CClipView::OnDraw(CDC* pDC) {
CClipDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);
// TODO: add draw code for native data here pDC->Rectangle(&rect); }
7、 在视图类(类CFillView中)添加成员函数int Encode(int x, int y),该函数用于对线段的两个顶点
进行Cohen_Sutherland编码。函数体如下: int CClipView::Encode(int x, int y) {
int nCode = 0; if(x < LEFT) nCode = nCode | 0x01; if(x > RIGHT) nCode = nCode | 0x02; if(y > BOTTOM)
nCode = nCode | 0x04; if(y < TOP) nCode = nCode | 0x08; return nCode; }
8、 在视图类中添加Cohen_Sutherland裁剪算法的实现函数,函数体如下:
void CClipView::CLIP_Line_Cohen_Sutherland(CPoint &P1, CPoint &P2) {
int nCode1 = 0; int nCode2 = 0;
nCode1 = Encode(P1.x, P1.y); nCode2 = Encode(P2.x, P2.y); if(nCode1 ==0 && nCode2 ==0) return; //直线在裁剪窗口内,直接返回 else if((nCode1 & nCode2) != 0) { P1 = CPoint(0,0); P2 = CPoint(0,0); return; //直线在裁剪窗口外,将直线的两个端点赋为0,返回 }
double wx = P2.x - P1.x; double wy = P2.y - P1.y; double dX = 0; double dY = 0;
while(nCode1 != 0 || nCode2 != 0) { int nCode = nCode1; if(nCode1 == 0) nCode = nCode2; if((nCode & 0x01) == 0x01) //说明左边与边界有交点 { dX = LEFT; dY = P1.y + wy * (LEFT-P1.x)/wx; } else if((nCode & 0x02) == 0x02) //说明右边与边界有交点 { dX = RIGHT; dY = P1.y + wy * (RIGHT-P1.x)/wx; } else if((nCode & 0x04) == 0x04) //说明下边与边界有交点 { dX = (BOTTOM-P1.y) * wx / wy + P1.x; dY = BOTTOM;
} }
}
else if((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裁剪函数。代码如下: void CClipView::OnClipLineCohenSutherland() {
// TODO: Add your command handler code here CPoint P1 = CPoint(80,400); CPoint P2 = CPoint(200,80); CDC *pDC = this->GetDC();
CPen newPen(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中
CPen clipPen(PS_SOLID,2,RGB(0,0,255)); pOldPen=pDC->SelectObject(&clipPen); pDC->MoveTo(P1); pDC->LineTo(P2);
pDC->SelectObject(pOldPen); this->ReleaseDC(pDC); }
二维的Cohen_Sutherland算法实现完毕。
//用窗口裁剪P1P2直线,裁剪后的顶点保存在
//用蓝色2个线宽绘制窗口内裁剪之后的线段
五、核心代码:
这里将自己编写的上机程序中的主要代码拷贝粘贴过来;
定义:
#define LEFT 100 #define RIGHT 300 #define TOP 150
#define BOTTOM 310
OnDraw部分:
void CClipView::OnDraw(CDC* pDC) { CClipDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->Rectangle(&rect); OnClipLineCohenSutherland(); // TODO: add draw code for native data here }
int CClipView::Encode(int x, int y) { int nCode = 0; if(x < LEFT) nCode = nCode | 0x01; if(x > RIGHT)