几何模板

1:圆的k次交面积(n个圆,area[i]代表被覆盖i次及以上的面积)

#include<bits/stdc++.h>
using namespace std;
#define maxn 1010
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1);
int n;
double sqr(double x){//平方
    return x*x;
}
int dcmp(double x){//判断与0的大小关系,小于0返回-1,大于0返回1,等于0返回0
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
struct Circle{//
    double x,y,r,angle;
    int d;
    Circle(){d = 1;}
    Circle(double _x,double _y,double _angle=0,int t=0){
        x=_x; y=_y; angle=_angle; d=t;
    }
    void get(){
        scanf("%lf%lf%lf",&x,&y,&r);
    }
};
Circle cir[maxn],tp[maxn<<1];
double area[maxn];//area[i]代表覆盖i次及以上的面积
double dis(Circle a,Circle b){
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
double cross(Circle p0,Circle p1,Circle p2){
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool Cir_inter_Cir(Circle c1,double r1,Circle c2,double r2,Circle &p1,Circle &p2){
    double d=dis(c1,c2);
    if(d<fabs(r1-r2)-eps || d>r1+r2+eps) return false;
    double cosa=(r1*r1+d*d-r2*r2)/(2*r1*d);
    double sina=sqrt(max(0.,1.-cosa*cosa));
    p1=c1; p2=c1;
    p1.x+=r1/d*((c2.x-c1.x)* cosa+(c2.y-c1.y)*-sina);
    p1.y+=r1/d*((c2.x-c1.x)* sina+(c2.y-c1.y)* cosa);
    p2.x+=r1/d*((c2.x-c1.x)* cosa+(c2.y-c1.y)* sina);
    p2.y+=r1/d*((c2.x-c1.x)*-sina+(c2.y-c1.y)* cosa);
    return true; 
}
bool circmp(const Circle& u,const Circle& v){
    return dcmp(u.r-v.r)<0;
}
bool cmp(const Circle& u,const Circle& v){
    if(dcmp(u.angle-v.angle)) return u.angle<v.angle;
    return u.d>v.d;
}
double calc(Circle cir,Circle cp1,Circle cp2){
    double ans=(cp2.angle-cp1.angle)*sqr(cir.r)-cross(cir,cp1,cp2)+cross(Circle(0,0),cp1,cp2);
    return ans/2;
}
void CirUnion(Circle cir[],int n){
    Circle cp1,cp2;
    sort(cir,cir+n,circmp);
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)
            if(dcmp(dis(cir[i],cir[j])+cir[i].r-cir[j].r)<=0) cir[i].d++;
    for(int i=0;i<n;i++){
        int tn=0,cnt=0;
        for(int j=0;j<n;j++){
            if(i==j) continue;
            if(!Cir_inter_Cir(cir[i],cir[i].r,cir[j],cir[j].r,cp2,cp1)) continue;
            cp1.angle=atan2(cp1.y-cir[i].y,cp1.x-cir[i].x);
            cp2.angle=atan2(cp2.y-cir[i].y,cp2.x-cir[i].x);
            cp1.d=1;  tp[tn++]=cp1;
            cp2.d=-1; tp[tn++]=cp2;
            if(dcmp(cp1.angle-cp2.angle)>0) cnt++;
        }
        tp[tn++]=Circle(cir[i].x-cir[i].r,cir[i].y,PI,-cnt);
        tp[tn++]=Circle(cir[i].x-cir[i].r,cir[i].y,-PI,cnt);
        sort(tp,tp+tn,cmp);
        int p,s=cir[i].d+tp[0].d;
        for(int j=1;j<tn;j++){
            p=s; s+=tp[j].d;
            area[p]+=calc(cir[i],tp[j-1],tp[j]);
        }
    }
}
int main(){
    int T;
  cin >> T;
  while(T--){
    cin >> n;
    for(int i = 0;i < n;i++){
      cir[i].get();
    }
    memset(area,0,sizeof(area));
    CirUnion(cir,n);
    for(int i = 1;i <= n;i++)cout << area[i] << endl;
  }
    return 0;
}
View Code

 

posted @ 2019-10-31 16:48  cherish__lin  阅读(187)  评论(0编辑  收藏  举报