码迷,mamicode.com
首页 > 其他好文 > 详细

计算几何--凸包总结

时间:2016-12-26 18:26:35      阅读:271      评论:0      收藏:0      [点我收藏+]

标签:abs   poi   point   距离   else   div   line   wap   int   

计算几何凸包

       凸包:给你n个散落的点,让你求出最小的凸多边形将所有的点包括起来,或者点在边上。用到的算法是Graham

Graham算法:首先找到一个顶点作为基点,然后将这个点与其他点进行连线,然后按照角度的大小进行排序。

 

然后加点,第一个点肯定在凸多边形上,然后开始加点,每加一个点,要用向量的×积判断以前是不是有边在他的里面,如果有的话,就将这个点替换,这个过程是一个回溯的过程

 

首先找基点,纵坐标最小的一定在凸包上,如果纵坐标相等那么就选横坐标小的。

下面模拟一下Graham算法扫描的过程(截图来自HDU课件)

首相找到基点,很明显p0一定会在凸包上

技术分享        

然后将p0与其他各点相连,按照角度进行排序,排序的时候,不用求出来具体的角度,只需要利用向量的差乘的大小进行排序即可,然后按照角度的顺序进行加点

 技术分享

当加点p3后,发现向量p1p3在向量p2p3的外面,所以p2这个点肯定不在凸包上,所以删掉(这个过程是一个回溯的过程)

 技术分享

然后加点p4没有边在p3p4的外面,继续

 技术分享

加p5的时候,p3p5在p4p5的外面,所以p4这个点也不在凸包上面删掉

 技术分享

重复这个过程每次加点的时候,先要回溯一边,又没有边在要加的这条边的外面

……

最后找到了凸包

 技术分享

那用代码怎么来实现呐?

模板:

/****************************凸包模板*******************************/
const double eps = 1e-8;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    //叉积
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
};
struct Line { 
    Point s,e; 
    Line(){} 
    Line(Point _s,Point _e) {         
        s = _s; e = _e; 
    }
}; 
//*两点间距离
double dist(Point a,Point b)
{
    return sqrt((a-b)*(a-b));
}   
/*
* 求凸包,Graham算法
* 点的编号0~n-1
* 返回凸包结果Stack[0~top-1]为凸包的编号
*/
const int MAXN = 1010;
Point List[MAXN];
int Stack[MAXN];//用来存放凸包的点
int top;//表示凸包中点的个数
//相对于List[0]的极角排序
bool _cmp(Point p1,Point p2)
{
    double tmp = (p1-List[0])^(p2-List[0]);
    if(sgn(tmp) > 0)
        return true;
    else if(sgn(tmp) == 0 && sgn(dist(p1,List[0]) - dist(p2,List[0])) <= 0)
        return true;
    else 
        return false;
}
void Graham(int n)
{
    Point p0;
    int k = 0;
    p0 = List[0];
    //找最下边的一个点
    for(int i = 1;i < n;i++)
    {
        if( (p0.y > List[i].y) || (p0.y == List[i].y && p0.x > List[i].x) )
        {
            p0 = List[i];
            k = i;
        }
    }
    swap(List[k],List[0]);
    sort(List+1,List+n,_cmp);
    if(n == 1)
    {
        top = 1;
        Stack[0] = 0;
        return;
    }
    if(n == 2)
    {
        top = 2;
        Stack[0] = 0;
        Stack[1] = 1;
        return ;
    }
    Stack[0] = 0;
    Stack[1] = 1;
    top = 2;
    for(int i = 2;i < n;i++)
    {
        while(top > 1 && sgn((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0)
            top--;
        Stack[top++] = i;
    }
}
/****************************凸包模板*******************************/

 

 

计算几何--凸包总结

标签:abs   poi   point   距离   else   div   line   wap   int   

原文地址:http://www.cnblogs.com/wuwangchuxin0924/p/6223152.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!