码迷,mamicode.com
首页 > 其他好文 > 详细

The area of the union of circles

时间:2015-03-28 14:27:03      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:圆的并

#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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!