求两个球的体积交或者并
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double pi=acos(-1.);
struct point3{
double x, y, z;
};
struct sph{
point3 c;
double r;
void read(){
scanf("%lf%lf%lf%lf", &c.x, &c.y, &c.z, &r);
}
};
double dist(point3 a, point3 b){
return sqrt(pow(a.x-b.x, 2.)+pow(a.y-b.y, 2.)+pow(a.z-b.z, 2.));
}
//计算球的体积
double sphArea(sph s){
return 4*pi*s.r*s.r*s.r/3;
}
//计算到s的球心的距离为d的平面横截求s得到的小球冠的体积
double crownArea(sph s, double d){
return pi*(s.r*s.r*(s.r-d)-(s.r*s.r*s.r-d*d*d)/3);
}
//计算三角形面积的平方,输入三边长
double trianArea(double a,double b,double c){
double s=(a+b+c)/2;
return s*(s-a)*(s-b)*(s-c);
}
//求两个求相交部分的体积
double interArea(sph a, sph b){
if(a.r>b.r) swap(a, b);
double d=dist(a.c, b.c);
if(d+a.r<=b.r) return sphArea(a);
if(d>=a.r+b.r) return 0.;
double ans=0., s, h, tmp;
s=trianArea(a.r, b.r, d);
h=4*s/(d*d);
tmp=crownArea(a, sqrt(a.r*a.r-h));
if(a.r*a.r+d*d-b.r*b.r<0.) tmp=sphArea(a)-tmp;
ans+=tmp;
tmp=crownArea(b, sqrt(b.r*b.r-h));
if(b.r*b.r+d*d-a.r*a.r<0.) tmp=sphArea(b)-tmp;
ans+=tmp;
return ans;
}
int main(){
//freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
sph a, b;
while(t--){
a.read();
b.read();
double ans=sphArea(a)+sphArea(b)-interArea(a, b);
printf("%.2lf\n", ans);
}
return 0;
}