点到线段的最近距离, 点与线段的位置关系 - 点乘投影方式
点到线段的最近距离
判断依据
1) 投影结果<0,则线段端点a离p最近
2) 投影结果>线段ab的长度,则线段端点b离p最近
3) 否则p在线段上的垂点为最近点
p与ab不共线时
1) p在线段两侧
2-a) p在线段内侧
2-b) p在线段内侧2
p与ab共线时
1) p在线段两侧
2-a) p在线段内侧
2-b) p在线段内侧
注意:判断内侧和外侧并不需要区分p与ab共线
//线段上离p最近的点, flag: -1_表示最近点为a, 1_表示最近点为b, 0_表示最近点为线段中间的点 public static Vector2 GetSegmentClosestPoint(Vector2 a, Vector2 b, Vector2 p, out int flag) { flag = 0; var ab = b - a; float abSqrLen = ab.sqrMagnitude; if (abSqrLen < float.Epsilon) //ab重合 return a; var ap = p - a; // 计算投影长度,并单位化到[0, 1](需要额外除以ab的长度)。因此这里就直接除以长度的平方了。 float proj = Vector2.Dot(ap, ab) / abSqrLen; if (proj < 0) { flag = -1; return a; } if (proj > 1) { flag = 1; return b; } return a + ab * proj; }
求最近距离
//点到线段的距离, flag: -1_表示最近点为a, 1_表示最近点为b, 0_表示最近点为线段中间的点 public static float PointToSegmentDistance2(Vector2 a, Vector2 b, Vector2 p, out int flag) { var c = GetSegmentClosestPoint(a, b, p, out flag); var pc = c - p; return pc.magnitude; }
点与线段的位置关系
判断依据:投影结果<0或>线段ab的长度,则在线段的两侧;否则在线段内侧
//点与线段的位置关系: -1_外侧, 0_与端点重合, 1_内侧; isA: 是否点A那边的外侧或是否和点A重合 public static int GetPointSideOfSegment2(Vector2 p, Vector2 a, Vector2 b, out bool isA) { isA = false; var ab = b - a; var ap = p - a; float abSqrLen = ab.sqrMagnitude; // 计算投影长度,并单位化到[0, 1](需要额外除以ab的长度)。因此这里就直接除以长度的平方了。 float proj = Vector2.Dot(ap, ab) / abSqrLen; if (proj < 0) { isA = true; return -1; } if (proj > 1) { return -1; } //点和线段端点重合时 float apSqrLen = ap.sqrMagnitude; if (apSqrLen < float.Epsilon) { isA = true; return 0; } var bp = p - b; float bpSqrLen = bp.sqrMagnitude; if (bpSqrLen < float.Epsilon) return 0; return 1; }
分类:
2d碰撞检测 / 1_点
, 2d碰撞检测
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-12-21 使用PropertyDrawer来实现ReorderableList条目高度可变