zoukankan      html  css  js  c++  java
  • [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
    ":"0
    ");
        }return 0;
    }
    //*******************************************************************************
    View Code
  • 相关阅读:
    成都Uber优步司机奖励政策(2月18日)
    北京Uber优步司机奖励政策(2月18日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月18日)
    优步UBER司机全国各地最新奖励政策汇总(持续更新...)
    新年Uber司机端换新装啦!
    百度参投 Uber中国12亿美元融资已到账
    人民优步+(拼车)自动接单功能上线
    vi 调到第一行,或最后一行
    linux文本操作界面 vi面板如何复制一行
    Apache支持多端口配置处理
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3246491.html
Copyright © 2011-2022 走看看