HDU 5733 - tetrahedron
题意:
给定四点,求是否能够成四面体,若能则求出其内接圆心和半径
是否能构成四面体: 三点成面的法线和另一点与三点中任一点相连的向量是否垂直?
四面体内接球
球心: 任意三个角平分面的交点
半径: 交点到任意面的距离
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 const double EPS = 1e-8; 6 struct Point3 7 { 8 double x,y,z; 9 Point3() {} 10 Point3(double x,double y,double z):x(x),y(y),z(z) {} 11 }; 12 typedef Point3 Vec3; 13 Vec3 operator + (Vec3 A,Vec3 B) 14 { 15 return Vec3(A.x + B.x, A.y + B.y, A.z + B.z); 16 } 17 Vec3 operator - (Vec3 A,Vec3 B) 18 { 19 return Vec3(A.x - B.x, A.y - B.y, A.z - B.z); 20 } 21 Vec3 operator * (Vec3 A,double p) 22 { 23 return Vec3(A.x * p, A.y * p, A.z * p); 24 } 25 Vec3 operator / (Vec3 A,double p) 26 { 27 return Vec3(A.x / p, A.y / p, A.z / p); 28 } 29 int dcmp(double x)//double cmp 30 { 31 return fabs(x) < EPS ? 0 : (x < 0? -1: 1); 32 } 33 double Dot3(Vec3 A,Vec3 B)//Dot mult 34 { 35 return A.x*B.x + A.y*B.y + A.z*B.z; 36 } 37 double Length3(Vec3 A) 38 { 39 return sqrt( Dot3(A, A) ); 40 } 41 double Angle(Vec3 A,Vec3 B)//夹角 42 { 43 return acos(Dot3(A,B) / Length3(A) / Length3(B)); 44 } 45 Vec3 Cross3(Vec3 A,Vec3 B)//叉积 右手螺旋A->B 46 { 47 return Vec3(A.y * B.z - A.z * B.y, 48 A.z * B.x - A.x * B.z, 49 A.x * B.y - A.y * B.x); 50 } 51 struct Plane 52 { 53 Vec3 n; //法线 54 Point3 p0; 55 Plane() {} 56 Plane(Vec3 nn,Point3 pp0) 57 { 58 n = nn / Length3(nn); 59 p0 = pp0; 60 } 61 Plane(Point3 a,Point3 b,Point3 c) 62 { 63 Point3 nn = Cross3(b-a,c-a); 64 n = nn/(Length3(nn)); 65 p0 = a; 66 } 67 }; 68 //角平分面 法向量为两平面法向量相加(内角)或相减(外角) 69 Plane jpfPlane(Point3 a1,Point3 a2,Point3 b,Point3 c) 70 { 71 Plane p1(a1,b,c),p2(a2,c,b); 72 Vec3 temp = p1.n + p2.n; 73 return Plane(Cross3(temp, c-b),b); 74 } 75 Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Plane a)//线面交点 取线上任意两点 76 { 77 Point3 p0 = a.p0; 78 Vec3 n = a.n,v = p2-p1; 79 double t = (Dot3(n,p0-p1) / Dot3(n,p2-p1)); //映射到法向量的比例 80 return p1 + v * t; 81 } 82 Point3 PlaneInsertion(Plane a,Plane b,Plane c)//三面交点 83 {//两面交线与两面法线均垂直,法线叉积为其方向矢量. 84 Vec3 nn = Cross3(a.n,b.n),use = Cross3(nn,a.n); 85 Point3 st = LinePlaneIntersection(a.p0, a.p0+use,b);//得交线上一点 86 return LinePlaneIntersection(st, st+nn, c); 87 } 88 double DistanceToPlane(Point3 p,Plane a) 89 { 90 Point3 p0 = a.p0; 91 Vec3 n = a.n; 92 return fabs( Dot3(p-p0,n) / Length3(n) ); 93 } 94 bool isOnePlane(Point3 a,Point3 b,Point3 c,Point3 d) 95 { 96 double t = Dot3(d-a,Cross3(b-a,c-a) ); 97 return dcmp(t)==0; 98 } 99 int main() 100 { 101 Point3 p[4]; 102 while(~scanf("%lf%lf%lf",&p[0].x,&p[0].y,&p[0].z)) 103 { 104 for(int i=1;i<4;i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z); 105 if(isOnePlane(p[0],p[1],p[2],p[3])) 106 { 107 puts("O O O O"); continue; 108 } 109 Plane a = jpfPlane(p[3],p[2],p[1],p[0]),//三个角平分面的交点即为圆心 110 b = jpfPlane(p[3],p[0],p[1],p[2]), 111 c = jpfPlane(p[3],p[1],p[0],p[2]); 112 Plane d(p[0],p[1],p[2]); 113 Point3 center = PlaneInsertion(a,b,c); 114 double r = DistanceToPlane(center,d); 115 printf("%.4f %.4f %.4f %.4f ",center.x,center.y,center.z,r); 116 } 117 }