[ACM_几何] F. 3D Triangles (三维三角行相交)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28235#problem/A
题目大意:给出三维空间两个三角形三个顶点,判断二者是否有公共点,三角形顶点、边、内部算三角形的一部分。 |
解题思路:见模板 |
//******************************************************************************* #include<iostream> #include<algorithm> #include<cmath> #include<stdio.h> using namespace std; #define eps 1e-8 int dcmp(double x){ if(fabs(x)<eps)return 0; else return x<0 ? -1:1; } struct Point3{ double x,y,z; Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z){} }; bool operator==(const Point3& a,const Point3& b){ return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0 && dcmp(a.z-b.z)==0 ; } typedef Point3 Vector3; Vector3 operator+(Vector3 A,Vector3 B){ return Vector3(A.x+B.x,A.y+B.y,A.z+B.z); } Vector3 operator-(Vector3 A,Vector3 B){ return Vector3(A.x-B.x,A.y-B.y,A.z-B.z); } Vector3 operator*(Vector3 A,double p){ return Vector3(A.x*p,A.y*p,A.z*p); } Vector3 operator/(Vector3 A,double p){ return Vector3(A.x/p,A.y/p,A.z/p); } double Dot(Vector3 A,Vector3 B){return A.x*B.x+A.y*B.y+A.z*B.z;} double Length(Vector3 A){return sqrt(Dot(A,A));} double Angle(Vector3 A,Vector3 B){return acos(Dot(A,B)/Length(A)/Length(B));} /*p到平面p0-n的距离 double DistanceToPlane(Point3 p,Point3 p0,Vector3 n){ return fabs(Dot(p-p0,n))/Length(n); } //p到平面p0-n的投影 Point3 GetPlaneProjection(Point3 p,Point3 p0,Vector3 n){ double d=Dot(p-p0,n)/Length(n); return p+n*d; } //直线p1-p2到平面p0-n的交点 Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Point3 p0,Vector3 n){ Vector3 v=p2-p1; double t=(Dot(n,p0-p1)/Dot(n,p2-p1));//判断分母是否为0 return p1+v*t;//如果是线段,判断t是不是在0-1之间 }*/ //叉积 Vector3 Cross(Vector3 A,Vector3 B){ return Vector3(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x); } double Area2(Point3 A,Point3 B,Point3 C){return Length(Cross(B-A,C-A));} //点p在三角形p0p1p2中(利用面积法算点是否在三角形内,假定所有的点共面) bool PointInTri(Point3 p,Point3 p0,Point3 p1,Point3 p2){ double area1=Area2(p,p0,p1); double area2=Area2(p,p1,p2); double area3=Area2(p,p2,p0); return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0; } //三角形p0p1p2是否和线段AB相交(此函数会把线段在平面上的情况视为不相交) bool TriSegIntersection(Point3 p0,Point3 p1,Point3 p2,Point3 A,Point3 B,Point3& p){ Vector3 n=Cross(p1-p0,p2-p0); if(dcmp(Dot(n,B-A))==0)return false;//平行或共面 else{ //直线AB和平面P0P1P2有唯一交点 double t=Dot(n,p0-A)/Dot(n,B-A); if(dcmp(t)<0 || dcmp(t-1)>0)return false;//交点不在线段AB上 p=A+(B-A)*t; //计算交点 return PointInTri(p,p0,p1,p2); //判断交点是否在三角形内 } } /*到直线的距离 double DistanceToLine(Point3 p,Point3 A,Point3 B){ Vector3 v1=B-A,v2=p-A; return Length(Cross(v1,v2))/Length(v1); } //点p到线段AB的距离 double DistanceToSegment(Point3 p,Point3 A,Point3 B){ if(A==B)return Length(p-A); Vector3 v1=B-A,v2=p-A,v3=p-B; if(dcmp(Dot(v1,v2))<0)return Length(v2); else if(dcmp(Dot(v1,v3))>0)return Length(v3); else return Length(Cross(v1,v2))/Length(v1); } //返回,,的混合积,他等于四面体邮箱面积的6倍 double Volume6(Point3 A,Point3 B,Point3 C,Point3 D){ return Dot(D-A,Cross(B-A,C-A)); }*/ //判断两个三角形是否有公共点 bool TriTriIntersection(Point3* T1,Point3* T2){ Point3 p; for(int i=0;i<3;i++){ if(TriSegIntersection(T1[0],T1[1],T1[2],T2[i],T2[(i+1)%3],p))return true; if(TriSegIntersection(T2[0],T2[1],T2[2],T1[i],T1[(i+1)%3],p))return true; } return false; } //******************************************************************************* int main(){ int T;cin>>T; while(T--){ Point3 T1[3],T2[3]; for(int i=0;i<3;i++)cin>>T1[i].x>>T1[i].y>>T1[i].z; for(int i=0;i<3;i++)cin>>T2[i].x>>T2[i].y>>T2[i].z; cout<<(TriTriIntersection(T1,T2) ? "1\n":"0\n"); }return 0; } //*******************************************************************************
|