顾名思义,凸包就是把给定点包围在内部的、面积最小的凸多边形,它在计算几何中有着及其重要的作用。
这里介绍一下Andrew算法。
算法思想:首先把所有点按照x从小到大排序(如果x相同,按照y从小到大排序),删除重复点后得到序列p1,p2....然后把p1和p2放到凸包中。从p3开始,当新点在凸包前进方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边。重复这个过程,直到碰到最右边的pn,就求出了下凸包,然后反过来从pn开始再做一次,求出上凸包,合并起来就是完整的凸包。
这个算法在排序后仅仅是从左到右和从右到左各扫描了一次,时间复杂度为O(n)。加上排序后时间复杂度也仅为O(nlogn).
算法实现:
计算凸包,输入点数组p,个数为n,输出点数组ch。函数返回凸包顶点数。
函数执行完后输入点的顺序被破坏
如果不希望在凸包的边上有输入点,把两个<= 改成 <
在精度要求高的时建议用dcmp比较。
int ConvexHull(Point *p, int n, Point *ch)
{
int i, k, m;
sort(p, p+n); //先比较x座标,再比较y座标
n = unique(p, p+n) - p; //去除重复点
m = 0;
for(i = 0; i < n; i++)
{
while(m>1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) //至少有俩点,才能删点
m--;
ch[m++] = p[i];
}
k = m;
for(i = n-2; i >= 0; i--)
{
while(m>k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0)
m--;
ch[m++] = p[i];
}
if(n > 1) //如果n大于1,则最后数组中有两个p[0] 需要减少一个 n=1则不需要。
m--;
return m;
}