[计算几何]凸包算法


 
/*
凸包算法总结:
凸包是指覆盖平面坐标系内若干点的面积最小的凸多边形。求凸包的第一步是确定:凸包的定点都在给定的点中。通过几何方法反证很容易得到这一结论。所以,只要从所有点中挑选若干正确的点,按顺序(顺时针或逆时针)排列,就相当与求得了凸包。一种简便的方法是"包裹法"(Gift-Wrapping)。将y坐标最低的点作为凸包的第一个顶点H1(易证,所有点中x或y坐标取到最大或最小值的点一定是凸包顶点之一)找到满足条件的点,该点与水平线的叉积为正且夹角最小,作为凸包的第二个点H2。再求与线段H1H2叉积为正且夹角最小的点,。。。。依此类推。
*/


// 计算几何中的凸包问题程序(graham算法)
#i nclude  < stdio.h >
#i nclude 
< stdlib.h >
#i nclude 
< math.h >
#define  MAXN 10000

/* 顶点的类型定义 */
typedef 
struct   {
    
double x;
    
double y;
    
double arCos;
}
Point1;
int  n;      //  顶点的个数
Point1 points[MAXN];      //  顶点数组
int  stack[MAXN];   //  栈

/*主函数*/
int  main()
{
    
void Init();
    
void Make();
    Init();    
//程序数据的读入
    Make();    //程序算法过程
    while(1); 
    
return 0;
}


/*数据读入函数*/
void  Init()
{
    FILE 
*in;   // 采用读文件的方式,读入数据
    int i;
    
in = fopen("281.txt""r");
    fscanf(
in"%d"&n);
    
for(i = 0; i < n; ++i) 
        fscanf(
in"%lf%lf"&points[i].x, &points[i].y);
    fclose(
in);   // 关闭文件
}


/*算法实现函数*/
void  Make()
{
    
int Multi(Point1, Point1, Point1);   //计算两个向量的积
    double Angle(int);      //计算其余顶点与第一顶点的角度,为排序做准备
    void QSort(intint);     //对顶点进行快速排序
    void Swap(intint);      
    
int i, j, t;
    
double min = 32767.0;
    
for(i = 0; i < n; ++i){     //找第一个顶点,做为算法的起始顶点
        if(points[i].y < min) {
            j 
= i;
            min 
= points[i].y;
        }

    }

    Swap(
0, j);
    
for(i = 1; i < n; ++i){     //计算除第一顶点外的其余顶点到第一点的线段与x轴的夹角
        points[i].arCos = Angle(i);
    }

    QSort(
1, n-1);       //根据所得到的角度进行快速排序.
    for(i = 0; i <= 2++i) stack[i] = i;   //将前3个顶点压栈
    t = 2;
    
while(i < n) {
        
/*如果新的点,与最近入栈中的2点构成了一个"凹"角, 则将栈顶元素出栈. 直到把栈检查完*/
        
while(Multi(points[stack[t-1]], points[stack[t]], points[i]) && t >= 1)  
            t
--;     
        t
++;        // 将新点压栈
        stack[t] = i;
        i
++;
    }

    
/*打印结果*/
    
for(i = 0; i <=t; ++i) 
        printf(
"<%.2lf, %.2lf> ",points[stack[i]].x, points[stack[i]].y);
}

int  Multi(Point1 px, Point1 py, Point1 pz)
{
    
double k;
    k 
= (py.x-px.x)*(pz.y-py.y) - (pz.x-py.x)*(py.y-px.y);  // 计算两个向量的向量积,
    
// 判断3个点所成的角是不是一个"凹"角.
    if(k < 0return 1;
    
return 0
}


/*角度计算函数*/
double  Angle( int  i)
{
    
double j, k, m, n;
    j 
= fabs(points[i].x - points[0].x);
    k 
= fabs(points[i].y - points[0].y);
    m 
= sqrt(j*j+k*k);     //得到顶点i 到第一顶点的线段长度.
    n = acos(j/m);      //得到该线段与x轴的角度
    
//强悍
    return n;
}


void  QSort( int  top,  int  bot)
{
    
//快排
    int Loc(intint);
    
int pos;
    
    
if(top < bot) {
        pos 
= Loc(top, bot);
        QSort(top, pos
-1);
        QSort(pos
+1, bot);
    }

}


int  Loc( int  top,  int  bot)
{
    
void Swap(intint);
    
double x = points[top].arCos;
    
int j, k;
    j 
= top+1;
    k 
= bot;
    
while(1{
        
while(j < bot && points[j].arCos < x) j++;
        
while(k > top && points[k].arCos > x) k--;
        
        
if(j >= k) break;
        
        Swap(j, k);
    }

    Swap(top, k);
    
return k;
}


void  Swap( int  px,  int  py)
{
    Point1 k;
    k 
= points[px];
    points[px] 
= points[py]; //注意
    points[py] = k;
}


你可能感兴趣的:([计算几何]凸包算法)