1 引言
问题:已知三维空间中四点A、B、C、D,如何判断线段AB与CD是否相交,若相交则求出交点。

分析:

AB、CD要相交,则AB、CD必须要在同一平面内
快速排斥和跨立实验判断是否相交
几何法分析求出交点
先来看看效果,紫色小球为交点。

2 求解
2.1 AB、CD是否共面与平行
要判断AB、CD是否共面,其实就是判断A、B、C、D四个点是否共面。我们知道三点确定一个平面,如果AB垂直于ACD三点所在平面的法线,则说明A、B、C、D四点共面。
A、C、D三点所在平面的法线怎么求?
很简单,两个向量的叉乘就是这两个向量所在平面的法线。

这里我们用点积来写代码。

Vector3 ab = b - a;
Vector3 ca = a - c;
Vector3 cd = d - c;Vector3 v1 = Vector3.Cross(ca, cd);if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6)
{// 不共面return false;
}

AB和CD平行时,两者的夹角为0°或180°,也可用点积或叉积来判断,这里就不再多说了。

2.2 快速排斥与跨立实验判断AB、CD是否相交
2.2.1 快速排斥
快速排斥的作用是先预处理一下,先排出掉根本不可能相交的情况,以减少不必要的运算。
其原理就是判断AB的包围盒与CD的包围盒是否有重叠的部分。什么意思呢?看图就明白了。

三维的同理。

代码怎么写呢?如下。

// 快速排斥
if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)|| Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)|| Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z)
)return false;

2.2.2 跨立实验
什么是跨立呢?比如A、B两点分别位于CD的左右两边,我们就说A、B跨立CD。
如果两条线段相交,它们必然是互相跨立的嘛。
怎么判断跨立呢?用向量的叉积。

代码如下:

// 跨立试验
if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0&& Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0)
{// 相交return true;
}

2.3 计算交点
咱们先写结论。

AO与AB的比值求到了,O点也就能求到了。
结论怎么来的?分析如下:

① 咱们先做条辅助线CE,CE平行于AB,且与AB等长。

② 则有ΔAFO相似于ΔEGC,则有

③ 则有

④根据叉积的定义,又有

⑤于是乎,就有

这里我们用点积来计算,主要是为了能够求出AB和CD不直接相交,但AB的延长线和CD相交的交点。比如我们把下面提供的代码中的快速排斥和跨立试验给注释掉,就能求出延长线的交点。

3 完整项目
如下。

/// <summary>
/// 计算AB与CD两条线段的交点.
/// </summary>
/// <param name="a">A点</param>
/// <param name="b">B点</param>
/// <param name="c">C点</param>
/// <param name="d">D点</param>
/// <param name="intersectPos">AB与CD的交点</param>
/// <returns>是否相交 true:相交 false:未相交</returns>
private bool TryGetIntersectPoint(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 intersectPos)
{intersectPos = Vector3.zero;Vector3 ab = b - a;Vector3 ca = a - c;Vector3 cd = d - c;Vector3 v1 = Vector3.Cross(ca, cd);if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6){// 不共面return false;}if (Vector3.Cross(ab, cd).sqrMagnitude <= 1e-6){// 平行return false;}Vector3 ad = d - a;Vector3 cb = b - c;// 快速排斥if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)|| Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)|| Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z))return false;// 跨立试验if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0&& Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0){Vector3 v2 = Vector3.Cross(cd, ab);float ratio = Vector3.Dot(v1, v2) / v2.sqrMagnitude;intersectPos = a + ab * ratio;return true;}return false;
}

————————————————
原文链接:https://blog.csdn.net/sinat_25415095/article/details/114293638

