OpenGL研究3.0 多边形区域填充
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 多边形区域填充的更多相关文章
- OpenGL研究2.0 计算圆
OpenGL研究2.0 计算圆 DionysosLai2014-06-18 在游戏中.常常有些地方涉及到一些圆的轨迹计算,例如一些转轴类的游戏,人物一般在角色转轴上面运动.这时,我们就要时刻计算角色的 ...
- Opengl研究4.0 走样与反走样
Opengl研究4.0 走样与反走样 DionysosLai(906391500@qq.com) 2014-06-25 走样与反走样,也叫混淆与反混淆.所谓走样,是因为使用离散量(像 ...
- 在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping)
在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping) 视差贴图 最近一直在研究如何在我的 iPad 2(只支持 OpenGL ES 2.0, 不支持 3.0) 上实现 视 ...
- OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型
OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- 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, ...
- OpenGL ES 3.0 基础知识
首先要了解OpenGL的图形管线有哪些内容,再分别去了解其中的相关的关系: 管线分别包括了顶点缓冲区/数组对象,定点着色器,纹理,片段着色器,变换反馈,图元装配,光栅化,逐片段操作,帧缓冲区.其中顶点 ...
- 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, ...
- Android OpenGL ES 3.0 纹理应用
本文主要演示OpenGL ES 3.0 纹理演示.接口大部分和2.0没什么区别,脚本稍微有了点变化而已. 扩展GLSurfaceView package com.example.gles300; im ...
随机推荐
- 【VBA】全局数组定义
[说明] 全局数组定义(写在Module的最上面) 'Array Public Arr_approver Public Arr_delegator Public Arr_Role
- 【小技巧】树剖套线段树优化建图如何做到 O(nlogn)
前提:用树剖套线段树优化树链连边.例题:bzoj4699 我们说树剖的时间复杂度是 $O(n\times log(n))$,是因为访问一条链时需要经过 $log(n)$ 级别条重链,对于每条重链还需要 ...
- iOS 代理为啥要用weak修饰?
在开发中我们经常使用代理,或自己写个代理,而代理属性都用weak(assign)修饰,看过有些开发者用strong(retain),但并没发现有何不妥,也不清楚weak(assign)与strong( ...
- Docker学习之Docker Registry
前言 前面已经学习了怎样通过Dockerfile来构建我们自己的镜像了,但是一个系统可能包含着很多个微服务即有很多个镜像,当镜像越来越多的时候,就必须得有一个地方来管理这些镜像,Docker官方提供了 ...
- FCKeditor2.6.4控件及其使用范例
原文发布时间为:2009-06-14 -- 来源于本人的百度文章 [由搬家工具导入] 已经精简了,很小,不多说了,我的源代码去下载看。 web.config 看看。。。还有bin里面的dll就是控件, ...
- Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分
题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...
- C#byte怎么转成图片
这个其实很简单我给大家提供一个方法吧 /// <summary> /// 字节数组生成图片 /// </summary> /// <param name="By ...
- git tag 的使用
// 查看tag,列出所有tag,列出的tag是按字母排序的,和创建时间没关系. $ git tag v0.1 v1.3 /查看指定版本的tag,git tag -l “v1.4.2.**” $ gi ...
- python第三方库安装-多种方式
第一种方式:安装whl文件 pip install whatever.whl 第二种方式:安装tar.gz文件 一般是先解压,然后进入目录之后,有setup.py文件 通过命令 python se ...
- bzoj1455&&luogu2713罗马游戏
罗马游戏 题目描述 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻. ...