c++ 凸包 分治算法_LabVIEW Convex Hull(凸包)算法详解

凸包定义:

       凸包(Convex Hull)是一个计算几何(图形学)中的概念。

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

     最近写一个算法用到了平面内散乱点凸包计算,我直接使用LabVIEW自带的函数“Convex Hull.vi”计算,返回排好序的最小凸包集。

6c57e89b0ae90641f807005dacdc25c4.png

使用一段时间后,发现该VI在一些特定情况下,返回错误的凸包,排序出错,这是非常棘手的问题,算法不稳定。如下图所示:红色点是给定的一个点集,白色线是LabVIEW Convex Hull.vi 计算的结果,显然出现了错误。

fa3fcf8db9dcbcef117db20c005113fe.png

那还是从原理入手,写一遍!

使用Graham扫描法:

时间复杂度:O(n㏒n) 

8c448f9603bfc8831e1101ea86837f05.png

1)把所有点放在二维坐标系中,则Y轴最小的点一定是凸包上的点,如图中的P0。
2) 将所有点平移,使P0作为原点。
3)计算各个点相对于 P0 的幅角 α ,按从小到大的排序各点。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由几何知识可以知道,结果中第一个点 P1和最后一个点P8 一定是凸包上的点。 
 4) 以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在数组里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。接下来开始找第三个点:
如果第三个点与前两个点组成的三角形逆时针,则扔掉,继续找一下个点;如果三角形是顺时针则,则将该点存入数组,重复步骤4) 检查当前的点是不是最后一个元素p8,是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,继续重复步骤4)

LabVIEW实现:

1)检查输入数据是否有效:

b313367b42a0d76a025da1a505cf4ef0.png

2)删除掉重复点

a50c1470287ea287317f1936a5ee4fe7.png

这里使用变体属性来完成该操作,变体属性的存储方式是二叉树存储,是速度最快的一种删除方式。延展一点:常规的删除方式如下(OpenG的一种方式):

1adb50d0b1f2f02fc38cdb9c7f9cdd26.png

效率取决于搜索方式,线性搜索远远慢于二叉树搜索,数据量大时,效率会差很多。

3)极坐标转换、相同角度保留最远的点

79f142fc1e8fa9f999e7a57f03a9aeed.png

这里依然使用变体属性操作函数来设计算法,该套操作函数出镜率还是很高的。

4)查找构建三角形是顺时针排序的点,一直到查找结束。

718f5c35f06f4bdbd456d5078382d03f.png

5)顺时针判断

利用矢量叉积判断是逆时针还是顺时针。

设A(x1,y1),B(x2,y2),C(x3,y3),则三角形两边的矢量分别是:

AB=(x2-x1,y2-y1), AC=(x3-x1,y3-y1)

则AB和AC的叉积为:(2*2的行列式)

 |x2-x1, y2-y1|

 |x3-x1, y3-y1|

值为:(x2-x1)*(y3-y1) - (y2-y1)*(x3-x1)

利用右手法则进行判断:

如果AB*AC>0,则三角形ABC是逆时针的

如果AB*AC<0,则三角形ABC是顺时针的

如果……  =0,则说明三点共线,

2cbf9944722e740e6afecabd80d62a08.png

验证算法的准确性及稳定性:

2d99abf91b0e6a3b3e00495d22060239.png

7af96bde095de0fa7d80b0440047315a.png

具有COS标签的图,就是重写ConvexHull.vi算法的结果(右边图)。经过大量运算及验证,该方法稳定高效。

以上详细介绍了基于LabVIEW的凸包算法,并贴了源码!感兴趣的朋友欢迎交流!

=========================

有任何问题欢迎交流:

caf1f41b3b3d677e6a7524b7a7956935.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值