poj 2546 Circular Area

Circular Area
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 5763 Accepted: 2255

Description

Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three digits after decimal point.

Input

In the single line of input file there are space-separated real numbers x1 y1 r1 x2 y2 r2. They represent center coordinates and radii of two circles.

Output

The output file must contain single real number - the area.

Sample Input

20.0 30.0 15.0 40.0 30.0 30.0

Sample Output

608.366

Source

Northeastern Europe 2000, Far-Eastern Subregion


题意:求两个圆的公共面积


两圆相交求公共弦长公式:

已知两个圆的半径,两个圆心的距离,在相交情况下

假设两个半径分别是a,b,圆心距是c
那么公共弦的长度是--------sqrt((a+b+c)(a+b-c)(a+c-b)(b+c-a))/c

(a+b+c)(a+b-c)(a+c-b)(b+c-a)的乘积开根号,然后再除以c


海伦公式:

S=sqrt(p(p-a)(p-b)(p-c))


#include<iostream>
#include<cstdio>
#include<cmath>

const double pi=acos(-1.0);

struct POINT
{
    double x;
    double y;
    POINT():x(0),y(0) {};
    POINT(double _x_,double _y_):x(_x_),y(_y_) {};
};

struct Circular
{
    POINT O;
    double r;
};

double Distance(const POINT &a,const POINT &b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double pub_area(double r,double pub_ch)                         //通过扇形面积减去三角形面积求公共面积(有两部分)
{
    double p=0.5*(r+r+pub_ch);
    double S_tri=sqrt(p*(p-r)*(p-r)*(p-pub_ch));              //海伦公式计算三角形面积
    double angle=acos((2*r*r-pub_ch*pub_ch)/(2*r*r));        //通过余弦定理计算出公共弦对应的圆心角(acos()函数计算出来的值为弧度制)
    double S_sector=0.5*angle*r*r;                         //计算出扇形面积
    return S_sector-S_tri;
}

bool isAcute_angle(double r1,double r2,double o_dis)               //判断是不是锐角
{
    return acos((r2*r2+o_dis*o_dis-r1*r1)/(2*r2*o_dis))<pi/2;
}

int main()
{
    //freopen("in.txt","r",stdin);
    Circular a,b;
    while(~scanf("%lf%lf%lf%lf%lf%lf",&a.O.x,&a.O.y,&a.r,&b.O.x,&b.O.y,&b.r))
    {
        bool ar_min=true;
        double maxn_r;
        if(a.r>b.r)
        {
            ar_min=false;
            maxn_r=a.r;
        }
        else
        {
            maxn_r=b.r;
        }
        double O_dis=Distance(a.O,b.O);                                                  
        double pub_chord=sqrt((a.r+b.r+O_dis)*(a.r+b.r-O_dis)*(a.r+O_dis-b.r)*(b.r+O_dis-a.r))/O_dis;          //公共弦长
        if(a.r>=b.r&&a.r>=b.r+O_dis)                                          //圆b在圆a内
        {
            printf("%.3f\n",b.r*b.r*pi);                        
            continue;
        }                                                                 
        if(b.r>a.r&&b.r>=a.r+O_dis)
        {
            printf("%.3f\n",a.r*a.r*pi);
            continue;
        }
        if(O_dis>=a.r+b.r)                           //两圆不相交
        {
            printf("0.000\n");
            continue;
        }
        if(maxn_r>O_dis)                    //两圆相交时
        {
            if(ar_min&&isAcute_angle(b.r,a.r,O_dis))
            {
                printf("%.3f\n",pub_area(a.r,pub_chord)+pub_area(b.r,pub_chord));
            }
            if(!ar_min&&isAcute_angle(a.r,b.r,O_dis))
            {
                printf("%.3f\n",pub_area(a.r,pub_chord)+pub_area(b.r,pub_chord));
            }
            if(ar_min&&!isAcute_angle(b.r,a.r,O_dis))
            {
                printf("%.3f\n",a.r*a.r*pi-(pub_area(a.r,pub_chord)-pub_area(b.r,pub_chord)));
            }
            if(!ar_min&&!isAcute_angle(a.r,b.r,O_dis))
            {
                printf("%.3f\n",b.r*b.r*pi-(pub_area(b.r,pub_chord)-pub_area(a.r,pub_chord)));
            }
        }
        else
        {
            printf("%.3f\n",pub_area(a.r,pub_chord)+pub_area(b.r,pub_chord));
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值