OpenGL研究3.0 多边形区域填充

DionysosLai(906391500@qq.com)2014-06-22

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

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

1.      逐点扫描方法:

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRGlvbnlzb3NfbGFp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

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

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

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

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

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

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

图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,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.区间连贯性:同一区间像素取同一颜色属性。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRGlvbnlzb3NfbGFp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

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

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

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

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

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

  1. OpenGL研究2.0 计算圆

    OpenGL研究2.0 计算圆 DionysosLai2014-06-18 在游戏中.常常有些地方涉及到一些圆的轨迹计算,例如一些转轴类的游戏,人物一般在角色转轴上面运动.这时,我们就要时刻计算角色的 ...

  2. Opengl研究4.0 走样与反走样

    Opengl研究4.0 走样与反走样 DionysosLai(906391500@qq.com) 2014-06-25          走样与反走样,也叫混淆与反混淆.所谓走样,是因为使用离散量(像 ...

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

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

  4. OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型

    OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...

  5. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  6. Beginning OpenGL ES 2.0 with GLKit Part 1

    Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, ...

  7. OpenGL ES 3.0 基础知识

    首先要了解OpenGL的图形管线有哪些内容,再分别去了解其中的相关的关系: 管线分别包括了顶点缓冲区/数组对象,定点着色器,纹理,片段着色器,变换反馈,图元装配,光栅化,逐片段操作,帧缓冲区.其中顶点 ...

  8. OpenGL ES 3.0 点,线,三角形绘制形式总结

    OpenGL ES 3.0 顶点     -1,  1, 0, -0.5f,  0, 0,     0, -1, 0,    -1,  0, 0, 0.5f,   0, 0,     1, -1,   ...

  9. Android OpenGL ES 3.0 纹理应用

    本文主要演示OpenGL ES 3.0 纹理演示.接口大部分和2.0没什么区别,脚本稍微有了点变化而已. 扩展GLSurfaceView package com.example.gles300; im ...

随机推荐

  1. JavaScript真的要一统江湖了

    ttp://www.newsmth.net/nForum/#!article/Python/125347?p=4 标  题: JavaScript真的要一统江湖了 发信站: 水木社区 (Fri Sep ...

  2. XPath gramma

    XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. XML 实例文档 我们将在下面的例子中使用这个 XML 文档. & ...

  3. DOS头结构

    DOS头结构typedef struct _IMAGE_DOS_HEADER {                 // DOS .EXE header   +0h WORD   e_magic;    ...

  4. MySQL 手动主从同步不锁表

    有时候MySQL主从同步不一致比较严重的时候,需要手动同步. 然而网上看大很多需要锁表的同步的方法基本如下 1.先对主库锁表 FLUSH TABLES WITH READ LOCK; 2.备份数据 m ...

  5. Java I/O系统学习系列一:File和RandomAccessFile

    I/O系统即输入/输出系统,对于一门程序语言来说,创建一个好的输入/输出系统并非易事.因为不仅存在各种I/O源端和想要与之通信的接收端(文件.控制台.网络链接等),而且还需要支持多种不同方式的通信(顺 ...

  6. JMeter特殊情况二:针对某些请求数据每次请求都是变化的情况

    概要:某些post请求,例如,登录的请求除了有我们再页面上需要输入的一些值(用户名.密码.是否记住密码等)之外,还有其他的参数,例如token等等,而且这些参数不固定,也就是说每一次post请求这些参 ...

  7. spring 基础

    作者:Spring太难链接:https://zhuanlan.zhihu.com/p/38131490来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 目录 Spring ...

  8. Akka之Actor生命周期

    我们首先来看一下官方给出的Actor的声明周期的图: 在上图中,Actor系统中的路径代表一个地方,其可能会被活着的Actor占据.最初路径都是空的.在调用actorOf()时,将会为指定的路径分配根 ...

  9. angular使用canvas操作时报错

    最近,用 angular 前端框架为应用登录新增图形验证码认证,由于没有现成的插件,于是便使用canvas+js操作,也是可以正常使用,但是在编译阶段却有个报错: ERROR in src/app/l ...

  10. Oracle rac配置Weblogic数据源(实例名及URL的选择)

    这几天,应用程序后台一直报无法取得连数据库接池.但之前从来没有这个问题,迁移到Weblogic后才发生. 之后据了解,我们服务器上的Oracle 10G 是 RAC 的,即有两个节点. 两个节点 IP ...