UVa 11275 3D Triangles 空间三角形

题目地址: UVa11275

首先:点在三角形内有两个模板  一个要求已经共面,一个可以帮助判断是否共面

这里是“三角面” 那么为了考虑完全包含且共面的情形,是应该判断一下是否有顶点在另一个三角形面上的。

比如测试数据 

2

0 100 0

-100 -100 0

100 -100 0

0 1 0

-1 -1 0

1 -1 0


就应该输出1  但是测试数据却...

"ac" 代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include <vector>

using namespace std;
const double eps=1e-8;
const double PI=acos(-1.0);

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) {}
    
};

typedef Point3 Vector3;

Vector3 operator+(Point3 A,Point3 B)
{
    return Point3(A.x+B.x,A.y+B.y,A.z+B.z);
    
}

Vector3 operator-(Point3 A,Point3 B)
{
    return Point3(A.x-B.x,A.y-B.y,A.z-B.z);
    
}

Vector3 operator*(Point3 A,double p)
{
    return Point3(A.x*p,A.y*p,A.z*p);
    
}

Vector3 operator/(Point3 A,double p)
{
    return Point3(A.x/p,A.y/p,A.z/p);
    
}

bool operator<(Point3 &A,Point3 &B)
{
    return A.x<B.x||(A.x==B.x&&A.y<B.y)||(A.x==B.x&&A.y==B.y&&A.z<B.z);
    
}
bool operator==(Point3 &A,Point3 &B)
{
    return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0&&dcmp(A.z-B.z)==0;
}
ostream & operator<<(ostream & out,Vector3 A)
{
    out<<A.x<<' '<<A.y<<' '<<A.z<<endl;
    
    return out;
}


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));
}


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));
}


double DistanceToPlane(const Point3 &p,const Point3 & p0,const Vector3 &n)
{
    return fabs(Dot(p-p0,n))/Length(n);
    
}

Point3  GetPlaneProjection(Point3 p,Point3 p0,Vector3 n)
{
    return p-n*Dot(p-p0,n)/Dot(n,n);
}

Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Point3 p0,Vector3 n)
{
    double t=Dot(n,p0-p1)/Dot(n,p2-p1);
    return p1+(p2-p1)*t;
    
}

//  点在三角形内部
//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;
//}

//  线段与三角形相交 不考虑共面情形


double DistanceToLine(Point3 P,Point3 A,Point3 B)
{
    Vector3 v1=B-A;
    Vector3 v2=P-A;
    return  Length(Cross(v1, v2))/Length(v1);
    
}

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);
    
}

double volume6(Point3 A,Point3 B,Point3 C,Point3 D)
{
    return  Dot(D-A,Cross(B-A,C-A));
}



struct Tri{
    
    Point3 P[3];
    
    Tri(Point3 A=Point3(0,0,0),Point3 B=Point3(0,0,0),Point3 C=Point3(0,0,0))
    {
        P[0]=A;
        P[1]=B;
        P[2]=C;
    }
    
};


//bool SameSide(const Point3& p1, const Point3& p2, const Point3& a, const Point3& b) {
//    return dcmp(Dot(Cross(b-a, p1-a), Cross(b-a, p2-a))) >= 0;
//}
//
 点在三角形P0, P1, P2中
//bool PointInTri(const Point3& P, const Point3& P0, const Point3& P1, const Point3& P2) {
//    return SameSide(P, P0, P1, P2) && SameSide(P, P1, P0, P2) && SameSide(P, P2, P0, P1);
//}


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

//bool PointInTri(const Point3& P, Tri tri) {
//    Point3& P0=tri.P[0];
//    Point3& P1=tri.P[1];
//    Point3& P2=tri.P[2];
//    
//    return SameSide(P, P0, P1, P2) && SameSide(P, P1, P0, P2) && SameSide(P, P2, P0, P1);
//}
//  线段与三角形相交 不考虑共面情形

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{
        
        double t=Dot(n,p0-A)/Dot(n,B-A);
        if(dcmp(t)<0||dcmp(t-1)>0)  return false;   // 端点也ok
        else
        {
            p=A+(B-A)*t;
            
            return PointInTri(p,p0,p1,p2);
        }
        
    }
}

bool  TriSegIntersection(Tri tri,Point3 A,Point3 B,Point3 & p)
{
    Point3 p0=tri.P[0];
    Point3 p1=tri.P[1];
    Point3 p2=tri.P[2];
    
    Vector3 n=Cross(p1-p0, p2-p0);
    if(dcmp(Dot(n,B-A))==0)  return false;
    else{
        
        double t=Dot(n,p0-A)/Dot(n,B-A);
        if(dcmp(t)<0||dcmp(t-1)>0)  return false;   // 端点也ok
        else
        {
            p=A+(B-A)*t;
            
            return PointInTri(p,p0,p1,p2);
        }
        
    }
}



Point3 read_point3()
{
    Point3 ans;
    scanf("%lf%lf%lf",&ans.x,&ans.y,&ans.z);
    return ans;
    
}

//bool TriCommom(Tri A,Tri B)
//{
//    Point3 sol;
//    
//    for(int i=0;i<3;i++)
//    {
//        if(PointInTri(A.P[i], B))  return 1;
//        if(PointInTri(B.P[i], A))  return 1;
//        
//        if(TriSegIntersection(A, B.P[i],B.P[(i+1)%3] , sol))  return 1;
//        if(TriSegIntersection(B, A.P[i],A.P[(i+1)%3] , sol))  return 1;
//        
//    }
//    
//    return 0;
//    
//}

bool TriCommom(Point3 * A,Point3 * B)
{
    Point3 sol;
    
    for(int i=0;i<3;i++)
    {
        // 不应该注释的~!!
//        if(PointInTri(A[i], B[0],B[1],B[2]))  return 1;
//        if(PointInTri(B[i], A[0],A[1],A[2]))  return 1;
        
        if(TriSegIntersection(A[0],A[1],A[2],B[i],B[(i+1)%3] , sol))  return 1;
        if(TriSegIntersection(B[0],B[1],B[2], A[i],A[(i+1)%3] , sol))  return 1;
        
    }
    
    return 0;
    
}

int main()
{
    int T;
    cin>>T;
    
    
    while(T--)
    {
        Point3  T1[3],T2[3];
        
        for(int i=0;i<3;i++)
        {
            T1[i]=read_point3();
            
        }
        for(int i=0;i<3;i++)
        {
            T2[i]=read_point3();
            
        }
        
        
        //        A=Tri(P[0],P[1],P[2]);
        //        B=Tri(P[3],P[4],P[5]);
    
        
        printf("%d\n", TriCommom(T1, T2) ? 1 : 0);
    }
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值