计算机图形学-二维图形的裁剪

计算机图形学-二维图形的裁剪,第1张

计算机图形学-二维图形的裁剪 Cohen-Surtherland算法

新建一个文档命名为1124,文档类型为单文档。
创建CP2类

右键1124 classes,点击new class新建一个类CP2:


在CP2类中声明三个域:(double x;double y;UINT rc;)

找到cpp文件,在里面引用CP2这个类:(#include “P2.h”)


在CView类中新建两个CP2类型的变量p0、p1和四个成员变量(定义矩形的四个方向的边界):

(这四个边界变量用double、int都可以)


在构造函数中给这四个变量赋值。

CMy11122View::CMy11122View()
{
	// TODO: add construction code here
	wxl=-300,wyb=-100,wxr=300,wyt=100;
}

新建函数DrawClipWindow(CDC*pDC),用来画矩形。

void CMy11122View::DrawClipWindow(CDC*pDC)
{
	CRect rect(wxl,wyb,wxr,wyt);
	pDC->Rectangle(rect);
}

在OnDraw函数中调用画矩形函数

void CMy11122View::OnDraw(CDC* pDC)
{
	CMy11122Doc* pDoc = Getdocument();
	ASSERT_VALID(pDoc);
	DrawClipWindow(pDC);//绘制裁剪窗口
	// TODO: add draw code for native data here
}

增加鼠标点击函数:

  1. 新建成员变量flag(用来判断赋值给p0还是p1,以及画线)

  2. 在构造函数中将flag初始化为0

CMy11122View::CMy11122View()
{
	// TODO: add construction code here
	wxl=300,wyb=100,wxr=700,wyt=400;
	flag=0;
}


3. 双击WM_LBUTTONDOWN添加该函数,点击Add and Edit编辑函数。

4. 在函数中编写如下代码:

void CMy11122View::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CDC*pDC=GetDC();
	if(flag==0)
	{
		p0.x=point.x;
		p0.y=point.y;
		flag=1;
	}
	else
	{
		p1.x=point.x;
		p1.y=point.y;
	    pDC->MoveTo(p0.x,p0.y);
	    pDC->LineTo(p1.x,p1.y);
		flag=0;
	}
	CView::OnLButtonDown(nFlags, point);
}

创建编码函数:

#define LEFT 0x1    //代表:0001
#define RIGHT 0x2    //代表:0010
#define BOTTOM 0x4   //代表:0100
#define TOP 0x8   //代表:1000
 
void CMy1112View::EnCode(CP2 &pt)
{
	pt.rc=0;
	if(pt.xwxr)
	     pt.rc=pt.rc | RIGHT;
	if(pt.ywyt)
	     pt.rc=pt.rc | TOP;	
}

创建Cohen函数:

添加代码:(我用的方法是在函数开始时用白色画笔覆盖所画的线,再重画裁剪后得到的线)

void CMy11122View::OnCohen() 
{
	CDC*pDC=GetDC();
    CPen NewPen,*pOldPen;
    NewPen.CreatePen(PS_SOLID,1,RGB(255,255,255));
	pOldPen=pDC->SelectObject(&NewPen);
	pDC->MoveTo(p0.x,p0.y);
    pDC->LineTo(p1.x,p1.y);
    pDC->SelectObject(pOldPen);
	// TODO: Add your command handler code here
	CP2 p;//交点坐标
	EnCode(p0);//起点编码
	EnCode(p1);//终点编码
	while(p0.rc!=0 || p1.rc!=0)//处理至少一个顶点在窗口外
	{
		if((p0.rc & p1.rc)!=0)//简弃之
		{
			return;
		}
		if(0==p0.rc)//确保p0位于窗口之外
		{
			CP2 Temp;
			Temp=p0;
			p0=p1;
			p1=Temp;
		}
        UINT RC=p0.rc;
		double k=(p1.y-p0.y)/(p1.x-p0.x);//斜率
		if(RC & LEFT)//p0点位于窗口的左侧
		{
			p.x=wxl;//计算交点y坐标
			p.y=k*(p.x-p0.x)+p0.y;
		}
		else if(RC & RIGHT)//p0点位于窗口的右侧
		{
			p.x=wxr;//计算交点y坐标
			p.y=k*(p.x-p0.x)+p0.y;
		}
		else if(RC & BOTTOM)//p0点位于窗口的下侧
		{
			p.y=wyb;//计算交点x坐标
			p.x=(p.y-p0.y)/k+p0.x;
		}			
		else if(RC & TOP)//p0点位于窗口的上侧
		{
			p.y=wyt;//计算交点x坐标
			p.x=(p.y-p0.y)/k+p0.x;
		}
        EnCode(p);
		p0=p;
	}
	pDC->MoveTo(p0.x,p0.y);
	pDC->LineTo(p1.x,p1.y);
}

为Cohen添加菜单函数:

  1. 在此处双击:

  2. 双击“帮助”后的空白处

  3. 编辑菜单属性

  4. 在空白处右键建立类向导:


    点击Edit Code,将Cohen函数复制到OnCohen中来:

    运行,用鼠标任意点两点,画线

    点击裁剪:

    裁剪多条直线效果(此方法只能画一条线裁剪一次):

梁友栋算法

梁友栋裁剪算法:
把EnCode和Cohen函数中的裁剪部分算法换成LBLineClip函数即可。

void CMy11122View::OnCohen() 
{
	CDC*pDC=GetDC();
    CPen NewPen,*pOldPen;
    NewPen.CreatePen(PS_SOLID,1,RGB(255,255,255));
	pOldPen=pDC->SelectObject(&NewPen);
	pDC->MoveTo(p0.x,p0.y);
    pDC->LineTo(p1.x,p1.y);
    pDC->SelectObject(pOldPen);
	double tmax,tmin,dx,dy;
	dx=p1.x-p0.x;dy=p1.y-p0.y;tmax=0.0,tmin=1.0;
	if(ClipTest(-dx,p0.x-wxl,tmax,tmin)) //窗口边界的左、右、下、上顺序裁剪直线
	{
		if(ClipTest(dx,wxr-p0.x,tmax,tmin))
		{			
			if(ClipTest(-dy,p0.y-wyb,tmax,tmin))
			{
				if(ClipTest(dy,wyt-p0.y,tmax,tmin))
				{
					if(tmin<1.0)//判断直线终点
					{
						 p1.x=p0.x+tmin*dx;
                         p1.y=p0.y+tmin*dy;                       
					}
					if(tmax>0.0)//判断直线的起点
					{
						 
                         p0.x=p0.x+tmax*dx;
						 p0.y=p0.y+tmax*dy;                          
					}
				}
			}
		}
	}
	pDC->MoveTo(p0.x,p0.y);
	pDC->LineTo(p1.x,p1.y);
}
BOOL CMy11122View::ClipTest(double u,double v,double &tmax,double &tmin)//裁剪测试函数
{
	double t;
	BOOL ReturnValue=TRUE;
	if(u<0.0)//从裁剪窗口的外部到内部,计算起点处的tmax
	{
		t=v/u;
		if(t>tmin)
			ReturnValue=FALSE;
		else if(t>tmax)
			tmax=t;
	}
	else
	{
		if(u>0.0)//从裁剪窗口的内部到外部,计算终点处的tmin
		{
			t=v/u;
			if(t					
										


					

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5592994.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存