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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转]Android笔记:ScrollView嵌套ViewPager的滚动冲突解决方法

12345678910111213141516171819202122232425262728293031323334/*** 能够兼容ViewPager的ScrollView * Description: 解决了ViewPager在ScrollView中的滑动反弹问题 */ public class ScrollViewExtend extends ScrollView { // 滑动距离及坐标 private float xDistance, yDista…

android tv 乐视手机,乐视超4系列原生Android TV分享

固件&#xff1a;Official USA Firmware:USA BIN Firmware 5.8.050S_1028://mega.nz/#F!7PhyDI6D!TnwNlMmWXosK1uCUdpyNGg[/url]USA ZIP Firmware 5.8.056S_0420 (OTA ZIP, must be flashed only after flashing the above bin)://drive.google.com/open?id1N9...rNHVB_-VPIad…

ping、网络抖动与丢包

基本概念&#xff1a; ping: PING指一个数据包从用户的设备发送到测速点&#xff0c;然后再立即从测速点返回用户设备的来回时间。也就是俗称的“网络延迟” 一般以毫秒&#xff08;ms&#xff09;计算 一般PING在0~100ms都是正常的速度&#xff0c;不会有较为明显的卡顿。 测试…

Webtask后端即服务:无服务器快速教程

查尔斯厄勒(Charles Ouellet) (By Charles Ouellet) The word serverless is buzzing through dozens of dev circles today.如今&#xff0c; 无服务器一词正在数十个开发界中流行。 It has been for a while now.已经有一段时间了。 I’ve been meaning to exit my code ed…

leetcode145. 二叉树的后序遍历(dfs)

给定一个二叉树&#xff0c;返回它的 后序 遍历。示例:输入: [1,null,2,3] 1\2/3 输出: [3,2,1]class Solution {List<Integer> listnew ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {getPostorderTraversal(root);return list;…

[luoguP2801] 教主的魔法(二分 + 分块)

传送门 以为对于这类问题线段树都能解决&#xff0c;分块比线段树菜&#xff0c;结果培训完才知道线段树是一种特殊的分块方法&#xff0c;有的分块的题线段树不能做&#xff0c;看来分块还是有必要学的。 对于这个题&#xff0c;先分块&#xff0c;然后另开一个数组对于每个块…

鸿蒙系统适配开发,捕获科技拟建立鸿蒙开发组 为区块链钱包客户适配鸿蒙系统做筹备...

遭遇美国“实体清单”封杀的第85天&#xff0c;华为“鸿蒙”横空出世&#xff01;8月9日下午&#xff0c;在华为全球开发者大会上&#xff0c;当余承东正式宣布鸿蒙系统(Harmony OS)发布的时候&#xff0c;全场掌声雷动&#xff01;世界上第一个由中国企业自主研发的全平台微内…

[arm驱动]linux内核中断编程

第一部分获取中断(开启硬件中断)一、中断的申请注销: 1&#xff09;中断的申请 12int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) 2)中断的注销 1void free_irq(unsigned int irq, void *dev_id) 3&am…

关于VCP(Virtual Com Port)拓展的调试经历(一)

* The Overview 前日&#xff0c;接到老板部署的任务&#xff0c;将现有的基于STM32L151与L432的LoRaWAN程序中添加USB CDC(Communication Device Class)功能&#xff0c;并枚举为VCP(Virtual Com Port)用以替代以往的串口打印。很疑惑为什么以前架构代码的时候没有添加进去。。…

leetcode701. 二叉搜索树中的插入操作(dfs)

给定二叉搜索树&#xff08;BST&#xff09;的根节点和要插入树中的值&#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证&#xff0c;新值和原始二叉搜索树中的任意节点值都不同。注意&#xff0c;可能存在多种有效的插入方式&#xff0c;只要树在…

三星s6 android 8.0,再见Android 8.0,三星s6全系列系统都停止了,第一代国王已经倒下了吗?...

对于Android用户而言&#xff0c;最令人兴奋的事情是系统更新&#xff0c;因为该更新意味着更流畅的体验和更加用户友好的功能. 但是&#xff0c;旧的三星S6并不是那么幸运&#xff0c;并且不再错过Android 8.0.三星s6的全系列指的是三星s6&#xff0c;三星s6 edge&#xff0c;…

devise tree_Devise如何确保您的Rails应用密码安全

devise treeby Tiago Alves由蒂亚戈阿尔维斯(Tiago Alves) Devise如何确保您的Rails应用密码安全 (How Devise keeps your Rails app passwords safe) Devise is an incredible authentication solution for Rails with more than 40 million downloads. However, since it ab…

Exchange 2010无法安装问题解决方法

当你在活动目录(AD)森林中安装多台全局编录服务器(GC)之后,默认情况下你会发现在AD站点里面自动生成二条站点连接,从上面的截图可以看到目前在AD森林的Default-First-Site-Name(默认站点)里面有6台GC。 从上面的截图可以看到目前只有一台叫做Sh-Site1GC(全局编录服务器)是处于运…

android edittext 不滚动,EditText 设置可以垂直滑动但是不可输入

一、前言&#xff1a;android:id"id/edtInput"android:layout_width"match_parent"android:layout_height"60dp"android:background"drawable/round_theme_3_gray"android:gravity"top"android:hint"string/please_inp…

snmpd修改端口

http://blog.csdn.net/cau99/article/details/5077239 http://blog.csdn.net/gua___gua/article/details/48547701转载于:https://www.cnblogs.com/diyunpeng/p/6829592.html

leetcode LCP 19. 秋叶收藏集(dp)

小扣出去秋游&#xff0c;途中收集了一些红叶和黄叶&#xff0c;他利用这些叶子初步整理了一份秋叶收藏集 leaves&#xff0c; 字符串 leaves 仅包含小写字符 r 和 y&#xff0c; 其中字符 r 表示一片红叶&#xff0c;字符 y 表示一片黄叶。 出于美观整齐的考虑&#xff0c;小扣…

步进电机 步距角 编码器_我如何迈出了学习编码的第一步

步进电机 步距角 编码器A couple of months ago, I was chatting to a developer at work about how I’ve always wanted to learn to code but never tried.几个月前&#xff0c;我正在与一个开发人员聊天&#xff0c;讨论我一直想学习编码但从未尝试过的方法。 Coding alwa…

第五章:配置使用FastJson返回Json视图

fastJson是阿里巴巴旗下的一个开源项目之一&#xff0c;顾名思义它专门用来做快速操作Json的序列化与反序列化的组件。它是目前json解析最快的开源组件没有之一&#xff01;在这之前jaskJson是命名为快速操作json的工具&#xff0c;而当阿里巴巴的fastJson诞生后jaskjson就消声…

一加6android9玩飞车掉,解锁新速度:一加6T深度评测

解锁新速度&#xff1a;一加6T深度评测2019-11-02 14:28:595点赞2收藏4评论创作立场声明&#xff1a;我们只谈智能硬件&#xff0c;向改变生活的智能硬件Say“嗨”&#xff01;作为安卓旗舰机成员&#xff0c;一加这个品牌在玩机一类的同学手里可是大放光彩&#xff0c;各种刷机…

设计模式(第十七式:迭代器模式)

概念&#xff1a;  迭代器模式&#xff1a;Provide a way to access the elements of an aggregarte object sequentiaally with exposing its underlying representation. 提供一种访问容器对象内每个元素的一种方式&#xff0c;并且不暴露对象的一些内部细节。实现&#xf…