C++实现空间中两个三角形位置关系(相交、平行)的判断

  两个空间三角形相交关系的判断:


    分别判断三角形trangle_1 的三条边与三角形trangle_2 的位置关系,三角形trangle_2 的三条边与三角形trangle_1 的位置关系。

    --求解三角形trangle_1 的其中一条边的直线方程
    --求解三角形trangle_2 所在平面的方程
    --根据以上方程求得x,y,z

    --判断点(x,y,z)是否在边(线段)上
    --判断点(x,y,z)是否在三角形内部
    --若都满足,则该边与三角形相交

    --若存在三角形的一条边与另一个三角形相交,则两个三角形相交
    --若三角形trangle_1 的三条边都不与三角形trangle_2 相交
      且三角形trangle_2 的三条边都不与三角形trangle_1 相交
      则两个三角形不相交

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;

// 3D vector
class Vector3
{
public:
    Vector3(float fx, float fy, float fz)
        :x(fx), y(fy), z(fz)
    {
    }

    // Subtract
    Vector3 operator - (const Vector3& v) const
    {
        return Vector3(x - v.x, y - v.y, z - v.z) ;
    }

    // Dot product
    float Dot(const Vector3& v) const
    {
        return x * v.x + y * v.y + z * v.z ;
    }

    // Cross product
    Vector3 Cross(const Vector3& v) const
    {
        return Vector3(
            y * v.z - z * v.y,
            z * v.x - x * v.z,
            x * v.y - y * v.x ) ;
    }

public:
    float x, y, z ;
};

bool JudgeIntersection(vector<vector<float>> triangle1, vector<vector<float>> triangle2);
bool EdgeAndTriangle(vector<vector<float>> triangle1, vector<vector<float>> triangle2, int i);
bool PointinTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 P);
bool JudgeParallel(vector<vector<float>> triangle1,vector<vector<float>> triangle2);
float PointFaceDistance(Vector3 point, vector<vector<float>> triangle);

int main(){
    vector<vector<float>> triangle1,triangle2;
    // 输入triangle1的顶点坐标: 3*3
    triangle1.resize(3);
    for(int i=0;i<3;i++)
        triangle1[i].resize(3);
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            cin>>triangle1[i][j];
        }
    }
    // 输入triangle2的顶点坐标: 3*3
    triangle2.resize(3);
    for(int i=0;i<3;i++)
        triangle2[i].resize(3);
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            cin>>triangle2[i][j];
        }
    }

    // 判断两个三角形是否相交
    bool res1=JudgeIntersection(triangle1,triangle2);
    if(res1==true){
        cout<<"xiang jiao"<<endl;
    }
    else{
        cout<<"bu xiang jiao"<<endl;
        /**
            若不相交,则判断是否平行。
            平面间的平行关系判断:(利用法向量)
            若法向量相等,则平行;否则不平行

            若平行,计算距离:
            1)取trangle1的一个顶点
            2)计算点面距(利用点面距的计算公式)
        **/
        bool bb=JudgeParallel(triangle1,triangle2);
        if(bb){
            cout<<"ping xing"<<endl;
            float d=PointFaceDistance(Vector3(triangle1[0][0],triangle1[0][1],triangle1[0][2]),triangle2);
            cout<<d<<endl;
        }
        else{
            cout<<"bu ping xing"<<endl;
        }
    }

    return 1;
}


/**
    两个空间三角形相交关系的判断:
    分别判断三角形trangle_1 的三条边与三角形trangle_2 的位置关系,三角形trangle_2 的三条边与三角形trangle_1 的位置关系。

	--求解三角形trangle_1 的其中一条边的直线方程
	--求解三角形trangle_2 所在平面的方程
	--根据以上方程求得x,y,z

	--判断点(x,y,z)是否在边(线段)上
	--判断点(x,y,z)是否在三角形内部
	--若都满足,则该边与三角形相交

	--若存在三角形的一条边与另一个三角形相交,则两个三角形相交
	--若三角形trangle_1 的三条边都不与三角形trangle_2 相交
	  且三角形trangle_2 的三条边都不与三角形trangle_1 相交
	  则两个三角形不相交
**/
bool JudgeIntersection(vector<vector<float>> triangle1,vector<vector<float>> triangle2){

    // 判断是否存在triangle2的一条边与triangle1相交
    for(int i=0;i<3;i++){
        bool res=EdgeAndTriangle(triangle1,triangle2,i);
        // 若存在三角形的一条边与另一个三角形相交,则两个三角形相交
        if(res==true){
            return true;
        }
    }

    // 判断是否存在triangle1的一条边与triangle2相交
    for(int i=0;i<3;i++){
        bool res=EdgeAndTriangle(triangle2,triangle1,i);
        // 若存在三角形的一条边与另一个三角形相交,则两个三角形相交
        if(res==true){
            return true;
        }
    }

    // 若三角形trangle1 的三条边都不与三角形trangle2 相交
	// 且三角形trangle2 的三条边都不与三角形trangle1 相交
	// 则两个三角形不相交
	return false;
}


