Description
Given the co-ordinates of a circle and the lower left and upper right coordinate of an axis parallel rectangle, you have to find their common area. In the picture, the shaded area is their common area.
Input
Input starts with an integer T (≤ 4000), denoting the number of test cases.
Each case contains two lines, first line contains three integers x, y, r where (x, y) denotes the center of the circle and r denotes the radius. The next line contains four integers x1, y1, x2, y2 (x1<x2, y1<y2). All the integers are non-negative and not greater than 200.
Output
For each case, print the case number their common area. Errors less than 10-6 will be ignored.
Sample Input
3
1 1 10
2 2 5 5
1 1 10
20 20 30 30
1 1 5
0 1 8 8
Sample Output
Case 1: 9
Case 2: 0
Case 3: 24.6014178376
#include <cstdio>
#include<cstdlib>
#include<cstring>
#include <cmath>
using namespace std;
struct point
{
double x,y;
}a[55];
double r;
double dist_1point(double x0,double y0)
{
return sqrt(x0*x0+y0*y0);
}
double dist_2point(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double dist_line(double x1,double y1,double x2,double y2)
{
double A,B,C,dist;
A=y1-y2;
B=x1-x2;
C=x1*y2-x2*y1;
dist=fabs(C)/sqrt(A*A+B*B);
return dist;
}
double get_cos(double a,double b,double c)
{
double angel=(b*b+c*c-a*a)/(2*b*c);
return angel;
}
point get_point(double x0,double y0)
{
double k;
point temp;
if(x0!=0)
{
k=y0/x0;
temp.x=fabs(r)/sqrt(1+k*k);
if(x0<0) temp.x=-temp.x;
temp.y=k*temp.x;
}
else
{
temp.x=0;
if(y0>0) temp.y=r;
else temp.y=-r;
}
return temp;
}
int fi(double x1,double y1,double x2,double y2)
{
if (x1*y2-x2*y1>0) return 1;
else return -1;
}
double get_area(double x1,double y1,double x2,double y2)
{
int sign=fi(x1,y1,x2,y2);
double s;
double l=dist_line(x1,y1,x2,y2);
double a=dist_1point(x1,y1);
double b=dist_1point(x2,y2);
double c=dist_2point(x1,y1,x2,y2);
if(a==0 || b==0)
return 0;
if(a<=r && b<=r)
{
s=fabs(x1*y2-x2*y1)/2.0;
return s*sign;
}
else if(a>=r && b>=r && l>=r)
{
point t1=get_point(x1,y1);
point t2=get_point(x2,y2);
double d=dist_2point(t1.x,t1.y,t2.x,t2.y);
double sita1=acos(get_cos(d,r,r));
double s=fabs(sita1*r*r/2.0);
return s*sign;
}
else if(a>=r && b>=r && l<=r && (get_cos(a,b,c)<=0 || get_cos(b,a,c)<=0))
{
point t1=get_point(x1,y1);
point t2=get_point(x2,y2);
double d=dist_2point(t1.x,t1.y,t2.x,t2.y);
double sita=acos(get_cos(d,r,r));
s=fabs(sita*r*r/2.0);
return s*sign;
}
else if(a>=r && b>=r && l<=r && (get_cos(a,b,c)>0 && get_cos(b,a,c)>0))
{
double xx1,xx2,yy1,yy2;
if(x1!=x2)
{
double k12=(y1-y2)/(x1-x2);
double b12=y1-k12*x1;
double a0=(1+k12*k12);
double b0=(2*k12*b12);
double c0=(b12*b12-r*r);
xx1=(-b0+sqrt(b0*b0-4*a0*c0))/(2*a0);
yy1=k12*xx1+b12;
xx2=(-b0-sqrt(b0*b0-4*a0*c0))/(2*a0);
yy2=k12*xx2+b12;
}
else
{
xx1=x1;
xx2=x1;
yy1=sqrt(r*r-x1*x1);
yy2=-sqrt(r*r-x1*x1);
}
point t1=get_point(x1,y1);
point t2=get_point(x2,y2);
double d1=dist_2point(xx1,yy1,xx2,yy2);
double d2=dist_2point(t1.x,t1.y,t2.x,t2.y);
double sita1=acos(get_cos(d1,r,r));
double sita2=acos(get_cos(d2,r,r));
double s1=fabs(sita1*r*r/2.0);
double s2=fabs(sita2*r*r/2.0);
double s3=fabs(xx1*yy2-xx2*yy1)/2.0;
s=s2+s3-s1;
return s*sign;
}
else if(a>=r && b<=r)
{
double xxx,yyy;
if(x1!=x2)
{
double k12=(y1-y2)/(x1-x2);
double b12=y1-k12*x1;
double a0=(1+k12*k12);
double b0=(2*k12*b12);
double c0=(b12*b12-r*r);
double xx1=(-b0+sqrt(b0*b0-4*a0*c0))/(2*a0);
double yy1=k12*xx1+b12;
double xx2=(-b0-sqrt(b0*b0-4*a0*c0))/(2*a0);
double yy2=k12*xx2+b12;
if(x1<=xx1 && xx1<=x2 || x2<=xx1 && xx1<=x1) {xxx=xx1; yyy=yy1;}
else {xxx=xx2; yyy=yy2;}
}
else
{
double xx1=x1;
double yy1=-sqrt(r*r-x1*x1);
double yy2=sqrt(r*r-x1*x1);
if(y1<=yy1 && yy1<=y2 || y2<=yy1 && yy1<=y1) {yyy=yy1; xxx=xx1;}
else {yyy=yy2; xxx=xx1;}
}
point t1=get_point(x1,y1);
double ddd=dist_2point(t1.x,t1.y,xxx,yyy);
double sita1=acos(get_cos(ddd,r,r));
double s1=fabs(sita1*r*r/2.0);
double s3=fabs(xxx*y2-yyy*x2)/2.0;
s=s1+s3;
return s*sign;
}
else if(a<=r && b>=r)
{
double xxx,yyy;
if(x1-x2!=0)
{
double k12=(y1-y2)/(x1-x2);
double b12=y1-k12*x1;
double a0=(1+k12*k12);
double b0=(2*k12*b12);
double c0=(b12*b12-r*r);
double xx1=(-b0+sqrt(b0*b0-4*a0*c0))/(2*a0);
double yy1=k12*xx1+b12;
double xx2=(-b0-sqrt(b0*b0-4*a0*c0))/(2*a0);
double yy2=k12*xx2+b12;
if(x1<=xx1 && xx1<=x2 || x2<=xx1 && xx1<=x1) {xxx=xx1; yyy=yy1;}
else {xxx=xx2; yyy=yy2;}
}
else
{
double yy1=-sqrt(r*r-x1*x1);
double yy2=sqrt(r*r-x1*x1);
double xx1=x1;
if(y1<=yy1 && yy1<=y2 || y2<=yy1 && yy1<=y1) {yyy=yy1; xxx=xx1;}
else {yyy=yy2; xxx=xx1;}
}
point t1=get_point(x2,y2);
double ddd=dist_2point(t1.x,t1.y,xxx,yyy);
double sita1=acos(get_cos(ddd,r,r));
double s1=fabs(sita1*r*r/2.0);
double s3=fabs(xxx*y1-yyy*x1)/2.0;
s=s1+s3;
return s*sign;
}
else return 0;
}
int main()
{
int i,n,t,k=1;
double area;
scanf("%d",&t);
while(t--)
{
double xx,yy;
scanf("%lf%lf%lf",&xx,&yy,&r);
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
x1-=xx;x2-=xx;y1-=yy;y2-=yy;
a[0].x=x1;a[0].y=y1;
a[1].x=x2;a[1].y=y1;
a[2].x=x2;a[2].y=y2;
a[3].x=x1;a[3].y=y2;
a[4]=a[0]; area=0;
for(i=0;i<4;i++)
{
area+=get_area(a[i].x,a[i].y,a[i+1].x,a[i+1].y);
}
printf("Case %d: %.7lf\n",k++,fabs(area));
}
return 0;
}