相交 - 点是否在三角形内 - 重心法
1) 点在三角形的边上时
AP=AE+AF (向量加法)
设AE=v*AB, AF=u*AC; 则AP=v*AB+u*AC(二元一次方程,u, v为我们引入的变量)
根据向量三点共线定理可知:u+v=1
2) 点在三角形内时
AE不变, 让AF变短一些, 当用u*AC表示AF时, u的值肯定也比1)中小了,所以此时u+v<1
所以点是否在三角形内,就转换为判断u+v<=1
这边利用二元一次方程来处理这个问题:AP=v*AB+u*AC, 其中u, v为未知数
将方程的两边分别点乘向量AB和AC
AP•AB = v*AB•AB + u*AC•AB, 设a=AC•AB, b=AB•AB, e=AP•AB, 则方程可表示成 a*u+b*v=e
AP•AC = v*AB•AC + u*AC•AC, 设c=AC•AC, d=AB•AC, f=AP•AC, 则方程可表示成 c*u+d*v=f
利用矩阵求二元一次方程组的方式,即可求出u, v的值
跟这边是类似的,把x换成u, v换成y就可以了
//重心法判断点是否在三角形内 public static bool IsPointInTriangle2(Vector2 P, Vector2 A, Vector2 B, Vector2 C) { var AB = B - A; var AC = C - A; var AP = P - A; float a = Vector2.Dot(AC, AB); float b = Vector2.Dot(AB, AB); float e = Vector2.Dot(AP, AB); float c = Vector2.Dot(AC, AC); float d = a; //Vector2.Dot(AB, AC); float f = Vector2.Dot(AP, AC); float invDetDown = 1 / (a * d - b * c); float u = (d * e - b * f) * invDetDown; if (u < 0 || u > 1) return false; float v = (-c * e + a * f) * invDetDown; if (v < 0 || v > 1) return false; var result = (u + v) <= 1; return result; }
效果
可以看到日志打印的耗时,重心法比同侧法快一点
测试代码
using System; using UnityEditor; using UnityEngine; public class PointTriTest : CollideTestBase { //三角形3个顶点 public Transform m_A; public Transform m_B; public Transform m_C; public Transform m_P; void Update() { m_IsIntersect = false; if (m_P && m_A && m_B && m_C) { var t1 = DateTime.Now; switch (m_ApiType) { case 1: for (int i = 0; i < m_InvokeCount; ++i) m_IsIntersect = Shape2DHelper.IsPointInTriangle(m_P.position, m_A.position, m_B.position, m_C.position); break; case 2: for (int i = 0; i < m_InvokeCount; ++i) m_IsIntersect = Shape2DHelper.IsPointInTriangle2(m_P.position, m_A.position, m_B.position, m_C.position); break; } CheckTimeCost(t1, 2); } } private void OnDrawGizmos() { if (m_P && m_A && m_B && m_C) { if (m_IsIntersect) { Gizmos.color = Color.red; Gizmos.DrawLine(m_A.position, m_B.position); Gizmos.DrawLine(m_B.position, m_C.position); Gizmos.DrawLine(m_C.position, m_A.position); Gizmos.color = Color.white; } else { Gizmos.DrawLine(m_A.position, m_B.position); Gizmos.DrawLine(m_B.position, m_C.position); Gizmos.DrawLine(m_C.position, m_A.position); } } } }
参考
判断点是否在三角形内 - 翰墨小生 - 博客园 (cnblogs.com)
几种方法判断平面点在三角形内_判断点在三角形内-CSDN博客
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2022-11-22 Sprite的几个属性的解释