Unity3D C#数学系列之判断两条线段是否相交并求交点相关推荐

  1. 判断两条线段/直线相交,并求交点

      一.矢量基本知识     因为后面的计算需要一些矢量的基本知识,这里只是简单的列举如下,如果需要更加详细的信息,可以自行搜索wikipedia或google. 1.矢量的概念:如果一条线段的端点是 ...

  2. 【数学计算】判断两条线段是否相交+计算两条线段的交点和夹角

    序言 还是那句话,学习是为了应用.书到用时方恨"用得少" 1. 计算两条直线的交点 直线一般式方程 A x + B y + C = 0 Ax+By+C = 0 Ax+By+C=0 ...

  3. 计算几何-判断两条线段是否相交

    原理:如果两条线段相交,那么必须跨立,就是以一条线段为标准,另一条线段的两端点一定在这条线段的两段 也就是说a b两点在线段cd的两端,c d两点在线段ab的两端 struct point() {do ...

  4. 如何判断两条线段是否相交

    本篇是在 [C++笔记]如何判断2个线段相交 的基础上加上自己的理解和实践总结出的判断两线段是否相交的方法. 判断两条线段是否相交 先附上判断函数 bool judge(int Ax1,int Ay1 ...

  5. 判断两条线段是否相交

    如上图,判断线段AB和线段CD相交. 分析:如果线段AB和线段CD相交,只能是图中的两种相交情况.可以用向量叉乘来判断.如果(向量AB叉乘向量AC)*(向量AB叉乘向量AD)<= 0 并且(向量 ...

  6. 判断两条线段是否相交 java_判断两个线段是否相交02

    写在前面 在其他博客中看到这方面的知识,很多都是重复,并且说的总是云里雾里的,所以这里我就自己总结一下这种问题如何求解,判断两个线段是否相交在前面我们提到了会用到叉积的一点知识,那么这里就来详细说一下 ...

  7. 二维空间内,如何判断两条线段是否相交,相离,平行,重合,并求交点

    首先,假设有两条线段p,q,求这两条线段的空间关系. 我们把两条线段的四个顶点看为向量,用坐标表示:p1(p1x,p1y), p2(p2x,p2y), q1(q1x,q1y), q2(q2x, q2y ...

  8. 【转载】判断两条线段是否相交——(向量叉乘)

    原文:https://www.cnblogs.com/tuyang1129/p/9390376.html 实现:https://blog.csdn.net/yegshun/article/detail ...

  9. 两条线段是否相交,计算交点公式。

    A本身无限长,假设B也无限长,直接求得AB的交点坐标,然后再判断该坐标是否在定长线段B的内部就可以了啊 AB本身就是两条直线,知道两端点就可以知道其直线方程,B也是一样,两个方程联立,     得到一 ...

最新文章

  1. python ipaddress_Python3标准库:ipaddress Internet地址
  2. dp 与px互相转换
  3. 爬虫前期知识的储备(二)
  4. 【转载】java中Date与String的相互转化
  5. 使用code::blocks搭建objective-c的IDE开发环境 支持 @interface
  6. linux 下  qserialport waitforreadyread_北师大版初中数学八年级(下)第二章第一节不等关系(精品)...
  7. PostgreSQL一些简单问题以及解决办法
  8. 七嘴八舌Google
  9. java 异常java.lang.UnsupportedOperationException
  10. Cknife与一句话木马提权
  11. 基于matlab的音频处理论文,基于Matlab的语音信号处理与仿真设计毕业论文
  12. app invento2r wxbit版 快速开发简单蓝牙上位/蓝牙串口助手
  13. [转载] OpenCV—利用回调函数实现返回鼠标点击位置的坐标和灰度值
  14. 搭建springboot+mybatis+freemarker项目
  15. 小程序点击按钮分享功能
  16. 【无标题】OSPF协议及ACL的使用及配置
  17. 黑马 React 学习记录
  18. tnc_pib_tc
  19. java中数组和集合的区别以及特性
  20. 1.5 黑群晖安装后洗白的三种方法 教程

热门文章

  1. 一文搞懂CAS,CAS原理分析及ABA问题详解
  2. webpack 中实现自动识别 CSS Modules
  3. 面试中会谈工资的人,一开口就赢了,这几种谈薪资方式,让工资翻倍
  4. 青藤正式加入微软MAPP计划
  5. 校园英语杂志校园英语杂志社校园英语编辑部2022年第17期目录
  6. 文案改写神器软件-文案改编神器
  7. 独家 | 如何为计算机视觉和深度学习安置英伟达?
  8. 大学生家乡主题网页制作 旅游网页设计模板 学生静态网页作业成品 dreamweaver家乡HTML网站制作
  9. 高手在民间,用户体验地图这么画
  10. 第46届世界技能大赛网络系统管理项目湖北省选拔赛赛题-模块C-Cisco