zoj3500

求两个球的体积交或者并

#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;
}
 

你可能感兴趣的:(两个球的体积交,两个球的体积并)