1、凸包定义
凸包问题可以描述为:给定一个点集P,求最小点集S,使得S构成的形状能包含这些点集。
凸包的定义为:平面的一个子集S被称为是“凸”的,当且进当对于任意两点p,q∈S,线段
都完全属于S。几何S的凸包CH(S),就是包含S的最小凸集,更准确地说,它是包含S的所有凸集的交[2]。由此还可以推出凸包的很多性质,包括一条直线如果与凸包相交(不是相切)的话,最多交于两条边或者两个面
二维:
三维:
2、凸包算法
计算几何的算法,大致可以分为增量法和分治法。
2.1 增量法
增量法就是一直k个顶点的解集,与第k+1个顶点合并得到新的解集。分治法解决凸包问题有两个方向,无序地增加顶点和Gift-Wrapping查询。
2.1.1 增点法
直接使用增量法的思想,可以将凸包算法简述为:
- 遍历所有点
- 对于新增加的每个点p,分析其是否在当前构成的凸包内,如果在则直接忽略该点,如果不在则将当前凸包和p整合成一个新的凸包。
2.1.2 Gift-Wrapping查询
Gift-Wrapping查询暂时限定在二维平面上,表述为:给定点集s,点q和过q的直线l,问l沿顺时针方向绕q旋转,第一个碰到的点是哪一个。
如果p为凸包上的点,且Gift-Wrapping查询得到的点为p,则s中的其他点必在pq的同一侧,就是说,q也为凸包上的点,且pq为凸包上的一条线。由此,可以得到一种较简单的凸包算法:由s的最左点p1开始,循环进行Gift-Wrapping查询,将得到的点加入凸包,循环至查询到p1点为止。
将Gift-Wrapping查询引申到递增式策略,可以得到复杂度更小的算法:
- 将所有点由左至右排序,得p1, p2, … , pn,
- 由p1出发,一次遍历连接点,当出现V型时,去掉下部的点,直接连接上部的点。
- 遍历至pn,可得到凸包的上半部分。
- 反过来由pn遍历至p1,与(2)部原理相同,可得到凸包的下半部分。
如果直接将二维情况扩展到三维,则Gift-Wrapping查询应该是给定一个凸包上的面和一条边,求面绕边碰到的第一个点,不断利用Gift-Wrapping查询扩展也可构造三维凸包
2.2 分治法
2.1.1 基本分治法
分治法是一种很基础的算法。基本思路是将问题分解为等价的几个子问题,对子问题进行递归分解和求解,然后将子问题的解合成为所求的解。
由此,可以得到一种最简单的凸包分治算法:将点集依照某种划分方法分为N部分,对每个部分求子凸包,最后将几个子凸包合成一个更大的凸包。
这样的算法有两个优势:
首先,在计算子凸包时,可以去除很多已经在子凸包内的点,这种情况在点集很大时非常有效。
其次,需要合并的本身已为凸包,如果选择了合适的划分方式,则可以更快得合并。
这类的算法具体实现方式有许多。如M2M[10]算法,在二维平面上以栅格形式划分点集,并且在预处理时已经建立起了多分辨率式的映射关系,所以成块地删除和合并点集操作非常快