栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

VS2010 MFC c++实现线段剪裁(LiangBarsky和CohenSutherland)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

VS2010 MFC c++实现线段剪裁(LiangBarsky和CohenSutherland)

       注意的几点:

1 链表做.缩放窗口不消失是因为OnDraw函数中遍历链表重绘,这也是所有绘制都放在OnDraw函数中的原因.

2 引用变量的使用.

3.实现效果如下(刚学的,下了个licecap.可制作gif),需要缩放窗口才能剪裁(其实是在刷新窗口):

先附上代码,有时间会解析(只要不出错,大概率不会解析):

1 View头文件:

//文件名是LineClipping
//头文件中添加的代码
public:
	int menu;
	bool flag;//判断单击鼠标画出的是第一个端点还是第二个端点
	struct PL* SavePoint;//建立存储结构体的链表
	struct PL* p;//辅助建立存储结构体的链表
	bool draw;//判断画出的线段是否需要剪裁

	//创建矩形裁剪
	double xmin, xmax;//左上角
	double ymin, ymax;//右下角

	//Cohen剪裁用到的函数
	char CLineClippingView::EnCode(float px, float py);//确定点的编码
	bool CLineClippingView::CohenSutherland(CPoint &p1, CPoint &p2); 

	//LiangBarsky剪裁用到的函数
	//double CLineClippingView::Max(double a, double b);
	//double CLineClippingView::Min(double a, double b);
	void CLineClippingView::exchange(CPoint &p1, CPoint &p2);//交换
	bool CLineClippingView::LiangBarsky(CPoint &p1, CPoint &p2);
	bool CLineClippingView::LbUnEqual(CPoint &p1, CPoint &p2);//deltax,deltay都不等于零

2 源文件中的代码:

2.1 构造函数:

