计算机图形学 实验6 直线的裁剪—Cohen Sutherland裁剪算法(MFC中)

实验目的:

  1. 理解裁剪的作用
  2. 掌握直线裁剪的算法
    实验内容:
    一、编写程序实现Cohen Sutherland裁剪算法
    算法原理:
    首先判断直线段是否全部在窗口内,是,则保留;不是,则再判断是否完全在窗口之外,如是,则舍弃。
    如果这两种情况都不属于,则将此直线段从交点处分割,对分割后的线段再进行如前判断。
    直至所有直线段和由直线段分割出来的子线段都已经确定了是保留还是舍弃为止。
    算法流程:
  3. 对直线的两个端点进行编码
    编码方式
    注意:l为left,r为right,b为bottom,t为top
    (1)若x小于wxl,D0=1,否则D0=0 C1 | 0001 按位或
    (2)若x大于wxr,D1=1,否则D1=0 C1 | 0010
    (3)若y小于wyb,D2=1,否则D2=0 C1 | 0100
    (4)若y大于wyt,D3=1,否则D3=0 C1 | 1000
    在这里插入图片描述
  4. 进行区域测试
    如果code1和code2均为0,code1按位或code2,则说明P1和P2均在窗口内,那么线段全部位于窗口内部,应取之。
    如果code1和code2经过按位与运算后的结果code1&code2不等于0,说明P1和P2同时在窗口的上方、下方、左方或右方,那么线段全部位于窗口的外部,应弃之。
  5. 当2不满足时,确保p1在窗口外部:若p1在窗口内,则交换p1和p2的坐标值和编码。
  6. 求出直线段与窗口边界的交点,并用该交点的坐标值替换p1的坐标值。也即在交点s处把线段一分为二。考虑到p1是窗口外的一点,因此可以去掉p1s。转(2)。
  7. 画出当前的直线段p1p2。
  8. 算法结束。

在这里插入图片描述

实验作业:

  1. 假设裁剪窗口参数为wxl=250;wxr=850;wyb=250;wyt=450;其中,wxl为左侧裁剪边,wxr为右侧裁剪边,wyb为下侧裁剪边,wyt为上裁剪边。
    编写unsigned int EnCode(double,double);函数,实现对直线端点的编码。
    提示:编码的代码实现区域编码思路:如,端点在裁剪窗口左侧,其编码最后一位为1,可以按位或0001,将编码最后一位至1.
    代码:
unsigned int CCohenSutherlandView::EnCode(CPoint point)
{
	
	int C1=0;
	if (point.x<wxl)
		C1=C1|D0;
	if (point.x>wxr)
		C1=C1|D1;
	if (point.y<wyb)
		C1=C1|D2;
	if (point.y>wyt)
		C1=C1|D3;
	return C1;
}
  1. 写出裁剪函数CohenSutherland(),并在OnDraw()里面绘制出裁剪窗口,绘制出裁剪后的直线,测试裁剪结果是否正确,给出至少三种情况的直线的裁剪,第一种情况,全部保留,第二种情况,完全去除,第三种情况,直线需要剪切。
    代码:
在CohenSutherlandView.h中:

public:
	int wxl,wxr,wyb,wyt;
	unsigned int CCohenSutherlandView::EnCode(CPoint point);
	void CCohenSutherlandView::CohenSutherland(CPoint p1,CPoint p2,CDC *pdc);
	void CCohenSutherlandView::DDA(CPoint p1,CPoint p2,CDC *pdc,COLORREF color);
// 重写
在CohenSutherlandView.cpp中:

#define D0 1 //0001
#define D1 2 //0010
#define D2 4 //0100
#define D3 8 //1000

void CCohenSutherlandView::OnDraw(CDC* pDC)
{
	CCohenSutherlandDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	 wxl=250,wxr=850,wyb=250,wyt=450;	
	 //CPoint X(250,250);//左上	
	// CPoint Y(850,450);//右下
	 pDC->Rectangle(wxl,wyb,wxr,wyt);
	 CPoint A(500,400),B(800,420);//全部保留
	 CohenSutherland(A,B,pDC);
	  CPoint C(1000,500),D(900,500);//完全去除
	 CohenSutherland(C,D,pDC);
	  CPoint E(350,300),F(1200,300);//直线需要剪切
	 CohenSutherland(E,F,pDC);
	// pDC->Polyline()
	// TODO: 在此处为本机数据添加绘制代码
}
void CCohenSutherlandView::CohenSutherland(CPoint p1,CPoint p2,CDC *pdc)
{
	int code1,code2,code;
	CPoint p;
	code1=EnCode(p1);
	code2=EnCode(p2);
	while (code1!=0||code2!=0)
	{
		if (code1&&code2!=0)//全部位于外部
			return;
		if(code1!=0)code=code1;//部分在外部
		else
			code=code2;
		if ((D0&code)!=0)//Left 
		{
			p.x=wxl;
			p.y=p1.y+(p.x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x);
		}
		else if ((D1&code)!=0)//Right
		{
			p.x=wxr;
			p.y=p1.y+(p.x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x);
		}
		else if ((D2&code)!=0)//Bottom
		{
			p.y=wyb;
			p.x=p1.x+(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y);
		}
		else if ((D3&code)!=0)//Top
		{
			p.y=wyt;
			p.x=p1.x+(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y);
		}
		if(code==code1)//p1在外部
		{
			p1.x=p.x;p1.y=p.y;
			code1=EnCode(p);
		}
		else
		{
			p2.x=p.x;p2.y=p.y;
			code2=EnCode(p);
		}
	}
	CPen pen;
	pen.CreatePen(PS_SOLID,5,RGB(0,255,255));
	pdc->SelectObject(&pen);
	pdc->MoveTo(p1);
	pdc->LineTo(p2);	
	
}

截图:
在这里插入图片描述

  • 18
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值