解题思路:
两圆相交分如下集中情况:相离、相切、相交、包含。
设两圆圆心分别是O1和O2,半径分别是r1和r2,设d为两圆心距离。又因为两圆有大有小。
相离相切的面积为零
d=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); if(d>=r1+r2) //相离或外切 return 0;
包含的面积就是小圆的面积了
if(r1>=d+r2) //内切或内含 return PI*r2*r2; if(r2>=d+r1) //内切或内含 return PI*r1*r1;
接下来看看相交的情况。
相交面积可以这样算:S=扇形O1AB - △O1AB + 扇形O2AB - △O2AB,
这两个三角形组成了一个四边形,可以用两倍的△O1AO2求得,
所以答案就是两个扇形-两倍的△O1AO2。
要求出扇形的面积,要知道扇形的圆心角。
小圆包含的扇形的圆心角为2*ang1 //ang1表示∠AO1O2=∠AO1E
ang1=acos((r1^2-r2^2+d^2)/(2*r1*d)) //ang1表示∠AO1O2 ,求法如上图下方公式所示。
ang2=acos((r2^2-r1^2+d^2)/(2*r2*d)) //ang2表示∠AO2O1
扇形O1AB面积=pi*r1*r1*2*∠AO1O2 / (2*pi)=ang1*r1*r1
同理:
扇形O2AB面积=ang2*r2*r2
两倍的△O1AO2=2*r1*d*sin(∠AO1O2)/2=r1*d*sin(ang1)
则S=ang1*r1*r1+ang2*r2*r2-r1*d*sin(ang1)
ang1=acos((r1*r1-r2*r2+d*d)/(2*r1*d)); //第一个圆心角的一半 ang2=acos((r2*r2-r1*r1+d*d)/(2*r2*d)); //第二个圆心角的一半 return ang1*r1*r1+ang2*r2*r2-r1*d*sin(ang1); //两个扇形面积之和-两倍的△O1AO2
参考代码:
#include <stdio.h> #include <math.h> #define PI acos(-1.0) double Area(double x1,double y1,double x2,double y2,double r1,double r2) { double d; double ang1,ang2; d=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); if(d>=r1+r2) //相离或外切 return 0; if(r1>=d+r2) //内切或内含 return PI*r2*r2; if(r2>=d+r1) //内切或内含 return PI*r1*r1; //两个圆相交情况 ang1=acos((r1*r1-r2*r2+d*d)/(2*r1*d)); //第一个圆心角的一半 ang2=acos((r2*r2-r1*r1+d*d)/(2*r2*d)); //第二个圆心角的一半 return ang1*r1*r1+ang2*r2*r2-r1*d*sin(ang1); //两个扇形面积之和-两倍的△O1AO2 } int main() { double x1,y1,x2,y2,r1,r2; double area; int n; scanf("%d",&n); while(n--) { scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&r1,&r2); area=Area(x1,y1,x2,y2,r1,r2); printf("%.3f\n",area); } return 0; }
0.0分
4 人评分
C语言程序设计教程(第三版)课后习题8.1 (C语言代码)浏览:1292 |
简单的for循环浏览:1495 |
WU-格式化数据输出 (C语言代码)浏览:1818 |
2003年秋浙江省计算机等级考试二级C 编程题(2) (C语言代码)浏览:638 |
C语言程序设计教程(第三版)课后习题9.6 (C语言代码)浏览:388 |
C语言程序设计教程(第三版)课后习题5.5 (C语言代码)浏览:590 |
sizeof的大作用 (C语言代码)浏览:1590 |
妹子杀手的故事 (C语言代码)浏览:1152 |
永远的丰碑 (C语言代码)浏览:608 |
C语言程序设计教程(第三版)课后习题6.9 (C语言代码)浏览:609 |