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; }