OpenGL研究3.0 多边形区域填充

DionysosLai([email protected])2014-06-22

所谓多边形区域填充。就是将多边形内部区域,所有已相同色块填充。注意:这里讨论的多边形是简单多边形(即不考虑诸如五角星这样的相交多边形)。简单多边形,分为凹多边形和凸多边形。

多边形区域填充有下面几种方法:

1.      逐点扫描方法:

原理:扫描多边形区域,逐点推断点是否在多边形内。

难点:在于怎样推断点是否在区域内;

经常使用怎样推断点是否在区域内方法:射线法、面积法。

面积法原理:取一个点。连接多边形各个点,依据三个点形成一个三角形原理,我们能够求得三角形面积。推断面积的大小,就能够推断该店是否在多边形内了。

射线法:这种方法。是我们这里要重点解说的一个方法。原理:取一个点。向左或者向右做一条射线过去,推断射线与多边形的交点。依据多边形交点熟练和本身多边形边情况,推断点是否在多边形内。

首先,射线从左向右,最左边点肯定在多边形区域为(我们这里假定射线方向水平向左)。那么与多边形相交第一个点,必定表明射线右部分在多变形内,与多边形相交第二个点。表明射线右部分在多边形外面。因此。通过推断射线与多变的交点奇偶性。推断点是否在多边形内。

这里。有几种特殊情况,例如以下图所看到的:

图a,射线与多变形顶点相交,顶点算一个;图b。射线与多边形顶点的交点。不被计算在内(注意图a和图b的差别->顶点纵坐标大小差别);图c和图d,射线与多边形一条边重合,这条边被忽略不计。

因此。我们能够设计例如以下:取点向左做一条射线,1. 对于水平边不做考虑;2. 对于多边形顶点与射线交点情况。假设其纵坐标是所属边较大顶点,则计数(參考图a),否则不计数(图b)。3.对于点在多边形上情况,可直接推断点在多边形内。

伪代码例如以下:

count ← 0;
以P为端点。作从右向左的射线L;
for 多边形的每条边s
 do if P在边s上
	  then return true;
	if s不是水平的
	  then if s的一个端点在L上
			 if 该端点是s两端点中纵坐标较大的端点
			   then count ← count+1
		   else if s和L相交
			 then count ← count+1;
if count mod 2 = 1
  then return true;
else return false;

对应代码例如以下:注:我是在coco2dx2.3版本号内測试的。因此可能移植要改些类名。

///@brief 推断点是否在多边形
///@param[in] p0--要推断点, poly--多边形点集合, numberOfPoints--多边形点数量
///@return 2---点在多边形内, 1---点在多边边上,0---点不在多边形内
///@author DionysosLai,[email protected]
///@retval
///@post
///@version 1.0
///@data 2014-04-11
int HelloWorld::pointIsInPolygon(const CCPoint& p0, const CCPoint* poly, const unsigned int numberOfPoints)
{
	unsigned int count  = 0;		///< 用来标记射线L与多边形的交点数;
	CCSize	winsize = CCDirector::sharedDirector()->getWinSize();
	/// 已点p0向左向右做一条射线L;
	CCPoint leftPoint = ccp(-100.0f, p0.y);
	CCPoint rightPoint = ccp(winsize.width+100.0f, p0.y);

	/// 推断每条边
	for (unsigned int i = 0; i < numberOfPoints-1; i++)
	{
		/// 先推断点p0是否在边s上;
		if (pointIsAtLine(p0, poly[i], poly[(i+1)%(numberOfPoints)]))
		{
			CCLOG("Point is at the %dth line", i);

			return 1;
		}

		/// 推断边s是否是平行线;
		if (poly[i].y != poly[(i+1)%(numberOfPoints)].y)
		{
			do
			{
				/// 推断边s的是否有端点在L上 同一时候 再推断该点是否是边s纵坐标较大的一个点
				if (pointIsAtLine(poly[i], leftPoint, rightPoint))
				{
					if (poly[i].y > poly[(i+1)%(numberOfPoints)].y)
					{
						count += 1;
					}
					break;
				}
				if (pointIsAtLine(poly[(i+1)%(numberOfPoints)], leftPoint, rightPoint))
				{
					if (poly[i].y < poly[(i+1)%(numberOfPoints)].y)
					{
						count += 1;
					}

					break;
				}	

				/// 假设边s没有端点在L上,则推断s与L是否相交
				if (segmentLineIsIntersect(leftPoint, rightPoint, poly[i], poly[(i+1)%(numberOfPoints)]))
				{
					count += 1;
				}
			} while (0);
		}
	}

	if (1 == count%2)
	{
		CCLOG("Point is not in polygon!");
		return 0;
	}
	else
	{
		CCLOG("Point is in  polygon!");
		return 2;
	}
}

这里有个pointIsAtLine。是用来推断点是否在边上函数;segmentLineIsIntersect。是用来推断两条线段是否相交函数。可參考我的还有一边博文:http://blog.csdn.net/dionysos_lai/article/details/24418697计算几何文档一系列文章(眼下仅仅写了一篇,实际上是几乎相同写了经常使用几何算法,还没写成博文。怪楼主太懒了。)

Ok,逐点扫描推断方法就是差不都这样了。

2.       扫描线算法

逐点扫描算法,没有充分考虑到像素之间的连贯性。效率低。

扫描线算法。就是要利用像素之间的连贯性,提高算法效率。

