求凸包或者闭包的顺序

343 阅读2分钟

 已知一个多边形N有点A,B,C,D,E,F,G,H组成,切多边形的凹凸性不确定,如何判断多边形的方向呢。

\

如果多边形为凸多边形,则判断方法很简单,只需要取出顺序的三个点,如:A,B,C 三点,计算向量AB,BC的叉乘,得到的结果如果大于0,则表示C点在AB的左侧,多边形的顶点是顺时针序,这样也能判断该凸多边形为顺时针序,反之,则为逆时针序。

              

     上述方法只适合于凸多边形,若为凹多边形则判断会出错,因为当选择的点刚好为凹点的时候,结果刚好与上述相反,

  比如选择了C点作为顶点来判断,BC,CD的叉乘结果

此时,我们就需要选择好用来判断的点。

\

             解决方法为:选择多边形的凸点进行判断,选择该凸点的前一个和后一个点按上述方法判断,这样判断结果依然正确。

 为了简单,凸点的选择可以选取X或者Y值中最大或者最小的点,这个点必然是凸点。

\

叉乘:矢量P(X1,Y1),矢量Q(X2,Y2),则PxQ=X1*Y2-X2*Y1

\

若PxQ>0,则P在Q的顺时针方向

若PxQ<0,则P在Q的逆时针方向

若PxQ=0,则P和Q共线,但可能同向也可能反向

题目链接:www.nowcoder.com/acm/contest…

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define ls 2*rt
#define rs 2*rt+1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define ll long long
using namespace std;
typedef pair<int,int> pii;
const ll inf = 0x3f3f3f3f;
/*void dis(int a[], int n){
    printf("总数为%d个\n",n);
    for(int i = 0; i < n; i++)   cout<<a[i]<<", ";
    cout<<endl<<"------------------"<<endl;      
}*/
 
const int mx = 0;
 
  
int x[100],y[100];
 
int main(){
    //int T=10;
 
    int n;
    scanf("%d",&n);
    int max_x = - 2000,max_y=-2000,id_x,id_y;
    for(int i = 0; i < n; i++){
        scanf("%d%d",x+i,y+i);
        if(x[i] > max_x){
            max_x = x[i];
            id_x = i;
        }
        if(y[i] > max_y){
            max_y = y[i];
            id_y = i;
        }
         
    }
 
     
//  int f = (x[2]-x[1])*(y[3]-y[2])-(y[2]-y[1])*(x[3]-x[2]);
    int f= (x[id_x]-x[id_x-1+n%n])*(y[id_x+1%n]-y[id_x]) - (x[id_x+1%n]-x[id_x])*(y[id_x]-y[id_x-1+n%n]);  
 
    if(f== 0){
        f= (x[id_y]-x[id_y-1+n%n])*(y[id_y+1%n]-y[id_y]) - (x[id_y+1%n]-x[id_y])*(y[id_y]-y[id_y-1+n%n]);
    }
     
    if(f < 0)
        puts("clockwise");
     
    else{
        puts("counterclockwise");
    }
     
    return 0;
}

\

本文已参与「新人创作礼」活动,一起开启掘金创作之路