交点 - 两线段(直线)交点 - 直线方程组方式
//求两直线交点 - 直线方程组方式 public static bool IsTwoLineIntersect(Vector2 A, Vector2 B, Vector2 C, Vector2 D, out Vector2 point) { point = Vector2.zero; /** 1 解线性方程组, 求线段交点. **/ //a*x+b*y=e float a = (B.y - A.y); //AB.y float b = (A.x - B.x); //BA.x float e = A.x * B.y - A.y * B.x; //A×B //c*x+d*y=f float c = (C.y - D.y); //DC.y float d = (D.x - C.x); //CD.x float f = D.x * C.y - D.y * C.x; //D×C float detDown = a * d - b * c; //AB×CD // 叉乘结果为0, 则平行或共线, 不相交 if (Mathf.Approximately(detDown, 0)) //float.Epsilon return false; // 克莱姆法则解出方程组, (x, y)即为交点 float invDetDown = 1 / detDown; float x = (d * e - b * f) * invDetDown; float y = (a * f - c * e) * invDetDown; point = new Vector2(x, y); return true; }
//求两线段交点 - 直线方程组方式 public static bool IsTwoSegmentIntersect3(Vector2 A, Vector2 B, Vector2 C, Vector2 D, out Vector2 point) { if (IsTwoLineIntersect(A, B, C, D, out point)) { float x = point.x; float y = point.y; if ((x - A.x) * (x - B.x) <= 0 && (y - A.y) * (y - B.y) <= 0 // 交点在线段1上 && (x - C.x) * (x - D.x) <= 0 && (y - C.y) * (y - D.y) <= 0) // 且交点也在线段2上 { return true; } } point = Vector2.zero; return false; }
效果
投影法慢很多
测试代码
using System; using UnityEditor; using UnityEngine; public class SegmentTest : CollideTestBase { //线段1的顶点A, B public Transform m_A; public Transform m_B; //线段2的顶点C, D public Transform m_C; public Transform m_D; public Vector2 m_Point; //显示交点用 private Vector3 m_CubeSize = new Vector3(0.02f, 0.02f, 0.01f); void Update() { m_IsIntersect = false; m_Point = Vector2.zero; if (m_A && m_B && m_C && m_D) { var t1 = DateTime.Now; switch (m_ApiType) { case 1: for (int i = 0; i < m_InvokeCount; ++i) m_IsIntersect = Shape2DHelper.IsTwoSegmentIntersect(m_A.position, m_B.position, m_C.position, m_D.position); break; case 2: for (int i = 0; i < m_InvokeCount; ++i) m_IsIntersect = Shape2DHelper.IsTwoSegmentIntersect2(m_A.position, m_B.position, m_C.position, m_D.position, out m_Point); break; case 3: for (int i = 0; i < m_InvokeCount; ++i) m_IsIntersect = Shape2DHelper.IsTwoSegmentIntersect3(m_A.position, m_B.position, m_C.position, m_D.position, out m_Point); break; } CheckTimeCost(t1, 3); } } private void OnDrawGizmos() { if (m_A && m_B && m_C && m_D) { if (m_IsIntersect) { Gizmos.color = Color.red; Gizmos.DrawLine(m_A.position, m_B.position); Gizmos.DrawLine(m_C.position, m_D.position); Gizmos.color = Color.green; float handleSize = HandleUtility.GetHandleSize(m_Point) * 0.1f; m_CubeSize.Set(handleSize, handleSize, 0.01f); Gizmos.DrawCube(m_Point, m_CubeSize); Gizmos.color = Color.white; } else { Gizmos.DrawLine(m_A.position, m_B.position); Gizmos.DrawLine(m_C.position, m_D.position); } } } }
参考
求两条线段交点zz - 马语者 - 博客园 (cnblogs.com)
分类:
2d碰撞检测 / 2_直线
, 2d碰撞检测
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界