Lflame

两圆面积交

    终于写了一遍了。 模板题 :codevs 3273

    其实很简单 !

    

    首先,判两个圆外离和内含的情况,外离(和外切)返回0,内含(和内切)返回小圆面积。

    现在,我们再来考虑两个圆相交的情况。如下图,于是我们用两个扇形加起来再减去三角形面积,乘以二就是答案。

    为什么要只算一半呢 ?  因为这样不用判断选择哪一边的扇形,可以把交的面积大于小圆面积一半的情况一起考虑,很方便。

    (不知道为什么...总是觉得自己画得好奇怪...)

    

codevs 3273的代码:

#include<iostream>

#include<cmath>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;


struct Points{

double x,y;

Points(double _x=0,double _y=0){

x=_x , y=_y ;

}

}o1,o2;


typedef Points Vectors ;


Vectors operator-(const Points &a,const Points &b) { return Vectors(a.x-b.x,a.y-b.y); }


Vectors operator+(const Vectors &a,const Vectors &b) { return Vectors(a.x+b.x,a.y+b.y) ; }


Vectors operator*(const double &a,const Vectors &b) { return Vectors(a*b.x,a*b.y) ; }


inline double det(const Vectors &a,const Vectors &b) { return a.x*b.y-a.y*b.x ; }


inline double dot(const Vectors &a,const Vectors &b) { return a.x*b.x+a.y*b.y ; }


inline double get_dis(const Points &a,const Points &b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)) ; }


inline Vectors rev(const Vectors &a,const double &ang) { return Vectors(a.x*cos(ang)-a.y*sin(ang),a.x*sin(ang)+a.y*cos(ang)) ; }


inline double get_len(const Vectors &a) { return sqrt(a.x*a.x+a.y*a.y) ; }


int sgn(const double &a)

{

if(fabs(a)<1e-8)return 0 ;

if(a>0)return 1;

return -1;

}


const double Pi=acos(-1) ;

double r1,r2 ;


inline double get_area(const double &r,const double &ang) //得到扇形面积

{

return ang*r*r/2 ;

}


double circle_intersection() //圆面积交

{

if(sgn(r1-r2)<0)swap(r1,r2) , swap(o1,o2) ;

double t_dis=get_dis(o1,o2) ;

if(sgn(t_dis-(r1-r2))<=0){ return Pi*r2*r2 ; }

if(sgn(t_dis-(r1+r2))>=0)   return 0 ;

double ang1=acos((t_dis*t_dis+r1*r1-r2*r2)/(2*r1*t_dis)) , ang2=acos((t_dis*t_dis+r2*r2-r1*r1)/(2*r2*t_dis)) ;

Vectors vec=rev((o2-o1),ang1) ;

vec=(r1/get_len(vec))*vec ;

double ret=get_area(r1,ang1) + get_area(r2,ang2) - fabs(det(o2-o1,vec)/2);

return 2*ret ;

}


int main()

{

scanf("%lf%lf%lf%lf%lf%lf",&o1.x,&o1.y,&r1,&o2.x,&o2.y,&r2) ;

printf("%.3f\n",circle_intersection()) ;

return 0 ;

}


评论

热度(2)