计算点、线、面等元素之间的交点、交线、封闭区域面积和闭合集(续7)
介绍求取平面上顶点集合凸包的Graham Scan和Andrew's Monotone Chain方法。基本原理是在顶点排序好后,初始化一栈,循环取出顶点集合中每个顶点元素,将其与栈顶两元素进行判别,看是否符合凸包条件,循环结束后,栈中剩余元素即为所求。具体过程如下。
求凸包Graham Scan方法。它的大致过程是:
找到最右下顶点P0后,以各顶点与P0X的夹角来排序所有的集合中顶点。实际工作中,可简化角度计算工作,而通过前面章节介绍的isLeft()函数,来判断顶点P2是否处于线段P0P1左边,从而判断夹角的大小。设这些经过排序的顶点为P0,P1,…Pn-1;
邻接关系判断图
将顶点排好序
然后,建立一个栈,最开始时P0,P1进栈,对于剩下的顶点P2,P3,…Pn-1等依次取出,若栈顶的开头两个顶点与新取出的顶点不满足“左转”(即isLeft()函数返回数值大于0)条件,则将栈顶的第一个顶点出栈,继续测试,直到满足“左转”条件后将新取出的顶点进栈;所有剩下的顶点P2,P3,…Pn-1处理完之后栈中剩下的顶点构成凸包。
需说明的是,此方法很难推进到三维空间。
参考代码:
//主程序
Stack GrahamScan( )
{
Stack top;
int i;
Point p1, p2;
top = NULL;
top = Push ( &P[0], top );
top = Push ( &P[1], top ); //初始化栈
i = 2;
while ( i < n ) //对所有的排序后顶点循环
{
if( !top->next) printf("Error"n"); //栈中没有第二个元素,报出错信息
p1 = top->next->p;
p2 = top->p; //取出栈顶的两个元素
if ( isLeft( p1->v , p2->v, P[i].v ) )//判断是否左转
{
top = Push ( &P[i], top ); //压栈
i++; //顶点计数器增加
}
else
top = Pop( top ); //退栈
}
return top; //栈中剩下的元素即为构成凸包的顶点
}
//开始准备工作中寻找所有顶点中右下角顶点
int FindLowest( void )
{
int i;
int m = 0;
for ( i = 1; i < n; i++ ) //对所有顶点循环
if ( (P[i].v[Y] < P[m].v[Y]) ||
((P[i].v[Y] == P[m].v[Y]) && (P[i].v[X] > P[m].v[X])) )
m = i;
return m; //返回右下角最低点索引
}
求凸包Andrew's Monotone Chain方法。
首先,依X轴和Y轴数值顺序排列所有顶点。
以最左(当X轴数值相同的时候,以Y轴数值最下和最上取顶点)至最右边的顶点(当X轴数值相同的时候,以Y轴数值最下和最上取顶点)连线,构成Lup,Llow等线段,将顶点集合分成上下两部分,分别使用类似于上面介绍的Graham Scan方法寻求子凸包,最后合并形成一个凸包(注意连接处顶点的重复存储)。
参考代码:
// 输入经过排序的顶点数组 P[],n为数组中顶点个数
// 输出: 凸包的顶点集合 H[]
// 返回: H[]中的顶点个数
int CDEMAlgorithm::chainHull_2D( Point* P, int n, Point* H )
{
// 输出的数组H[]被用作一个栈
int bot=0, top=(-1); // 指示栈底和栈顶
int i;
int minmin = 0, minmax; // 得到X轴最小情况下Y轴分别最小和最大顶点的索引
double xmin = P[0].x;
for (i=1; i<n; i++)
if (P[i].x != xmin) break; //顶点已经排好序,搜索开始阶段的X轴最小值
minmax = i-1; //记录X轴最小情况下Y轴最大顶点的索引
if (minmax == n-1) { // 如果出现极端情况,即所有顶点X轴数值都最小
H[++top] = P[minmin];
if (P[minmax].y != P[minmin].y) // 如果两顶点的Y轴数值不等,则可构成线段
H[++top] = P[minmax];
H[++top] = P[minmin]; // 将这两个顶点增加到输出的数组中
return top+1; //返回输出的数组中的顶点个数
}
int maxmin, maxmax = n-1; // 得到X轴数值最大情况下 Y轴数值分别最小和最大的顶点索引
double xmax = P[n-1].x;
for (i=n-2; i>=0; i--) //从顶点的原始数组中反向循环,因为顶点已排好序
if (P[i].x != xmax) break;
maxmin = i+1; //记录X轴数值最大情况下Y轴数值最小的顶点索引
H[++top] = P[minmin]; // 开始计算下半部分凸包,首先将X轴和Y轴数值都最小的顶点压入栈
i = minmax; //从X轴数值最小情况下Y轴数值最大的顶点开始计数
while (++i <= maxmin)
{
// 以X轴和Y轴数值最小顶点连接X轴最大和Y轴数值最小顶点建立低线
if (isLeft( P[minmin], P[maxmin], P[i]) >= 0 && i < maxmin)
continue; // 由于此顶点位于这根低线之上,所以忽略,继续下次循环
while (top > 0) // top是从最开始的-1计数,所以大于0的话,表明栈中至少有2个元素
{
if (isLeft( H[top-1], H[top], P[i]) > 0)
break; //表明P[i]顶点是需要的凸包中新顶点,结束循环
else
top--; //将栈顶元素出栈,继续循环
}
H[++top] = P[i]; // 将顶点P[i]压入栈
}
// 下面,计算上半部分的凸包顶点集合
if (maxmax != maxmin) // 如果X轴数值最大情况下Y轴有不同顶点存在
H[++top] = P[maxmax]; // 将X轴数值与Y轴数值最大的顶点压入栈
bot = top; // 记住准备增加元素到栈前已经存在的元素个数
i = maxmin; //从X轴数值最大情况下Y轴数值最小的顶点开始计数
while (--i >= minmax)
{
// 以X轴和Y轴数值最大顶点连接X轴最小和Y轴数值最大顶点建立高线
if (isLeft( P[maxmax], P[minmax], P[i]) >= 0 && i > minmax)
continue; // 由于此顶点位于这根高线之下,所以忽略,继续下次循环
while (top > bot) // top还是比开始记住的bot大,表明栈中至少有2个元素
{
if (isLeft( H[top-1], H[top], P[i]) > 0)
break; //表明P[i]顶点是需要的凸包中新顶点,结束循环
else
top--; //将栈顶元素出栈,继续循环
}
H[++top] = P[i]; // 将顶点P[i]压入栈
}
if (minmax != minmin) //如果X轴数值最小情况下Y轴有不同顶点存在
H[++top] = P[minmin]; // 把这最后一个顶点压入栈
return top+1; //返回输出的凸包数组中的顶点个数
}
转载于:https://www.cnblogs.com/wuhanhoutao/archive/2008/03/19/1112650.html
计算点、线、面等元素之间的交点、交线、封闭区域面积和闭合集(续7)相关推荐
- 计算点、线、面等元素之间的交点、交线、封闭区域面积和闭合集(续1)
继续上一节的内容,本节主要讲解三维空间中射线.线段与平面及三维物体的交点及距离的计算,它们在碰撞检测和可见性剔除等应用中是必不可少的.首先给出3D空间下点乘和叉乘的定义与定理的推导,再谈如何应用到程序 ...
- opencv检测相交点_在网络摄像头feed opencv中检测2条线之间的交点
我正在尝试检测摄像头Feed中两条线之间的交点.这是我已经拥有的屏幕截图 我尝试找到红线和绿线之间的交点. 这是我已经拥有的代码 #include "stdafx.h" #incl ...
- ad16 怎么设置单独元件间距_AD软件中怎么添加不同元素之间的间距规则?
我们在进行PCB设计的时候,一定会碰到各种元素与各种元素之间的间距规则的设置.比如想要设置铜皮跟走线的间距,或者设置过孔跟丝印的间距.这些都涉及到我们最基本的PCB设计,所以足以看出这项技能在PCB设 ...
- pandas使用pct_change计算数据列的百分比变化、环比变化率:计算当前元素和前一个元素之间的百分比变化、使用style函数指定format的格式:百分比、缺失值替换、用颜色标注极大值和极小值
pandas使用pct_change计算数据列的百分比变化.环比变化率:计算当前元素和前一个元素之间的百分比变化.使用style函数指定format的格式:百分比.缺失值替换.用颜色标注极大值和极小值 ...
- pandas使用pct_change函数计算数据列的百分比变化:计算当前元素和前一个元素之间的百分比变化(包含NaN值的情况以及数据填充方法)
pandas使用pct_change函数计算当前元素和前一个元素之间的百分比变化:默认情况下pct_change函数计算与紧邻前一行相比的百分比变化.计算当前元素和前一个元素之间的百分比变化(包含Na ...
- R语言使用forestplot包绘制森林图:编码创建森林图仿真数据、汇总线修改、元素位置调整、垂直线、字体、风格、置信区间、线型、图例、刻度、标签等
R语言使用forestplot包绘制森林图:编码创建森林图仿真数据.汇总线修改.元素位置调整.垂直线.字体.风格.置信区间.线型.图例.刻度.标签等 目录
- bootstrap4 调整元素之间距离
https://blog.csdn.net/jianye5461/article/details/79463014 影响元素之间的间距是可以通过style的margin或padding属性来实现,但这 ...
- 如何删除内联块元素之间的空间?
鉴于此HTML和CSS: span { display:inline-block; width:100px; background-color:palevioletred; } <p> & ...
- 051_元素之间空白间隙解决方案
1. 元素li和li之间, 以及多个图片直接会有一段空白的, 空白符会造成元素显示有间隙.消除间隙就不能有空白符.不留空白代码格式又显得糟糕. 2. 我们有消除间隙小窍门, 在元素的父容器中设置: f ...
最新文章
- Python 学习笔记01
- Linux系统基础-管理之用户、权限管理
- __slots__(面向对象进阶)
- 关于 SAP 电商云 Spartacus UI checkout 流程的一些讨论
- linux系统如何拨号上网连接,教你在Linux下如何使用ADSL拨号上网
- Java陷阱(一)——ArrayList.asList
- GPS定位,经纬度附近地点查询–C#实现方法
- 2021年中国传感器行业产业链分析:智能时代发展下,传感器市场需求旺盛[图]
- 互联网早报:微信内测深度清理功能内存,可一键清理缓存
- CANdelaStudio编辑CDD——学习碎笔
- [Phonegap+Sencha Touch] 移动开发19 某些安卓手机上弹出消息框 点击后不消失的解决的方法...
- 微信公众号申请注意事项
- frameworks/base/core/res/res/values/symbols.xml:3915: error: no definition for declared symbol解决办法
- 小米5 miui9 android8,小米5升级MIUI9速度对比MIUI8:开机就快10秒
- 推荐系统中的常用算法——基于Session的推荐
- H3C 802.11n的频宽模式
- 一名武大同学的春招48小时
- Google 搜素技巧分享
- 全国首批城市级5G车联网应用项目落地!
- VMware16安装CentOS7 并配置网络(步骤详细)