题意:
给定四个顶点,求四面体的内心坐标和内切圆半径
思路:
完全不知道怎么做,但是我们有维基百科~~~
(粗体代表向量,例如a即向量OA)
体积:
如果建立恰当的坐标系统,使得原点与d顶点重合,即d=0的话,该式可以简化为:
内切圆半径:
外接圆半径(这次没用到,先贴一下):
内心:
内心的计算返回一个点
外心(a^2为标量,即a的模的平方):
点积(Dot Product):
也可以表示成矩阵乘法:
叉积(Cross Product):
几何意义:
计算:
另外,三角形面积也可以用海伦公式求,(半径等于体积的三倍除以各个面面积之和)
,
其中
为了简化编码,可以用运算符重载(一般二元运算符用友元函数,一元用类内函数,我是乱写的别理我。。)
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=1e5+50;
const int Mod=1e9+7;
const double PI=acos(-1);
const double eps=1e-8;
typedef long long ll;
using namespace std;
struct Point{
double x,y,z;
Point(){}
Point(double xx,double yy,double zz){
x=xx; y=yy; z=zz;
}
Point operator+(const Point&rhs)const{
return Point(x+rhs.x,y+rhs.y,z+rhs.z);
}
Point operator-(const Point&rhs)const{
return Point(x-rhs.x,y-rhs.y,z-rhs.z);
}
//zoom Point s=s*2.0
//not working in reversed multiply
Point operator*(double ratio){
return Point(x*ratio,y*ratio,z*ratio);
}
Point operator/(double ratio){
return Point(x/ratio,y/ratio,z/ratio);
}
//dot product
double operator*(const Point&rhs)const{
return x*rhs.x+y*rhs.y+z*rhs.z;
}
//cross product
Point operator^(const Point&r){
return Point(
y*r.z-z*r.y,
z*r.x-x*r.z,
x*r.y-y*r.x
);
}
double len(){
return sqrt(x*x+y*y+z*z);
}
};
//四面体体积
double calVolume(Point a,Point b,Point c){
Point bc=b^c,ca=c^a,ab=a^b;
double ret=a*(b^c)/6;
return ret;
}
//四面体内切圆半径
double calRadius(Point a,Point b,Point c){
Point bc=b^c,ca=c^a,ab=a^b;
double v6=calVolume(a,b,c)*6;
double fm=bc.len()+ca.len()+ab.len()+(bc+ca+ab).len();
return fabs(v6/fm);
}
//四面体内心
Point calCenter(Point a,Point b,Point c){
Point bc=b^c,ca=c^a,ab=a^b;
Point fz=a*bc.len()+b*ca.len()+c*ab.len();
double fm=bc.len()+ca.len()+ab.len()+(ab+ca+bc).len();
return fz/fm;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
Point s[4];
while(~scanf("%lf %lf %lf",&s[0].x,&s[0].y,&s[0].z)){
for(int i=1;i<4;i++){
scanf("%lf %lf %lf",&s[i].x,&s[i].y,&s[i].z);
//规格化(以s[0]为原点)
s[i]=s[i]-s[0];
}
Point &a=s[1],&b=s[2],&c=s[3];
double check=(a^b)*c;
if (fabs(check)<eps) puts("O O O O");
else{
double radius=calRadius(a,b,c);
Point center=calCenter(a,b,c);
//加上坐标系偏移量
center=center+s[0];
printf("%.4f %.4f %.4f %.4f\n", center.x,center.y,center.z,radius);
}
}
return 0;
}