计算几何之凸包

一、什么是凸包?

假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。

当这个多边形是凸多边形的时候,我们就叫它“凸包”。

二、凸包问题

我们把这些点放在二维坐标系里面,那么每个点都能用 (x,y) 来表示。 
现给出点的数目和各个点的坐标。求构成凸包的点?

三、Graham扫描法

1、基本思路

(1)找到在平面中最左下方的那个点 p0;(先找纵坐标最小的点)

(2)计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。

        当 α 相同时,距离 P0 比较近的排在前面。

       我们由几何知识可以知道,结果中第一个点和最后一个点一定是凸包上的点。

(3)建立一个栈,初始时 P0 P1 进栈,对于 P[3..n-1]的每个点,若栈顶的两个点与它不构成

       "向左转"的关系,则将栈顶的点出栈,直至没有点需要出栈以后将当前点进栈; 

2、代码实现


#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;

struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
};

typedef Point Vector ;

Vector operator + (Vector A,Vector B)
{
    return Vector(A.x+B.x,A.y+B.y);
}

Vector operator - (Point A,Point B)
{
    return Vector((A.x-B.x),(A.y-B.y));
}

double Dot (Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}

double Length(Vector A)
{
    return sqrt(Dot(A,A));
}

double Angle(Vector A,Vector B)
{
    return acos(Dot(A,B)/Length(A)/Length(B));
}

double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}

double Area2(Point A,Point B,Point C)
{
    return Cross(B-A,C-A);
}

Point P[1005];
int stack[1005],top;

bool cmp(Point A,Point B)
{
    Vector AA=A-P[0];
    Vector BB=B-P[0];
    double ans=Cross(AA,BB);
    if(ans>0) return true;
    else if(ans==0)
    {
        if(A.x<B.x) return true;
        else return false;
    }
    else return false;
}

void init(int n)
{
    int k;
    Point P0;
    scanf("%lf%lf",&P[0].x,&P[0].y);
    P0=P[0];
    k=0;
    for(int i=1;i<n;i++)
    {
        scanf("%lf%lf",&P[i].x,&P[i].y);
        if( (P0.y>P[i].y) || (P[i].x<P0.x&&P0.y == P[i].y) )
        {
            P0=P[i];
            k=i;
        }
    }
    P[k]=P[0];
    P[0]=P0;
    sort(P+1,P+n,cmp);

}

void Graham(int n)
{
    if(n==1) {top=0;stack[0]=0;}
    if(n==2)
    {
        top=1;
        stack[0]=0;
        stack[1]=1;
    }
    if(n>2)
    {
        top=1;
        stack[0]=0;
        stack[1]=1;
        for(int i=2;i<n;i++)
        {
            while(top>0&&Cross(P[stack[top]]-P[stack[top-1]],P[i]-P[stack[top-1]])<=0)
            top--;
            top++;
            stack[top]=i;
        }
    }
}
posted @ 2017-01-17 14:19  邻家那小孩儿  阅读(197)  评论(0编辑  收藏  举报