所谓连贯性:有三个概念,1.边的连贯性,AB边与扫描线1相交,也可能与扫描线2相交;2.扫描线连贯性:当前扫描线与多边形边交点顺序,可能与下一条扫描线交点情况一致或者类似;3.区间连贯性:同一区间像素取同一颜色属性。

扫描线原理:将整个多边形区域扫描问题分解到一条条扫描线问题。仅仅要完毕每条扫描线的绘制,就实现了多边形区域填充问题。

一条扫描线与多边形有偶数个交点(0就不算了),按顺序每2个点形成一个区间,仅仅要绘制这个区间就可以。

难点这与扫描线与多边形边交点推断,这个是高中问题了,通过线段一般方程ax+by+c=0,两立方程求解。

只是这样的方法。要计算各种參数,比較费时,更好的方法是分成各种情况分开讨论(尽管比較麻烦)。能够关注我的《计算几何算法》系类文章。

时间: 2024-10-07 07:53:05

OpenGL研究3.0 多边形区域填充的相关文章

OpenGL研究2.0 圆计算方法

DionysosLai2014-06-18 在游戏中,经常有些地方涉及到一些圆的轨迹计算,比方一些转轴类的游戏,人物一般在角色转轴上面运动.这时,我们就要时刻计算角色的位置.分析一下,圆位置的一般算法. 首先,如下图的一个圆: 图1 根据对称性原理,我们只需要计算黑色区域的点集合即可.同时,由于黑色区域的圆的切线斜率明显在-1到0,这点就可以和前面一节线段的计算方法相结合了. 圆的点计算方法: 1.      直接计算方法 1). 离散点计算法 利用隐函数公式方法:: 2). 三角函数方法 这两

Opengl研究4.0 走样与反走样

DionysosLai([email protected]) 2014-06-25 走样与反走样,也叫混淆与反混淆.所谓走样,是由于使用离散量(像素)表示连续量(图形)而引起的失真. 走样现象: 1.      阶梯状的图形边界 如图所示: 由于像素点是一块一块的,存在锯齿状. 2.       图形细节失真 由于显示图形的最小单位为像素,像素是由宽度的.有时候,我们可能显示的线段比像素要窄,要小.那么可能出现两种情况:a. 如果显示的线段宽度比像素宽度小一点,将被保留:b. 如果线段很细,就不

OpenGL研究2.0 计算圆

DionysosLai2014-06-18 在游戏中.常常有些地方涉及到一些圆的轨迹计算,例如一些转轴类的游戏,人物一般在角色转轴上面运动.这时,我们就要时刻计算角色的位置. 分析一下.圆位置的一般算法. 首先.例如以下图的一个圆: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRGlvbnlzb3NfbGFp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究

对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究 想要彻底研究OpenGL ES 2.0与前一代OpenGL的区别,还是要费很大一番精力的.最近在仔细研读<OpenGL ES 2.0 Programming Guide>,虽然这本书最早出版日期是2008年,距今已经7年了,而著作的日期或许还要早上半年到1年,但是目前OpenGL ES 2.0是主流三维开发框架,因此这本书的知识直到现在,依然受用. OpenGL ES 2.0是桌面版OpenGL 2.0的一个子集,

基于扫描种子线算法的多边形区域填充实现

本学期算法课上我们学习了计算几何的基础内容,在课后的深入了解学习中我发现,计算几何仅仅是算法世界一个重要分支——计算机图形学的基础部分之一,计算机图形学还有很多其他非常有趣的算法,例如直线生成.圆生成.椭圆生成.而在本学期进行java项目实践的过程中,我也遇到了一个和计算机图形学息息相关的问题,那就是如何实现windows自带画图软件中的工具油漆桶?网上的开源画图代码基本上均只实现了其他简单的绘制工具.为此,在查阅大量相关资料后,我学习到,种子填充算法可以很好地实现多边形区域填充,并用其中效果最

多边形区域填充算法--递归种子填充算法

http://blog.csdn.net/orbit/article/details/7323090 平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充).区域填充中最常用的是多边形填色,本文中我们就讨论几种多边形区域填充算法. 一.种子填充算法(Seed Filling) 如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法(Seed Fillin

基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)

[本系列转自]http://cn.cocos2d-x.org/tutorial/lists?id=79 前言 在本系列教程中,我会以当下最流行的2D引擎Cocos2d-x为基础,介绍OpenGL ES 2.0的一些基本用法.本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2d-x过程中,知其然,更知其所以然.本系列教程不会涉及非常底层的数学原理,同时也不会过多地提及OpenGL本身的一些细节知识.但是我会在每篇文章的最后给出一些参考链接,大家可以顺藤摸瓜,一举Get OpenGL这个新

基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)

在上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了.在这篇文章中,我们不再画三角形了,改为画四边形.下篇教程,我们就可以画立方体了,到时候就是真3D了. 为什么三角形在OpenGL教程里面这么受欢迎呢?因为在OpenGL的世界里面,所有的几何体都可以用三角形组合出来.我们的四边形也一样,它可以用两个三角形组合出来. 你的第一个四边形 首先,因为OpenGL里面没有直接绘制四边形的命令的,所以我们需要画两个三角形来拼成一个四边形.

win7下搭建opengl es 2.0开发环境

http://codingnow.cn/opengles/1501.html =================================================================== 1. 下载AMD的OpenGL ES2.0的模拟器 ,下载地址: http://www.opengles-book.com/ESEmulator.2009-04-28-v1.4.APRIL_2009_RELEASE.msi 2. 下载<OpenGL ES2.0 Programming