ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:

则相交部分的面积为5.233。

Input

第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

Output

    输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

凸多边形交转为半平面交

#include<cstdio>
#include<cmath>
#include<algorithm>
const double pi=acos(-1),_0=1e-5;
struct vec{double x,y;};
struct line{vec p,v;double a;
void cal(){
    if(v.y==0&&v.x<0)a=pi;
    else a=atan2(v.y,v.x);
}
};
vec operator+(vec a,vec b){return (vec){a.x+b.x,a.y+b.y};}
vec operator-(vec a,vec b){return (vec){a.x-b.x,a.y-b.y};}
vec operator*(vec a,double b){return (vec){a.x*b,a.y*b};}
double operator*(vec a,vec b){return a.x*b.y-b.x*a.y;}
bool operator<(line a,line b){return a.a<b.a;}
vec operator&(line a,line b){return a.p+a.v*((b.v*(a.p-b.p))/(a.v*b.v));}
bool chk(line a,vec b){return a.v*(b-a.p)>0;}
double ans=0;
int n,m;
line ls[1024],q[1024];
vec ps[1024];
int l=0,r=0,p=0;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&m);
        for(int i=0;i<m;i++){
            scanf("%lf%lf",&ps[i].x,&ps[i].y);
        }
        ps[m]=ps[0];
        for(int i=0;i<m;i++){
            ls[p].p=ps[i];
            ls[p].v=ps[i+1]-ps[i];
            ls[p].cal();
            p++;
        }
    }
    std::sort(ls,ls+p);
    q[0]=ls[0];
    for(int i=1;i<p;i++){
        while(l<r&&!chk(ls[i],q[r-1]&q[r]))--r;
        while(l<r&&!chk(ls[i],q[l]&q[l+1]))++l;
        q[++r]=ls[i];
        if(fabs(q[r].v*q[r-1].v)<_0){
            --r;
            if(chk(q[r],ls[i].p))q[r]=ls[i];
        }
    }
    while(l<r&&!chk(q[l],q[r-1]&q[r]))--r;
    if(r-l<=1){
        puts("0.000");
        return 0;
    }
    for(int i=l;i<r;i++)ps[i]=(q[i]&q[i+1]);
    ps[r]=(q[r]&q[l]);
    for(int i=l+1;i<r;i++)ans+=fabs((ps[i]-ps[l])*(ps[i+1]-ps[l]))*.5;
    printf("%.3lf\n",ans);
    return 0;
}

 

posted on 2016-06-28 09:28  nul  阅读(255)  评论(0编辑  收藏  举报