#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
//(坐标、半径为-10000..10000)
const int chash=12343;
const double zero=1e-8;
int n,nodes;
double pi;
const int nSIZE=1010;
double x[nSIZE],y[nSIZE],r[nSIZE];
double ans;
double inter[nSIZE][3];
int link[10010],next[10010];
double node[10010][3];
int first[chash];
void initial()
{
int i;
pi=asin(1)*2;
scanf("%d",&n);
for (i=1; i<=n; i++)
scanf("%lf %lf %lf",&x[i],&y[i],&r[i]);
memset(first,0,sizeof(first));
memset(next,0,sizeof(next));
}
double sqrdist(double x1,double y1,double x2,double y2)
{
return pow(x1-x2,2)+pow(y1-y2,2);
}
double dist(double x1,double y1,double x2,double y2)
{
return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
}
void prepare()
{
int i,j;
bool b[nSIZE];
for (i=1; i<=n; i++)
b[i]=true;
for (i=1; i<=n; i++)
for (j=i+1; j<=n; j++)
if (x[i]==x[j] && y[i]==y[j] && r[i]==r[j])
{
b[i]=false;
break;
}
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
if (i!=j && r[i]+zero<r[j])
{
if (dist(x[i],y[i],x[j],y[j])<=r[j]-r[i])
{
b[i]=false;
break;
}
}
j=0;
for (i=1; i<=n; i++)
if (b[i])
{
j++;
x[j]=x[i];
y[j]=y[i];
r[j]=r[i];
}
n=j;
}
double getangle(double x,double y)
{
if (x<-zero) return atan(y/x)+pi;
else if (x>zero)
if (y>0) return atan(y/x);
else return atan(y/x)+pi*2;
else if (y>0) return pi/2 ;
else return pi*3/2;
}
void getcross(int i,int j,double &t1,double &t2)
{
double a,b,c,a1,b1,c1,x1,y1,x2,y2,t,l;
a=(x[i]-x[j])*2;
b=(y[i]-y[j])*2;
c=pow(r[j],2)-pow(r[i],2)+pow(x[i],2)-pow(x[j],2)+pow(y[i],2)-pow(y[j],2);
a1=b;
b1=-a;
c1=a1*x[i]+b1*y[i];
t=a*b1-b*a1;
x1=(c*b1-b*c1)/t;
y1=(a*c1-c*a1)/t;
l=sqrt(pow(r[i],2)-pow(x1-x[i],2)-pow(y1-y[i],2));
t=sqrt(pow(a1,2)+pow(b1,2));
x2=x1+l*a1/t;
y2=y1+l*b1/t;
x1=x1*2-x2;
y1=y1*2-y2;
t1=getangle(x1-x[i],y1-y[i]);
t2=getangle(x2-x[i],y2-y[i]);
if (t2<t1) t1=t1-pi*2;
t=(t1+t2)/2;
if (dist(x[j],y[j],x[i]+r[i]*cos(t),y[i]+r[i]*sin(t))>r[j])
{
t=t1;
t1=t2;
t2=t;
if (t2<zero) t2=t2+pi*2;
else t1=t1-pi*2;
}
}
void sort(int l,int r)
{
int i,j;
double k1,k2;
i=l;
j=r;
k1=inter[(l+r)>>1][1];
k2=inter[(l+r)>>1][2];
while (i<=j)
{
while ((inter[i][1]+zero<k1) || (fabs(inter[i][1]-k1)<zero) && (inter[i][2]>k2+zero)) i++;
while ((inter[j][1]>k1+zero) || (fabs(inter[j][1]-k1)<zero) && (inter[j][2]+zero<k2)) j--;
if (i<=j)
{
inter[0][1]=inter[i][1];
inter[i][1]=inter[j][1];
inter[j][1]=inter[0][1];
inter[0][2]=inter[i][2];
inter[i][2]=inter[j][2];
inter[j][2]=inter[0][2];
i++;
j--;
}
}
if (l<j) sort(l,j);
if (i<r) sort(i,r);
}
int getwhere(double x,double y)
{
int i,t;
t=((int)(fabs(x+y+zero)*100000))%chash;
i=first[t];
while (i!=0)
{
if ((fabs(node[i][1]-x)<zero)&&(fabs(node[i][2]-y)<zero))
{
return i;
}
i=next[i];
}
nodes++;
node[nodes][1]=x;
node[nodes][2]=y;
next[nodes]=first[t];
first[t]=nodes;
return nodes;
}
double getchord(double r,double a)
{
return pow(r,2)/2*(a-sin(a));
}
void getnode()
{
int i,j,k,top,t1,t2;
nodes=0;
for (i=1; i<=n; i++)
{
top=0;
for (j=1; j<=n; j++)
if ((i!=j) && (dist(x[i],y[i],x[j],y[j])+zero<r[i]+r[j]))
{
top++;
getcross(i,j,inter[top][1],inter[top][2]);
}
if (top>0)
{
sort(1,top);
k=0;
for (j=1; j<=top; j++)
if ((k==0)||(inter[j][1]>inter[k][2]))
{
k++;
inter[k][1]=inter[j][1];
inter[k][2]=inter[j][2];
}
else if (inter[j][2]>inter[k][2]) inter[k][2]=inter[j][2];
top=k;
while
((top>0)&&(inter[top][2]+zero>inter[1][1]+pi*2))
{
if (inter[top][1]-pi*2<inter[1][1])
inter[1][1]=inter[top][1]-pi*2;
top--;
}
if (top>0)
{
for (j=1; j<=top-1; j++)
{
ans=ans+getchord(r[i],inter[j+1][1]-inter[j][2]);
t1=getwhere(x[i]+r[i]*cos(inter[j+1][1]),y[i]+r[i]*sin(inter[j+1][1]));
t2=getwhere(x[i]+r[i]*cos(inter[j][2]),y[i]+r[i]*sin(inter[j][2]));
link[t1]=t2;
}
ans=ans+getchord(r[i],inter[1][1]+pi*2-inter[top][2]);
t1=getwhere(x[i]+r[i]*cos(inter[1][1]),y[i]+r[i]*sin(inter[1][1]));
t2=getwhere(x[i]+r[i]*cos(inter[top][2]),y[i]+r[i]*sin(inter[top][2]));
link[t1]=t2;
}
}
else ans=ans+pi*r[i]*r[i];
}
}
void work()
{
int i,j;
bool visited[10010];
ans=0;
getnode();
memset(visited,0,sizeof (visited));
for (i=1; i<=nodes; i++)
if (!visited[i])
{
j=i;
do
{
visited[j]=true;
ans=ans+(node[link[j]][1]*node[j][2]-node[j][1]*node[link[j]][2])/2;
j=link[j];
}
while (j!=i);
}
printf("%.6lf\n",ans);
}
int main()
{
initial();
prepare();
work();
return 0;
}
求圆面积并
最新推荐文章于 2023-06-07 01:39:31 发布