OpenGL研究3.0 多边形区域填充
OpenGL研究3.0 多边形区域填充
DionysosLai(906391500@qq.com)2014-06-22
所谓多边形区域填充。就是将多边形内部区域,所有已相同色块填充。注意:这里讨论的多边形是简单多边形(即不考虑诸如五角星这样的相交多边形)。简单多边形,分为凹多边形和凸多边形。
多边形区域填充有下面几种方法:
1. 逐点扫描方法:
原理:扫描多边形区域,逐点推断点是否在多边形内。
难点:在于怎样推断点是否在区域内;
经常使用怎样推断点是否在区域内方法:射线法、面积法。
面积法原理:取一个点。连接多边形各个点,依据三个点形成一个三角形原理,我们能够求得三角形面积。推断面积的大小,就能够推断该店是否在多边形内了。
射线法:这种方法。是我们这里要重点解说的一个方法。原理:取一个点。向左或者向右做一条射线过去,推断射线与多边形的交点。依据多边形交点熟练和本身多边形边情况,推断点是否在多边形内。
首先,射线从左向右,最左边点肯定在多边形区域为(我们这里假定射线方向水平向左)。那么与多边形相交第一个点,必定表明射线右部分在多变形内,与多边形相交第二个点。表明射线右部分在多边形外面。因此。通过推断射线与多变的交点奇偶性。推断点是否在多边形内。
这里。有几种特殊情况,例如以下图所看到的:
图a,射线与多变形顶点相交,顶点算一个;图b。射线与多边形顶点的交点。不被计算在内(注意图a和图b的差别->顶点纵坐标大小差别);图c和图d,射线与多边形一条边重合,这条边被忽略不计。
因此。我们能够设计例如以下:取点向左做一条射线,1. 对于水平边不做考虑;2. 对于多边形顶点与射线交点情况。假设其纵坐标是所属边较大顶点,则计数(參考图a),否则不计数(图b)。3.对于点在多边形上情况,可直接推断点在多边形内。
伪代码例如以下:
count ← 0;
以P为端点。作从右向左的射线L;
for 多边形的每条边sdo if P在边s上 then return true;if s不是水平的then if s的一个端点在L上if 该端点是s两端点中纵坐标较大的端点then count ← count+1else 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,906391500@qq.com
///@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,两立方程求解。
只是这样的方法。要计算各种參数,比較费时,更好的方法是分成各种情况分开讨论(尽管比較麻烦)。能够关注我的《计算几何算法》系类文章。
转载于:https://www.cnblogs.com/lytwajue/p/6823287.html
OpenGL研究3.0 多边形区域填充相关推荐
- 在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping)
在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping) 视差贴图 最近一直在研究如何在我的 iPad 2(只支持 OpenGL ES 2.0, 不支持 3.0) 上实现 视 ...
- OpenGL研究, GUI框架分析, 虚拟机比较, Win10历险记, WxWidget, uboot, WireShark
http://antkillerfarm.github.io/ OpenGL研究 书籍 我手上其实有几本关于OpenGL的实体书,但是比较了一下之后,发现还是电子版的<OpenGL编程指南> ...
- Android opengl es 3.0 + ndk 绘画涂鸦项目
前言 写一个opengl es 3.0 + ndk 的绘画涂鸦项目,命名为白板哈哈哈,记录自己遇到的问题,顺便学到的知识整合一遍,算是对自己一段时间的总结. 项目地址:Whiteboard 如果对你有 ...
- OpenGL(十二)——Qt OpenGL绕着坐标轴旋转多边形
OpenGL(十二)--Qt OpenGL绕着坐标轴旋转多边形 一.旋转多边形 前两篇介绍了如何绘制多边形,并且给多边形进行上色.本篇介绍如何旋转多边形. 多边形的旋转,在类中增加两个变量来控制这两个 ...
- android平台下OpenGL ES 3.0给图片添加黑白滤镜
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- OpenGL ES 2.0 for Android教程(六):进入第三维
OpenGL ES 2 第六章:进入第三维 文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(二) OpenGL ES ...
- 多边形区域填充算法--扫描线填充算法(有序边表法)
来源:https://blog.csdn.net/u013044116/article/details/49737585 二.扫描线算法(Scan-Line Filling) 扫描线算法适合对矢量图形 ...
- OpenGL ES 2.0 for Android教程(九):添加触摸反馈
OpenGL ES 2 第九章:添加触摸反馈 文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(二) OpenGL ES ...
- OpenGL ES 2.0 总体概述
文章目录 OpenGL ES 2.0 总体概述 1. OpenGL ES 的两个小伙伴 1.1 EGL 1.2 GLSL 2. 屏幕图片的本质和产生过程 3. OpenGL ES pipeline 3 ...
最新文章
- 阿里云K8S容器服务的使用
- Windows下32位汇编语言读取键盘输入单字符
- 第三次spring冲刺1
- django web 自定义通用权限控制
- (c语言)求满足表达式1+2+3+.......+n<=1000的最大的n
- Python 将中文、字母转成数字
- 长等线,中等线,正等线,细等线,扁宋,扁等线
- C语言:大小字母转换(ASCII码)
- Android webview拦截请求
- php相册照片批量修改,php如何实现批量修改文件名称
- 速览 关于网络安全专业学生的未来职业规划
- 第21章 DHCP
- 2022年全球与中国光通信芯片市场现状及未来发展趋势
- Pspice积分线路仿真问题汇总(压控电压源模拟理想运放)
- VS2022无法打开Silverlight 项目的问题:改用VS2015
- IDEA上Java项目控制台中文乱码
- 快速学习时代的三大高效学习技能
- Linux中如何使用Wireshark来分析数据包?
- VS2008Pro下载地址
- 淡季开战!列出“三宗罪”优信死磕瓜子
热门文章
- 记录程序写入日志_终于有人把MySQL 三大日志讲清楚了
- linux svn 看不到文件,SVN更新时不能打开新文件svn-base系统找不到指定的文件
- ldap统一用户认证php,针对LDAP服务器进行身份认证
- jsp mysql 音乐网站_Maven+JSP+SSM+Mysql实现的音乐网站
- 联想小新air14笔记本黑屏_联想小新air14锐龙版测评,谈谈它的好和坏
- linker `cc` not found
- MySQL 8.0.22执行器源码分析HashJoin —— 一些初始化函数的细节步骤
- Python中的append()和extend()
- java enummap_Java EnumMap containsKey()方法与示例
- c#中将集合写入文本_在C#中将记录插入MySQL数据库