标签:圆的并
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; const double eps=1e-8; const double PI=acos(-1.0); struct Circle{ double x,y,r; Circle(){} Circle(double xx,double yy){x=xx;y=yy;} }; struct Node{//入点+1,可以表示覆盖了多少层 double angle; int flag; Node(){} Node(double a,int b){angle=a;flag=b;} }; Circle c[1005]; Node p[2005]; double ss[100]; int n; double dist(Circle a,Circle b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int cmp(Circle a,Circle b){ return a.r<b.r; } void init(){ sort(c,c+n,cmp); int cnt; for(int i=1,j=0;i<n;i++){//去除被内切及内含的圆 if(c[i].x==c[j].x && c[i].y==c[j].y ||c[i].r<eps) continue; if((c[i].r-c[j].r)<dist(c[i],c[j])+eps) c[++j]=c[i]; cnt=j+1; } n=cnt; } void getarc(Circle p,Circle q,double &a,double &b){//a是小角,b是大角 double d=dist(p,q); double tmp1=acos((d*d+p.r*p.r-q.r*q.r)/(2*d*p.r)); double tmp2=atan2(q.y-p.y,q.x-p.x); a=tmp2-tmp1; b=tmp1+tmp2; if(b>PI) b-=2*PI; if(a<-PI) a+=2*PI; //printf("%lf %f\n",a,b); //printf(" %f\n",tmp2); } int cmp1(Node a,Node b){ if(a.angle!=b.angle) return a.angle<b.angle; else return a.flag>b.flag; } double cross(Circle a,Circle b){ return a.x*b.y-a.y*b.x; } double getarea(double a,double r){ return r*r*(a/2.0); } void solve(){ double area=0; for(int i=0;i<n;i++){ int cnt=0,flag=0; for(int j=0;j<n;j++){ if(i==j ||c[i].r+c[j].r<dist(c[i],c[j])+eps) continue;//不相交则直接跳过 double a,b; getarc(c[i],c[j],a,b); p[cnt++]=Node(a,1); p[cnt++]=Node(b,-1);//a是小角,b是大角 if(a>b) flag++;//记录圆的最左点被覆盖了多少次 } p[cnt++]=Node(-PI,flag); p[cnt++]=Node(PI,-flag); sort(p,p+cnt,cmp1); int s=flag+1;//+1是因为每段圆弧至少被c[i]这个圆覆盖 for(int j=1;j<cnt;j++){ if(s==1) {//被覆盖了1次及以上的面积 Circle a,b; a.x=c[i].x+c[i].r*cos(p[j-1].angle); a.y=c[i].y+c[i].r*sin(p[j-1].angle); b.x=c[i].x+c[i].r*cos(p[j].angle); b.y=c[i].y+c[i].r*sin(p[j].angle); double k=p[j].angle-p[j-1].angle; area+=(k-sin(k))*c[i].r*c[i].r*0.5;//弓形面积 area+=cross(a,b)*0.5;//有向面积 } s+=p[j].flag; } } printf("%f\n",area); } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++) scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r); init(); solve(); } return 0; }
The area of the union of circles
标签:圆的并
原文地址:http://blog.csdn.net/lj94093/article/details/44700313