点到线段的最短距离需先判断垂足是否在线段上:计算投影参数t,t<0时取p1,t>1时取p2,否则用点到直线距离公式。

点到线段的最短距离不是点到直线的距离
直接套用点到直线距离公式(如 np.linalg.norm(np.cross(p2-p1, p1-p0)) / np.linalg.norm(p2-p1))会出错——它算的是点到**无限长直线**的距离,而线段有端点约束。当垂足落在线段外时,最短距离其实是点到较近端点的距离。
用向量投影判断垂足是否在线段上
核心是把问题拆成两步:先求点 p0 到过 p1、p2 的直线的投影点,再检查该投影是否落在线段 [p1, p2] 内。关键看参数 t = np.dot(p0 - p1, p2 - p1) / np.dot(p2 - p1, p2 - p1):
- 若
t ,垂足在 <code>p1左侧 → 最短距离为np.linalg.norm(p0 - p1) - 若
t >= 1,垂足在p2右侧 → 最短距离为np.linalg.norm(p0 - p2) - 若
0 ,垂足在线段内部 → 距离为 <code>np.linalg.norm(p0 - (p1 + t * (p2 - p1)))
注意浮点精度和零向量陷阱
当 p1 和 p2 几乎重合时,np.dot(p2 - p1, p2 - p1) 接近零,会导致除零或数值不稳定:
- 务必先检查
np.allclose(p1, p2),若是退化线段,直接返回np.linalg.norm(p0 - p1) -
t的计算建议用np.clip(t, 0, 1)替代手动判断边界,更鲁棒(尤其在t因浮点误差略超 [0,1] 时) - 避免用
==比较浮点t是否等于 0 或 1
一个可直接复用的 NumPy 函数
下面函数输入均为 shape (2,) 的 np.ndarray,返回标量距离:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
立即学习“Python免费学习笔记(深入)”;
def point_to_segment_dist(p0, p1, p2):
if np.allclose(p1, p2):
return np.linalg.norm(p0 - p1)
seg_vec = p2 - p1
seg_len_sq = np.dot(seg_vec, seg_vec)
t = np.clip(np.dot(p0 - p1, seg_vec) / seg_len_sq, 0, 1)
proj = p1 + t * seg_vec
return np.linalg.norm(p0 - proj)
调用示例:point_to_segment_dist(np.array([3,2]), np.array([0,0]), np.array([2,2])) 返回约 0.707;若把 p0 换成 [-1,-1],则返回 np.sqrt(2)(到 p1 的距离)。
真正容易被忽略的是:这个逻辑不依赖坐标系方向,但所有点必须是同一坐标系下的二维向量;三维点也适用,只需确保输入是 (3,) 向量且用 np.linalg.norm 计算欧氏距离。

