//构造函数中的初始化
CLineClippingView::CLineClippingView()
{
	// TODO: 在此处添加构造代码
	flag = true;
	menu = 0;
	draw = false;
	
	xmin = 100;
	xmax = 500;
	ymin = 100;
	ymax= 500;

	p = NULL;
	SavePoint = (struct PL*)malloc(sizeof(PL));
	SavePoint->next = NULL;

2.2 OnDraw函数

void CLineClippingView::OnDraw(CDC* pDC)
{
	CLineClippingDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码

	//绘制矩形窗口
	pDC->Rectangle(xmin, ymin, xmax, ymax);
	
	struct PL* traverse;
	traverse = SavePoint->next;
	while(traverse)
	{
		//点击完菜单后需要放缩一下窗口,刷新一下,才能显示剪裁后的结果

		//CohenSutherland
		if(menu == 2)
		{
			if(CohenSutherland(traverse->pointa, traverse->pointb))
			{
				pDC->MoveTo(traverse->pointa);
				pDC->LineTo (traverse->pointb);
			}
		}
		//LiangBarsky
		if(menu == 3)
		{
			if(LiangBarsky(traverse->pointa, traverse->pointb))
			{
				pDC->MoveTo(traverse->pointa);
				pDC->LineTo (traverse->pointb);
			}
		}
			
		if(menu == 0)
		{
			pDC->MoveTo(traverse->pointa);
			pDC->LineTo (traverse->pointb);
		}
		
		traverse = traverse->next;
	}
	free(traverse);
}

2.3 Cohen-Sutherland算法

//赋值编码函数
char CLineClippingView::EnCode(float px, float py)
{
	unsigned char code = 0;
	if(px < xmin) code = code | LEFT_EDGE;
	else if(px > xmax) code = code | RIGHT_EDGE;
	if(py > ymax) code = code | BOTTOM_EDGE;
	else if(py < ymin) code = code | TOP_EDGE;

	return code;
}
//Cohen-Sutherland
bool CLineClippingView::CohenSutherland(CPoint &p1, CPoint &p2)//注意用的是引用变量
{
	int x, y;
	bool finish, draw;
	int code1, code2, code;

	finish = false;
	draw = false;

	while(!finish)
	{
		code1 = EnCode(p1.x, p1.y);
		code2 = EnCode(p2.x, p2.y);
 
		//if判断完全可见,else判断完全不可见
		if((code1 == 0) && (code2 == 0))
		{
			finish = true; 
			draw = true;
		}
		else if(code1 & code2)
		{
			finish = true; 
			draw = false;
		}

		//分段
		else 
		{
			//code是不可见点的编码
			if(code1 != 0)
				code = code1;
			else 
				code = code2;

			//求交处理
			if ((LEFT_EDGE & code)!=0)
			{
				x = xmin;
				y = p1.y + (p2.y - p1.y)*(xmin - p1.x) / (p2.x - p1.x);
			}
			else if ((RIGHT_EDGE & code)!=0)
			{
				x = xmax;
				y = p1.y + (p2.y - p1.y)*(xmax - p1.x) / (p2.x - p1.x);
			}
			else if ((BOTTOM_EDGE & code)!=0)
			{
				y = ymax;
				x = p1.x + (p2.x - p1.x)*(ymax - p1.y) / (p2.y - p1.y);
			}
			else if ((TOP_EDGE & code)!=0)
			{
				y = ymin;
				x = p1.x + (p2.x - p1.x)*(ymin - p1.y) / (p2.y - p1.y);
			}

			if (code == code1)
			{
				p1.x = x; p1.y = y; code1 = EnCode(p1.x, p1.y);
			}
			else
			{
				p2.x = x; p2.y = y; code2 = EnCode(p2.x, p2.y);
			}
		}
	}
	
	return draw;

	CDC *pDC = GetDC();
	OnDraw(pDC);
	ReleaseDC(pDC);
}

2.4Liang-Brasky

//交换
void CLineClippingView::exchange(CPoint &p1, CPoint &p2)
{
	CPoint p;
	p = p1;
	p1 = p2;
	p2 = p;
}
//deltax, deltay都不为零的情况
bool CLineClippingView::LbUnEqual(CPoint &p1, CPoint &p2)
{
	double deltax, deltay;
	double tmax, tmin;

	deltax = p2.x - p1.x;
	deltay = p2.y - p1.y;

	if((deltax>0) && (deltay>0))
	{
		tmax = min(1, min((xmax-p1.x)/deltax, (ymax-p1.y)/deltay));
		tmin = max(0, max((xmin-p1.x)/deltax, (ymin-p1.y)/deltay));
	}
	else if((deltax>0) && (deltay<0))
	{
		tmax = min(1, min((xmax-p1.x)/deltax, (ymin-p1.y)/deltay));
		tmin = max(0, max((xmin-p1.x)/deltax, (ymax-p1.y)/deltay));
	}

	if(tmin < tmax)
	{
		p1.x = deltax * tmin + p1.x;
		p1.y = deltay * tmin + p1.y;
		p2.x = deltax * tmax + p1.x;
		p2.y = deltay * tmax + p1.y;
		draw = true;
	}
	else
	{
		draw = false;
	}
	return(draw);
}
bool CLineClippingView::LiangBarsky(CPoint &p1, CPoint &p2)
{
	double deltax;
	double deltay;

	draw = false;
	deltax = p2.x - p1.x;
	deltay = p2.y - p1.y;

	if((deltax>0) && (deltay>0))
	{
		return(LbUnEqual(p1, p2));
	}
	else if((deltax<0) && (deltay<0))
	{
		exchange(p1, p2);
		return(LbUnEqual(p1, p2));
	}
	else if((deltax>0) && (deltay<0))
	{
		return(LbUnEqual(p1, p2));
	}

	else if((deltax<0) && (deltay>0))
	{
		exchange(p1, p2);
		return(LbUnEqual(p1, p2));
	}

	//deltax = 0
	else if(deltax == 0)
	{
		if((xmin > p1.x) || (xmax < p1.x))
			draw = false;
		else
		{
			p2.y = max(ymin, max(p1.y, p2.y));
			p1.y = min(ymax, min(p1.y, p2.y));

			if(p1.y < p2.y)
				draw = true;
			else
				draw = false;
		}
		
	}
	//deltay = 0
	else if(deltay == 0)
	{
		if((ymin > p1.y) || (ymax < p1.y))
			draw = false;
		else
		{
			p2.x = max(xmin, max(p1.x, p2.x));
			p1.x = min(xmax, min(p1.x, p2.x));

			if(p1.x < p2.x)
				draw = true;
			else
				draw = false;
		}
	}
}

2.5响应函数.2.5节代码看不懂的话看前两篇.

void CLineClippingView::OnWindow()
{
	// TODO: 在此添加命令处理程序代码
	menu = 1;
	MessageBox(L"鼠标左键单击两次建立矩形窗口");
}


void CLineClippingView::OnCohen()
{
	// TODO: 在此添加命令处理程序代码
	menu = 2;
	MessageBox(L"进行Cohen-Sutherland裁剪");
}


void CLineClippingView::OnLiang()
{
	// TODO: 在此添加命令处理程序代码
	menu = 3;
	MessageBox(L"进行Liang-Barsky裁剪");
}


void CLineClippingView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(flag)
	{
		p = (struct PL*)malloc(sizeof(PL));
		p->pointa = point;
	}
	else
	{
		p->pointb = point;
		p->next = SavePoint->next;
		SavePoint->next = p;
	}
	flag = !flag;

	CDC *pDC = GetDC();
	OnDraw(pDC);
	ReleaseDC(pDC);

	CView::OnLButtonDown(nFlags, point);
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/833078.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号