计算机图形学11:二维观察之多边形的裁剪

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 计算机图形学11:二维观察之多边形的裁剪,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

在这里插入图片描述

作者:非妃是公主
专栏:《计算机图形学》
博客地址https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
在这里插入图片描述

专栏推荐

专栏名称 专栏地址
软件工程 专栏——软件工程
计算机图形学 专栏——计算机图形学
操作系统 专栏——操作系统
软件测试 专栏——软件测试
机器学习 专栏——机器学习
数据库 专栏——数据库
算法 专栏——算法

专栏系列文章

文章名称 文章地址
直线生成算法(DDA算法) 计算机图形学01——DDA算法
中点BH算法绘制直线 计算机图形学02——中点BH算法
改进的中点BH算法 计算机图形学03——改进的中点BH算法
中点Bresenham画椭圆 计算机图形学04——中点BH绘制椭圆
中点BH算法绘制任意斜率直线 计算机图形学05——中点BH算法绘制任意斜率的直线
中点Bresenham画圆 计算机图形学06——中点BH算法画圆
有效边表法的多边形扫描转换 计算机图形学07——有效边表法绘制填充多边形
中点BH算法绘制抛物线

100

x

=

y

2

100x = y^2

100x=y2

计算机图形学08——中点BH绘制抛物线
二维观察之点的裁剪计算机图形学09——二维观察之点裁剪
二维观察之线的裁剪计算机图形学10——二维观察之线裁剪
二维观察之多边形的裁剪计算机图形学11——二维观察之多边形裁剪
二维图形的几何变换计算机图形学12——二维图形几何变换
三维图形的几何变换计算机图形学13——三维图形几何变换
三维图形的投影变换计算机图形学14——三维图形投影变换

计算机图形学(英语:computer graphics,缩写为CG)是研究计算机在硬件和软件的帮助下创建计算机图形的科学学科,是计算机科学的一个分支领域,主要关注数字合成与操作视觉的图形内容。虽然这个词通常被认为是指三维图形,事实上同时包括了二维图形以及影像处理。


一、多边形的裁剪算法原理

1. 多边形裁剪的目标

在这里插入图片描述

裁剪前:

在这里插入图片描述

正确裁剪后:

在这里插入图片描述


2. Sutherland-Hodgeman多边形裁剪

逐边裁剪算法基本思想:每次用窗口的一条边对多边形进行裁剪。
算法实施策略:

  • 为窗口各边界裁剪的多边形存储输入与输出顶点表。在窗口的一条裁剪边界处理完所有顶点后,其输出顶点表将用窗口的下一条边界继续裁剪。
  • 窗口的一条边以及延长线构成的裁剪线把平面分为两个区域,包含有窗口区域的一个域称为可见侧;不包含窗口区域的域为不可见侧。

在这里插入图片描述

在这里插入图片描述


二、代码实现

/// <summary>
/// 计算交点——X方向上的直线(垂直的直线)
/// </summary>
/// <param name="p1">第一个端点</param>
/// <param name="p2">第二个端点</param>
/// <param name="wxLorR">wxl或者wyr,分别求对应边的交点</param>
/// <returns>交点</returns>
VERTEX calIntersectionPointX(VERTEX p1, VERTEX p2, int wxLorR) {
	double k = (double)(wxLorR - p2.x) / (p1.x - p2.x);
	VERTEX res;
	res.x = wxLorR;
	res.y = k * p1.y + (1 - k) * p2.y;
	return res;
}

/// <summary>
/// 计算交点——Y方向上的直线(水平的直线)
/// </summary>
/// <param name="p1">第一个端点</param>
/// <param name="p2">第二个端点</param>
/// <param name="wyBorT">wxb或者wyt,分别求对应边的交点</param>
/// <returns>交点</returns>
VERTEX calIntersectionPointY(VERTEX p1, VERTEX p2, int wyBorT) {
	double k = (double)(wyBorT - p2.y) / (p1.y - p2.y);
	VERTEX res;
	res.y = wyBorT;
	res.x = k * p1.x + (1 - k) * p2.x;	
	return res;
}