// 判断边与三角形是否相交
/**
        1、计算三角形triangle2所在面的方程: 三点坐标(x1,y1,z1)、(x2,y2,z2)、(x3,y3,z3)

            Ax+By+Cz+D=0

            其中:
            A=y1z2-y1z3-y2z1+y2z3+y3z1-y3z2
            B=-x1z2+x1z3+x2z1-x2z3-x3z1+x3z2
            C=x1y2-x1y3-x2y1+x2y3+x3y1-x3y2
            D=-x1y2z3+x1y3z2+x2y1z3-x2y3z1-x3y1z2+x3y2z1



        2、计算过这两个顶点(x4,y4,z4)和(x5,y5,z5)的直线方程

            Px+Qy+R=0 && My+Nz+T=0

            其中:
            P=y5-y4
            Q=-(x5-x4)
            R=-((y5-y4)x4-(x5-x4)y4)
            M=z5-z4
            N=-(y5-y4)
            T=-((z5-z4)y4-(y5-y4)z4)

            (y2-y1)x-(x2-x1)y=(y2-y1)x1-(x2-x1)y1
            (z2-z1)y-(y2-y1)z=(z2-z1)y1-(y2-y1)z1



        3、计算交点坐标

            y=(A*R/P+C*T/N-D)/(B-A*Q/P-C*M/N);
            z=(-T-M*y)/N
            x=(-R-Q*y)/P

        4、判断交点坐标是否在线段(边)上、且在三角形内

**/
bool EdgeAndTriangle(vector<vector<float>> triangle1,vector<vector<float>> triangle2, int i){
        //三角形triangle1的三个顶点
        float x1=triangle1[0][0],
            y1=triangle1[0][1],
            z1=triangle1[0][2],
            x2=triangle1[1][0],
            y2=triangle1[1][1],
            z2=triangle1[1][2],
            x3=triangle1[2][0],
            y3=triangle1[2][1],
            z3=triangle1[2][2];

        // 三角形triangle2的一条边的两个顶点
        float x4=triangle2[i][0],
            y4=triangle2[i][1],
            z4=triangle2[i][2],
            x5=triangle2[(i+1)%3][0],
            y5=triangle2[(i+1)%3][1],
            z5=triangle2[(i+1)%3][2];

        // 计算交点坐标(x,y,z)
        float A=y1*z2-y1*z3-y2*z1+y2*z3+y3*z1-y3*z2,
        B=-x1*z2+x1*z3+x2*z1-x2*z3-x3*z1+x3*z2,
        C=x1*y2-x1*y3-x2*y1+x2*y3+x3*y1-x3*y2,
        D=-x1*y2*z3+x1*y3*z2+x2*y1*z3-x2*y3*z1-x3*y1*z2+x3*y2*z1,
        P=y5-y4,
        Q=-(x5-x4),
        R=-((y5-y4)*x4-(x5-x4)*y4),
        M=z5-z4,
        N=-(y5-y4),
        T=-((z5-z4)*y4-(y5-y4)*z4);

        float y=(A*R/P+C*T/N-D)/(B-A*Q/P-C*M/N);
        float z=(-T-M*y)/N;
        float x=(-R-Q*y)/P;

        // 判断(x,y,z)是否在线段上
        bool b1;
        if(x4>x5){
            if(x<=x4&&x>=x5){
                b1=true;
            }
            else{
                b1=false;
            }
        }
        else{
            if(x<=x5&&x>=x4){
                b1=true;
            }
            else{
                b1=false;
            }
        }

        // 判断点(x,y,z)是否在三角形内部
        Vector3 v1=Vector3(x,y,z);
        Vector3 v2=Vector3(x1,y1,z1);
        Vector3 v3=Vector3(x2,y2,z2);
        Vector3 v4=Vector3(x3,y3,z3);
        bool b2=PointinTriangle(v2,v3,v4,v1);

        // 若都满足,则该边与三角形相交
        if(b1==true && b2==true){
            return true;
        }
        return false;
}

// 判断点是否在三角形内部
bool PointinTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 P)
{
    Vector3 v0 = C - A ;
    Vector3 v1 = B - A ;
    Vector3 v2 = P - A ;

    float dot00 = v0.Dot(v0) ;
    float dot01 = v0.Dot(v1) ;
    float dot02 = v0.Dot(v2) ;
    float dot11 = v1.Dot(v1) ;
    float dot12 = v1.Dot(v2) ;

    float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01) ;

    float u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
    if (u < 0 || u > 1) // if u out of range, return directly
    {
        return false ;
    }

    float v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
    if (v < 0 || v > 1) // if v out of range, return directly
    {
        return false ;
    }

    return u + v <= 1 ;
}


