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 多边形区域填充相关推荐

  1. 在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping)

    在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping) 视差贴图 最近一直在研究如何在我的 iPad 2(只支持 OpenGL ES 2.0, 不支持 3.0) 上实现 视 ...

  2. OpenGL研究, GUI框架分析, 虚拟机比较, Win10历险记, WxWidget, uboot, WireShark

    http://antkillerfarm.github.io/ OpenGL研究 书籍 我手上其实有几本关于OpenGL的实体书,但是比较了一下之后,发现还是电子版的<OpenGL编程指南> ...

  3. Android opengl es 3.0 + ndk 绘画涂鸦项目

    前言 写一个opengl es 3.0 + ndk 的绘画涂鸦项目,命名为白板哈哈哈,记录自己遇到的问题,顺便学到的知识整合一遍,算是对自己一段时间的总结. 项目地址:Whiteboard 如果对你有 ...

  4. OpenGL(十二)——Qt OpenGL绕着坐标轴旋转多边形

    OpenGL(十二)--Qt OpenGL绕着坐标轴旋转多边形 一.旋转多边形 前两篇介绍了如何绘制多边形,并且给多边形进行上色.本篇介绍如何旋转多边形. 多边形的旋转,在类中增加两个变量来控制这两个 ...

  5. android平台下OpenGL ES 3.0给图片添加黑白滤镜

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  6. OpenGL ES 2.0 for Android教程(六):进入第三维

    OpenGL ES 2 第六章:进入第三维 文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(二) OpenGL ES ...

  7. 多边形区域填充算法--扫描线填充算法(有序边表法)

    来源:https://blog.csdn.net/u013044116/article/details/49737585 二.扫描线算法(Scan-Line Filling) 扫描线算法适合对矢量图形 ...

  8. OpenGL ES 2.0 for Android教程(九):添加触摸反馈

    OpenGL ES 2 第九章:添加触摸反馈 文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(二) OpenGL ES ...

  9. OpenGL ES 2.0 总体概述

    文章目录 OpenGL ES 2.0 总体概述 1. OpenGL ES 的两个小伙伴 1.1 EGL 1.2 GLSL 2. 屏幕图片的本质和产生过程 3. OpenGL ES pipeline 3 ...

最新文章

  1. 阿里云K8S容器服务的使用
  2. Windows下32位汇编语言读取键盘输入单字符
  3. 第三次spring冲刺1
  4. django web 自定义通用权限控制
  5. (c语言)求满足表达式1+2+3+.......+n<=1000的最大的n
  6. Python 将中文、字母转成数字
  7. 长等线,中等线,正等线,细等线,扁宋,扁等线
  8. C语言:大小字母转换(ASCII码)
  9. Android webview拦截请求
  10. php相册照片批量修改,php如何实现批量修改文件名称
  11. 速览 关于网络安全专业学生的未来职业规划
  12. 第21章 DHCP
  13. 2022年全球与中国光通信芯片市场现状及未来发展趋势
  14. Pspice积分线路仿真问题汇总(压控电压源模拟理想运放)
  15. VS2022无法打开Silverlight 项目的问题:改用VS2015
  16. IDEA上Java项目控制台中文乱码
  17. 快速学习时代的三大高效学习技能
  18. Linux中如何使用Wireshark来分析数据包?
  19. VS2008Pro下载地址
  20. 淡季开战!列出“三宗罪”优信死磕瓜子

热门文章

  1. 记录程序写入日志_终于有人把MySQL 三大日志讲清楚了
  2. linux svn 看不到文件,SVN更新时不能打开新文件svn-base系统找不到指定的文件
  3. ldap统一用户认证php,针对LDAP服务器进行身份认证
  4. jsp mysql 音乐网站_Maven+JSP+SSM+Mysql实现的音乐网站
  5. 联想小新air14笔记本黑屏_联想小新air14锐龙版测评,谈谈它的好和坏
  6. linker `cc` not found
  7. MySQL 8.0.22执行器源码分析HashJoin —— 一些初始化函数的细节步骤
  8. Python中的append()和extend()
  9. java enummap_Java EnumMap containsKey()方法与示例
  10. c#中将集合写入文本_在C#中将记录插入MySQL数据库