Intersection(xyiyy 2014年亚洲区域赛北京赛区现场赛)(数学几何方向)

Matt is a big fan of logo design. Recently he falls in love with logo made up by rings. The following figures are some famous examples you may know. 
 


A ring is a 2-D figure bounded by two circles sharing the common center. The radius for these circles are denoted by r and R (r < R). For more details, refer to the gray part in the illustration below. 
 


Matt just designed a new logo consisting of two rings with the same size in the 2-D plane. For his interests, Matt would like to know the area of the intersection of these two rings.

Input

The first line contains only one integer T (T ≤ 10 5), which indicates the number of test cases. For each test case, the first line contains two integers r, R (0 ≤ r < R ≤ 10). 

Each of the following two lines contains two integers x i, y i (0 ≤ x i, y i ≤ 20) indicating the coordinates of the center of each ring.

Output

For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the area of intersection rounded to 6 decimal places. 

Sample Input

2 2 3 0 0 0 0 2 3 0 0 5 0

Sample Output

Case #1: 15.707963 Case #2: 2.250778

题意:

题目让你输入的是两个圆环的圆心坐标,和一个圆环中的大半径和小半径,然后求出交叉的面积

我们来先构建一个两个不同半径的相交圆的面积求和:

左边大圆的半径为r1,右边小圆的半径为r2;

把左半部分记为s1,右半部分记为s2,总面积为s,中间的面积为s-s1-s2;

左边三角形的余弦值为:acos((r1*r1+d*d-r2*r2)/(2.0*r1*d));

右边三角形的余弦值为:acos((r2*r2+d*d-r1*r1)/(2.0*r2*d));

直接这样引用好了:

思路 : 


利用圆心距判断 两个圆之间的位置关系 
当圆心距小于两圆半径之差时 两圆内含 
当圆心距等于两圆半径之差时 两圆内切 
当圆心距小于两圆半径之和 大于半径之差时 两圆相交 
当圆心距等于两圆半径之和时 两圆外切 
当圆心距大于两圆半径之和时 两圆外离 
分三种情况讨论: 
假设半径小的圆为c1,半径大的圆为c2。 
c1的半径r1,圆心坐标(x1,y1)。c2的半径r2,圆心坐标(x2,y2)。 
d为两圆圆心连线的长度。 
相交面积为S 
d=sqrt((x1-x2)^2+(y1-y2)^2) 
(1)如果r1+r2<=d 
那么两圆相离,相交面积S=0 
(2)如果r2-r1>=d 
那么半径小的圆内含半径大的圆,那么相交面积为小圆的面积S=pi*r1*r1 
(3)既非(1)也非(2) 
在图上画两个相交圆,结合图像看。 
那么两圆相交,连接小圆的圆心与两个圆的交点,连接大圆的圆心和两个圆的交点。 
可以发现形成的图形被两个圆心的连线平分成2个全等三角形。 
由小圆圆心和交点所连两条线(长度为半径)以及在大圆之内的弧所形成的扇形为S1 
由大圆圆心和交点所连两条线(长度为半径)以及在小圆之内的弧所形成的扇形为S2 
由小圆圆心和交点所连两条线以及由大圆圆心和交点所连两条线所形成的四边形的面积为S3 
可见相交面积S=S1+S2-S3 
要求出扇形的面积,要知道扇形的圆心角。 
小圆包含的扇形的圆心角为2*a1(考虑一个三角形) 
a1=acos((r1^2+d^2-r2^2)/(2.0*r1*d)) 余弦定理 
a2=acos((r2^2+d^2-r1^2)/(2.0*r2*d)) 
S1=pi*r1*r1*2*a1/(2*pi)=a1*r1*r1 
同理 
S2=a2*r2*r2 
S3为一个三角形面积的2倍 
S3=2*r1*d*sin(a1)/2=r1*d*sin(a1) 
则S=a1*r1*r1+a2*r2*r2-r1*d*sin(a1)

代码:

#include<bits/stdc++.h>
using namespace std;
#define PI acos(-1.0)
double area(double x1,double y1,double r1,double x2,double y2,double r2)
{
    double d=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    if(d>=(r1+r2)*(r1+r2))return 0;
    if(d<=(r1-r2)*(r1-r2))return r1<r2 ? PI*r1*r1 : PI*r2*r2;
    d=sqrt(d);
    double a1=acos((r1*r1+d*d-r2*r2)/(2.0*r1*d));//表示第一个小圆的余弦值 
    double a2=acos((r2*r2+d*d-r1*r1)/(2.0*r2*d));//表示第二个大圆的余弦值 
    double s1=a1*r1*r1;//表示第一个扇形的面积 
    double s2=a2*r2*r2;//表示第二个扇形的面积 
    double t=r1*d*sin(a1);//表示整体相交的四边形面积 
    return s1+s2-t;
}
int main()
{
    int t;//表示测试用例的数量 
    double r1,r2,x1,y1,x2,y2;//分别表示两个圆的圆心坐标和两个圆的半径 
    scanf("%d",&t);
    int cas=1;//用来计数 
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf%lf",&r1,&r2,&x1,&y1,&x2,&y2);
        double ans=0;
        ans-=area(x1,y1,r2,x2,y2,r1)*2;//一个大圆与一个小圆相交区域 
        ans+=area(x1,y1,r2,x2,y2,r2);//两个小圆相交区域 
        ans+=area(x1,y1,r1,x2,y2,r1);//两个大圆相交区域 
        printf("Case #%d: ",cas++);
        printf("%.6lf\n",ans);
    }
    return 0;
}


 

猜你喜欢

转载自blog.csdn.net/rnzhiw/article/details/81705867