// 判断两个三角形是否平行
bool JudgeParallel(vector<vector<float>> triangle1,vector<vector<float>> triangle2){
    Vector3 v1_1=Vector3(triangle1[0][0],triangle1[0][1],triangle1[0][2]);
    Vector3 v1_2=Vector3(triangle1[1][0],triangle1[1][1],triangle1[1][2]);
    Vector3 v1_3=Vector3(triangle1[2][0],triangle1[2][1],triangle1[2][2]);
    Vector3 v2_1=Vector3(triangle2[0][0],triangle2[0][1],triangle2[0][2]);
    Vector3 v2_2=Vector3(triangle2[1][0],triangle2[1][1],triangle2[1][2]);
    Vector3 v2_3=Vector3(triangle2[2][0],triangle2[2][1],triangle2[2][2]);
    Vector3 v3=v1_1-v1_2;
    Vector3 v4=v1_1-v1_3;
    Vector3 v5=v2_1-v2_2;
    Vector3 v6=v2_1-v2_3;
    Vector3 c1=v3.Cross(v4);
    Vector3 c2=v5.Cross(v6);

    if(c1.x*c2.y==c1.y*c2.x&&c1.y*c2.z==c1.z*c2.y){
        return true;
    }
    else{
        return false;
    }
}

// 计算点面距离
float PointFaceDistance(Vector3 point, vector<vector<float>> triangle){
    // 三角形的三个点
    Vector3 v_1=Vector3(triangle[0][0],triangle[0][1],triangle[0][2]);
    Vector3 v_2=Vector3(triangle[1][0],triangle[1][1],triangle[1][2]);
    Vector3 v_3=Vector3(triangle[2][0],triangle[2][1],triangle[2][2]);
    // 两个边的方向向量
    Vector3 v1=v_1-v_2;
    Vector3 v2=v_1-v_3;
    // 面的法向量
    Vector3 n=v1.Cross(v2);
    //
    Vector3 v3=point-v_1;
    //
    float n_d=sqrt(n.x*n.x+n.y*n.y+n.z*n.z);
    //
    float distance=fabs(v3.Dot(n)/n_d);
    return distance;
}




















  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 C++ 代码实现: ```c++ #include <iostream> #include <cmath> using namespace std; struct Vector3 { double x, y, z; Vector3() {} Vector3(double x, double y, double z) : x(x), y(y), z(z) {} Vector3 operator+(const Vector3& other) const { return Vector3(x + other.x, y + other.y, z + other.z); } Vector3 operator-(const Vector3& other) const { return Vector3(x - other.x, y - other.y, z - other.z); } Vector3 operator*(double scalar) const { return Vector3(x * scalar, y * scalar, z * scalar); } double dot(const Vector3& other) const { return x * other.x + y * other.y + z * other.z; } Vector3 cross(const Vector3& other) const { return Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x); } double length() const { return sqrt(x * x + y * y + z * z); } }; struct Ray { Vector3 origin, direction; Ray() {} Ray(const Vector3& origin, const Vector3& direction) : origin(origin), direction(direction) {} }; struct Plane { Vector3 point, normal; Plane() {} Plane(const Vector3& point, const Vector3& normal) : point(point), normal(normal) {} }; bool intersect(const Ray& ray, const Plane& plane, double& t) { double denom = plane.normal.dot(ray.direction); if (abs(denom) < 1e-6) // 判断是否平行 return false; t = plane.normal.dot(plane.point - ray.origin) / denom; return t >= 0; } int main() { // 示例:射线由点(0, 0, 0)出发,方向为(1, 1, 1);平面上的一点为(0, 0, 1),法向量为(0, 0, 1) Ray ray(Vector3(0, 0, 0), Vector3(1, 1, 1)); Plane plane(Vector3(0, 0, 1), Vector3(0, 0, 1)); double t; if (intersect(ray, plane, t)) { Vector3 intersection = ray.origin + ray.direction * t; cout << "Intersection point: (" << intersection.x << ", " << intersection.y << ", " << intersection.z << ")" << endl; } else { cout << "No intersection." << endl; } return 0; } ``` 这里我们定义了三个结构体:`Vector3` 表示三维向量,`Ray` 表示射线,`Plane` 表示平面。`intersect` 函数判断射线与平面是否相交,并返回相交参数t。在主函数,我们给出了一个示例并输出相交点的坐标。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值