点到线段的最近距离
判断依据
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最近的点, 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; }
标签:ab,return,上离,线段,float,投影,flag,Vector2 From: https://www.cnblogs.com/sailJs/p/17899822.html