【unity】三维数学应用(计算线和面的交点)

本文介绍了在Unity中利用三维数学计算线段和面交点的一种方法,通过求面的法线、线段向量以及相似三角形原理,提供了计算交点的详细步骤和两种示例代码,包括面线相交判断。
摘要由CSDN通过智能技术生成

【unity】三维数学应用(计算线和面的交点)

实现方法有多种,下面介绍一种简单的方法。利用一个点指向面上任意点的向量,到该面法线的投影长度相同的基本原理,结合相似三角形既可以求出交点。

原理

如下图

GD组成的线段和ABC组成的三角形相交与E点,ABCDG的坐标已知求E点坐标。

首先用叉乘求出ABC面的法线 N ⃗ \vec{N} N ;(D点分别到ABC各点的向量在法线 N ⃗ \vec{N} N 上投影的模长是相同的,同样等于D点到E点的向量在 N ⃗ \vec{N} N 投影的模长)

分别用点乘的方法求出, D A ⃗ \vec{DA} DA N ⃗ \vec{N} N 的投影模长a和 D G ⃗ \vec{DG} DG N ⃗ \vec{N} N 的投影模长b;

D E ⃗ \vec{DE} DE N ⃗ \vec{N} N 的投影模长同样等于a

∴由相似三角形可得
a b = ∣ D E ⃗ ∣ ∣ D G ⃗ ∣ \frac{a}{b}=\frac{|\vec{DE}|}{|\vec{DG}|} ba=DG DE
由次可得E点的坐标

实现代码

    Vector3 GetIntersectPoint(Vector3 C1, Vector3 C2, Vector3 C3, Vector3 L1, Vector3 L2)
    {
        //求面的法线
        Vector3 n0 = (C2 - C1).normalized;
        Vector3 n1 = (C2 - C3).normalized;
        Vector3 N = Vector3.Cross(n0,  n1);
        //线段的向量和到面上点的向量
        Vector3 line1 = L2 - L1;
        Vector3 line2 = C1 - L1;
        //与面法线点成比,得到线段点到面的模长
        float dis1 = Vector3.Dot(N, line1);
        float dis2 = Vector3.Dot(N, line2);
        float magnitude = (dis2 / dis1)*line1.magnitude;
        //用线段的单位向量乘模长求出交点
        Vector3 direction = line1.normalized * magnitude;
        return L1 + direction;

    }

同样的方法也可以计算两条线段的加点

Vector3 GetIntersectPoint(Vector3 C1, Vector3 C2, Vector3 P1, Vector3 P2)
    {
       // 分别求出两个线段的单位向量
        Vector3 L0=(C2 - C1).normalized;
        Vector3 L1=( P2 - P1).normalized;
       //俩次差乘建立 L0为一个坐标轴的的坐标系
        Vector3 H = Vector3.Cross(L0,  L1);
        Vector3 N = Vector3.Cross( L0, H);

        float dis1 = Vector3.Dot(N, L1);
        float dis2 = Vector3.Dot(N, (P1-C1));
      
        float magnitude = dis2 / dis1;
        return L1 * magnitude + P1;
     }

叉乘判断线段和面是否相交

 //判断面和线段是否相相交
    bool isCut(Vector3 C1, Vector3 C2, Vector3 L1, Vector3 L2)
    {
        Vector3 V0 = squeeze( C2 - C1);
        Vector3 V1 = squeeze( L1 - C1);
        Vector3 V2 = squeeze( L2 - C1);
        Vector3 Cross1 = Vector3.Cross(V0, V1).normalized;
        Vector3 Cross2 = Vector3.Cross(V0, V2).normalized;
        float Dot = Vector3.Dot(Cross1, Cross2);
        if (Dot>0)
        {
            //同边不相交
            return false;
        }
        else
        {
            //同异边相交
            return true;
        }

    }
   //坐标平面化,去除y值
    Vector3 squeeze(Vector3 vector)
    {
        return new Vector3(vector.x, 0, vector.z);
    }

判断两条线段是否相交

    bool isCut(Vector3 C1, Vector3 C2, Vector3 L1, Vector3 L2)
    {
        Vector3 V0 =C2 - C1;
        Vector3 V1 =L1 - C1;
        Vector3 V2 = L2 - C1;
        Vector3 Cross1 = Vector3.Cross(V0, V1).normalized;
        Vector3 Cross2 = Vector3.Cross(V0, V2).normalized;
        float Dot = Vector3.Dot(Cross1, Cross2);
          if (Dot>0)
        {
            //同边不相交
            return false;
        }
        else
        {
            //同异边相交
            return true;
        }

    }
  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小生云木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值