您的位置:首页 > 其它

半平面交 求多边形内核问题

2015-07-22 22:33 162 查看
多边形的内核可以理解为:

在多边形找到一块区域,使这块区域中的任何一个点都能够和多边形上的任意一点相连而不受到多边形上其他边的阻挡

也可以抽象的理解为在这块区域中任意位置放一个旋转摄像头,这个摄像头可以监控多边形的整个区域

多边形内核是否存在可以利用半平面交的思想去求解

将多边形上的每一条边作为逆时针顺序的射线,在每一条线左侧的就是可行区域

譬如:

比如这个多边形

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;
#define N 1505
#define ll long long
#define eps 1e-9

int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}

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

typedef Point Vector;

struct Line{
Point p;
Vector v;
double ang;
Line(){}
Line(Point p , Vector v):p(p),v(v){ang = atan2(v.y , v.x);}
bool operator<(const Line &m) const{
return dcmp(ang-m.ang)<0;
}
}line
;

Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}

double Cross(Vector a , Vector b){return a.x*b.y-a.y*b.x;}

bool OnLeft(Line L , Point P)
{
return dcmp(Cross(L.v , P-L.p))>=0;
}

Point GetIntersection(Line a , Line b)
{
Vector u = a.p-b.p;
double t = Cross(b.v , u)/Cross(a.v , b.v);
return a.p+a.v*t;
}

int HalfplaneIntersection(Line *L , int n , Point *poly)
{
sort(L , L+n);
int first , last;
Point *p = new Point
;
Line *q = new Line
;
q[first=last=0] = L[0];
for(int i=1 ; i<n ; i++){
while(first<last && !OnLeft(L[i] , p[last-1])) last--;
while(first<last && !OnLeft(L[i] , p[first])) first++;
q[++last] = L[i];
if(fabs(Cross(q[last].v , q[last-1].v))<eps){
last--;
if(OnLeft(q[last] , L[i].p)) q[last]=L[i];
}
if(first < last) p[last-1] = GetIntersection(q[last-1] , q[last]);
}
while(first<last && !OnLeft(q[first] , p[last-1])) last--;
if(last-first<=1) return 0;
p[last] = GetIntersection(q[last] , q[first]);
int m=0;
for(int i=first ; i<=last ; i++) poly[m++] = p[i];
return m;
}

double calArea(Point *p , int n)
{
if(!n) return 0;
double ret = 0;
for(int i=2 ; i<n ; i++){
ret += Cross(p[i-1]-p[0],p[i]-p[0]);
}
return ret/2;
}

int main()
{
// freopen("in.txt" , "r" , stdin);
int T , n ;
scanf("%d" , &T);
while(T--)
{
scanf("%d" , &n);
for(int i=0 ; i<n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y);
p
= p[0];
for(int i=0 ; i<n ; i++) line[i] = Line(p[i] , p[i]-p[i+1]);
int cnt = HalfplaneIntersection(line , n , poly);
printf("%.2f\n" , calArea(poly , cnt));
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: