HDU-5733-tetrahedron-计算几何

题意:题意很简单就是给你四个点,判断这四个点能不能组成四面体,如果能求出内切圆半径,和内切圆坐标。

思路:公式题

ans.x=(sa*A.x+sb*B.x+sc*C.x+sd*D.x)/ssum;

ans.y=(sa*A.y+sb*B.y+sc*C.y+sd*D.y)/ssum;

ans.z=(sa*A.z+sb*B.z+sc*C.z+sd*D.z)/ssum;


r可以通过v/ssum*3求得

v可以通过公式或者面和高来求得

#include<bits/stdc++.h>
using namespace std;
#define maxn 9999999
#define eps 1e-8
struct point3{
    double x,y,z;
};
///A,B两点作差
point3 cha(point3 A,point3 B) {
    point3 tt;
    tt.x=A.x-B.x;
    tt.y=A.y-B.y;
    tt.z=A.z-B.z;
    return tt;
}
///两点距离
double dis(point3 A,point3 B) {
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
}
///叉积
point3 cross(point3 A,point3 B) {
    point3 tt;
    tt.x=A.y*B.z-A.z*B.y;
    tt.y=A.z*B.x-A.x*B.z;
    tt.z=A.x*B.y-A.y*B.x;
    return tt;
}
///点积
double dot_product(point3 A,point3 B) {
    return A.x*B.x+A.y*B.y+A.z*B.z;
}
///三点共线
bool check(point3 A,point3 B,point3 C) {
    double disp[5];
    disp[0]=dis(A,B);
    disp[1]=dis(A,C);
    disp[2]=dis(B,C);
    sort(disp,disp+3);
    return fabs(disp[0]+disp[1]-disp[2])<eps;
}
///点面距离 D到A,B,C的面积
double disDM(point3 A,point3 B,point3 C,point3 D) {
    point3 a1=cha(A,B);
    point3 a2=cha(B,C);
    point3 n=cross(a1,a2);///求法向量
    point3 up=cha(D,A);
    double aa=dot_product(up,n);
    double bb=dot_product(n,n);
    return fabs(aa/sqrt(bb));
}
///三角形面积
double area3(point3 A,point3 B,point3 C) {
    double la=dis(B,C);
    double lb=dis(A,C);
    double lc=dis(A,B);
    double p=(la+lb+lc)/2.0;
    return sqrt(p*(p-la)*(p-lb)*(p-lc));///海伦公式
}

int main()
{
    point3 A,B,C,D;
    while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&A.x,&A.y,&A.z,&B.x,&B.y,&B.z,&C.x,&C.y,&C.z,&D.x,&D.y,&D.z)!=EOF) {
        if(check(A,B,C)||check(A,B,D)||check(A,C,D)||check(B,C,D)) {
           // cout << "2***********" << endl;
            printf("O O O O\n");
            continue;
        }
        if(disDM(A,B,C,D)<eps) {
            //cout << "1***********" << endl;
            printf("O O O O\n");
            continue;
        }
        double sa=area3(B,C,D);
        double sb=area3(A,C,D);
        double sc=area3(A,B,D);
        double sd=area3(A,B,C);
        double ssum=sa+sb+sc+sd;
        point3 ans;
        ans.x=(sa*A.x+sb*B.x+sc*C.x+sd*D.x)/ssum;
        ans.y=(sa*A.y+sb*B.y+sc*C.y+sd*D.y)/ssum;
        ans.z=(sa*A.z+sb*B.z+sc*C.z+sd*D.z)/ssum;
        /*
        double aa=dis(A,B)*dis(A,B);
        double bb=dis(A,C)*dis(A,C);
        double cc=dis(A,D)*dis(A,D);
        double dd=dis(C,D)*dis(C,D);
        double ee=dis(B,D)*dis(B,D);
        double ff=dis(B,C)*dis(B,C);
        double v=sqrt((aa*dd*(bb+cc+ee+ff-aa-dd)+bb*ee*(aa+cc+dd+ff-bb-ee)+cc*ff*(aa+bb+dd+ee-cc-ff)-aa*bb*ff-bb*cc*dd-cc*aa*ee-dd*ee*ff)/16);
        */
        ///此公式也挺方便
        double ld=disDM(A,B,C,D);
        double v=sd*ld/3.0;
        double r=v/ssum*3.0;
        printf("%.4f %.4f %.4f %.4f\n",ans.x,ans.y,ans.z,r);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值