/// <summary>
/// 多边形裁剪
/// </summary>
/// <param name="polygon">多边形顶点的数组</param>
/// <param name="wxl">窗口的左边缘</param>
/// <param name="wxr">窗口的右边缘</param>
/// <param name="wyb">窗口的下边缘</param>
/// <param name="wyt">窗口的上边缘</param>
/// <returns>裁剪后的多边形顶点</returns>
vector<VERTEX> cropPolygon(vector<VERTEX> polygon, int wxl, int wxr, int wyb, int wyt) {
	vector<VERTEX> res;
	// 对边 wxl 进行裁剪
	for (int i = 0; i < polygon.size(); i++) {
		VERTEX p1 = polygon[i];
		VERTEX p2 = polygon[(i + 1) % polygon.size()];
		
		if (p1.x < wxl && p2.x >= wxl) {		// 不可见侧到可见侧
			VERTEX intersectionPoint = calIntersectionPointX(p1, p2, wxl);
			res.push_back(intersectionPoint);
			res.push_back(p2);
		}		
		else if (p1.x >= wxl && p2.x >= wxl) {	// 可见侧到可见侧
			res.push_back(p2);
		}
		else if (p1.x >= wxl && p2.x < wxl) {	// 可见侧到不可见侧
			VERTEX intersectionPoint = calIntersectionPointX(p1, p2, wxl);
			res.push_back(intersectionPoint);
		}
		else if (p1.x < wxl && p2.x < wxl) {	// 不可见侧到不可见侧
			continue;
		}
	}

	polygon = res; // 更新顶点
	res.clear();
	// 对边 wxr 进行裁剪
	for (int i = 0; i < polygon.size(); i++) {
		VERTEX p1 = polygon[i];
		VERTEX p2 = polygon[(i + 1) % polygon.size()];

		if (p1.x > wxr && p2.x <= wxr) {		// 不可见侧到可见侧
			VERTEX intersectionPoint = calIntersectionPointX(p1, p2, wxr);
			res.push_back(intersectionPoint);
			res.push_back(p2);
		}
		else if (p1.x <= wxr && p2.x <= wxr) {	// 可见侧到可见侧
			res.push_back(p2);
		}
		else if (p1.x <= wxr && p2.x > wxr) {	// 可见侧到不可见侧
			VERTEX intersectionPoint = calIntersectionPointX(p1, p2, wxr);
			res.push_back(intersectionPoint);
		}
		else if (p1.x > wxr && p2.x > wxr) {	// 不可见侧到不可见侧
			continue;
		}
	}

	polygon = res; // 更新顶点
	res.clear();
	// 对边 wyb 进行裁剪
	for (int i = 0; i < polygon.size(); i++) {
		VERTEX p1 = polygon[i];
		VERTEX p2 = polygon[(i + 1) % polygon.size()];

		if (p1.y < wyb && p2.y >= wyb) {		// 不可见侧到可见侧
			VERTEX intersectionPoint = calIntersectionPointY(p1, p2, wyb);
			res.push_back(intersectionPoint);
			res.push_back(p2);
		}
		else if (p1.y >= wyb && p2.y >= wyb) {	// 可见侧到可见侧
			res.push_back(p2);
		}
		else if (p1.y >= wyb && p2.y < wyb) {	// 可见侧到不可见侧
			VERTEX intersectionPoint = calIntersectionPointY(p1, p2, wyb);
			res.push_back(intersectionPoint);
		}
		else if (p1.y < wyb && p2.y > wyb) {	// 不可见侧到不可见侧
			continue;
		}
	}

	polygon = res; // 更新顶点
	res.clear();
	// 对边 wyt 进行裁剪
	for (int i = 0; i < polygon.size(); i++) {
		VERTEX p1 = polygon[i];
		VERTEX p2 = polygon[(i + 1) % polygon.size()];

		if (p1.y > wyt && p2.y <= wyt) {		// 不可见侧到可见侧
			VERTEX intersectionPoint = calIntersectionPointY(p1, p2, wyt);
			res.push_back(intersectionPoint);
			res.push_back(p2);
		}
		else if (p1.y <= wyt && p2.y <= wyt) {	// 可见侧到可见侧
			res.push_back(p2);
		}
		else if (p1.y <= wyt && p2.y > wyt) {	// 可见侧到不可见侧
			VERTEX intersectionPoint = calIntersectionPointY(p1, p2, wyt);
			res.push_back(intersectionPoint);
		}
		else if (p1.y > wyt && p2.y > wyt) {	// 不可见侧到不可见侧
			continue;
		}
	}

	// 返回最终的 vector<Polygon>
	return res;
}

三、效果展示

在这里插入图片描述

测试代码如下:

// 显示图形
void Display(void) {
	glClear(GL_COLOR_BUFFER_BIT);		//用当前背景色填充窗口
	glColor3f(0.0f, 0.0f, 0.0f);
	
	// 此处需增加调用基本图形生成函数
	Bhline(20, 30, 200, 30);
	Bhline(200, 30, 200, 200);
	Bhline(200, 200, 20, 200);
	Bhline(20, 200, 20, 30);
	
	ScanTransferX(_polygon, RGB(255, 0, 0));

	glFlush();
}

// 第2个窗口中的图形绘制
void Displayw(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.0f, 0.0f, 0.0f);
	
	// 此处进行裁剪
	Bhline(20, 30, 200, 30);
	Bhline(200, 30, 200, 200);
	Bhline(200, 200, 20, 200);
	Bhline(20, 200, 20, 30);

	vector<VERTEX> polygon = cropPolygon(_polygon, 20, 200, 30, 200);
	ScanTransferX(polygon, RGB(255, 0, 0));

	glFlush();
}

主函数等其它框架部分与前面(点、线裁剪)相同,可通过开头链接进行跳转查看,在此不再冗余贴代码片。


the end……

二维观察之多边形的裁剪到这里就要结束啦~~到此既是缘分,欢迎您的点赞评论收藏关注我,不迷路,我们下期再见!!

😘😘😘 我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
💞💞💞 内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
👋👋👋 我们相互交流,共同进步!

:本文由非妃是公主发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/128508946

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/130473.html

(1)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!