(HDU 5733)2016 Multi-University Training Contest 1 tetrahedron(几何)

题意:

给定四个顶点,求四面体的内心坐标和内切圆半径


思路:

完全不知道怎么做,但是我们有维基百科~~~

(粗体代表向量,例如a即向量OA)


体积:

V={\frac {1}{3}}A_{0}\,h\,


V={\frac {|(\mathbf {a} -\mathbf {d} )\cdot [(\mathbf {b} -\mathbf {d} )\times (\mathbf {c} -\mathbf {d} )]|}{6}}.

如果建立恰当的坐标系统,使得原点与d顶点重合,即d=0的话,该式可以简化为:

V={\frac {|\mathbf {a} \cdot (\mathbf {b} \times \mathbf {c} )|}{6}},

内切圆半径:


r={\frac {6V}{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|(\mathbf {b} \times \mathbf {c} )+(\mathbf {c} \times \mathbf {a} )+(\mathbf {a} \times \mathbf {b} )|}}\,



外接圆半径(这次没用到,先贴一下):


R={\frac {|\mathbf {a^{2}} (\mathbf {b} \times \mathbf {c} )+\mathbf {b^{2}} (\mathbf {c} \times \mathbf {a} )+\mathbf {c^{2}} (\mathbf {a} \times \mathbf {b} )|}{12V}}\,




内心:

\mathbf {I} ={\frac {|\mathbf {b} \times \mathbf {c} |\,\mathbf {a} +|\mathbf {c} \times \mathbf {a} |\,\mathbf {b} +|\mathbf {a} \times \mathbf {b} |\,\mathbf {c} }{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|\mathbf {b} \times \mathbf {c} +\mathbf {c} \times \mathbf {a} +\mathbf {a} \times \mathbf {b} |}}.\,


内心的计算返回一个点


外心(a^2为标量,即a的模的平方):



\mathbf {O} ={\frac {\mathbf {a^{2}} (\mathbf {b} \times \mathbf {c} )+\mathbf {b^{2}} (\mathbf {c} \times \mathbf {a} )+\mathbf {c^{2}} (\mathbf {a} \times \mathbf {b} )}{2\mathbf {a} \cdot (\mathbf {b} \times \mathbf {c} )}}.\,

点积(Dot Product):


\vec{a}\cdot \vec{b} = \sum_{i=1}^n a_ib_i = a_1b_1 + a_2b_2 + \cdots + a_nb_n

也可以表示成矩阵乘法:

{\displaystyle {\vec {a}}\cdot {\vec {b}}={\vec {a}}{\vec {b}}^{T}}  \begin{bmatrix} 1&3&-5\end{bmatrix}\begin{bmatrix} 4\\-2\\-1\end{bmatrix} = \begin{bmatrix} 3\end{bmatrix}

叉积(Cross Product):

几何意义:

计算:

{\displaystyle {\begin{aligned}\mathbf {a} \times \mathbf {b} &=(a_{2}b_{3}-a_{3}b_{2})\mathbf {i} +(a_{3}b_{1}-a_{1}b_{3})\mathbf {j} +(a_{1}b_{2}-a_{2}b_{1})\mathbf {k} \\&={\begin{vmatrix}\mathbf {i} &\mathbf {j} &\mathbf {k} \\a_{1}&a_{2}&a_{3}\\b_{1}&b_{2}&b_{3}\\\end{vmatrix}}\end{aligned}}}



另外,三角形面积也可以用海伦公式求,(半径等于体积的三倍除以各个面面积之和)

A={\sqrt  {s(s-a)(s-b)(s-c)}}

其中s={\frac {a+b+c}{2}}


为了简化编码,可以用运算符重载(一般二元运算符用友元函数,一元用类内函数,我是乱写的别理我。。)


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





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值