[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;

}

//*******************************************************************************
View Code

 

你可能感兴趣的:(ACM)