平面坐标系中判断点P是否在线段上AB上的常用方法总结

在平面坐标系中,判断点 P 是否在线段 AB 上,可以通过以下 ​​5种常用算法​​ 实现,涵盖数学原理、实现步骤和代码示例:


​​1. 参数化方程法(推荐)​​

​​原理​​

将点 P 表示为线段 AB 的线性插值,检查参数 t 是否在 0,1 范围内且满足共线性。

​​步骤​​
  1. ​​共线性检验​ ​:

    计算向量 AP 和 AB 的叉积(二维叉积为标量):

    Cross=(xP−xA)(yB−yA)−(yP−yA)(xB−xA)

    若 ∣Cross∣>ϵ(微小阈值,如 10−6),则点不共线。

  2. ​​参数 t 检查​ ​:

    若共线,计算参数:

    t=∥AB∥2(xP−xA)(xB−xA)+(yP−yA)(yB−yA)

    若 t∈0,1,则 P 在线段上。

​​代码实现​​
复制代码

python

复制

复制代码
def is_point_on_segment(A, B, P, epsilon=1e-6):
    cross = (P[0] - A[0]) * (B[1] - A[1]) - (P[1] - A[1]) * (B[0] - A[0])
    if abs(cross) > epsilon:  # 不共线
        return False
    dot = (P[0] - A[0]) * (B[0] - A[0]) + (P[1] - A[1]) * (B[1] - A[1])
    t = dot / ((B[0] - A[0])**2 + (B[1] - A[1])**2)
    return 0 <= t <= 1

​​2. 距离和检验法​​

​​原理​​

若点 P 在线段 AB 上,则 AP+PB=AB。

​​步骤​​
  1. 计算距离 AP、PB、AB。
  2. 检查 ∣AP+PB−AB∣<ϵ。
​​代码实现​​
复制代码

python

复制

复制代码
def is_point_on_segment_distance(A, B, P, epsilon=1e-6):
    d_AB = ((B[0] - A[0])**2 + (B[1] - A[1])**2)**0.5
    d_AP = ((P[0] - A[0])**2 + (P[1] - A[1])**2)**0.5
    d_PB = ((B[0] - P[0])**2 + (B[1] - P[1])**2)**0.5
    return abs(d_AP + d_PB - d_AB) < epsilon

​​3. 直线方程代入法​​

​​原理​​

将 P 的坐标代入线段 AB 的直线方程,检查是否满足且位于端点之间。

​​步骤​​
  1. 若线段非垂直(xA=xB),检查斜率一致性:xP−xAyP−yA=xB−xAyB−yA
  2. 若线段垂直(xA=xB),检查 xP=xA 且 yP 在 yA,yB 内。
  3. 最后检查 P 的坐标是否在 A 和 B 的范围内。
​​代码实现​​
复制代码

python

复制

复制代码
def is_point_on_segment_equation(A, B, P, epsilon=1e-6):
    if abs(B[0] - A[0]) < epsilon:  # 垂直线段
        return abs(P[0] - A[0]) < epsilon and min(A[1], B[1]) <= P[1] <= max(A[1], B[1])
    else:
        slope = (B[1] - A[1]) / (B[0] - A[0])
        on_line = abs((P[1] - A[1]) - slope * (P[0] - A[0])) < epsilon
        in_range = min(A[0], B[0]) <= P[0] <= max(A[0], B[0])
        return on_line and in_range

​​4. 边界框快速排除法​​

​​原理​​

先检查 P 是否在线段 AB 的轴对齐包围盒(AABB)内,再结合共线性检验。

​​步骤​​
  1. 检查 P 的坐标是否满足:min(xA,xB)≤xP≤max(xA,xB)min(yA,yB)≤yP≤max(yA,yB)
  2. 若在包围盒内,再进行共线性检验(如方法1)。
​​代码实现​​
复制代码

python

复制

复制代码
def is_point_on_segment_bbox(A, B, P, epsilon=1e-6):
    in_bbox = (min(A[0], B[0]) <= P[0] <= max(A[0], B[0])) and \
              (min(A[1], B[1]) <= P[1] <= max(A[1], B[1]))
    if not in_bbox:
        return False
    cross = (P[0] - A[0]) * (B[1] - A[1]) - (P[1] - A[1]) * (B[0] - A[0])
    return abs(cross) < epsilon

​​5. 面积法(三角形面积为零)​​

​​原理​​

若 P 在线段 AB 上,则三角形 ABP 的面积为 0。

​​步骤​​
  1. 计算叉积的绝对值(即平行四边形面积):Area=∣(xA(yB−yP)+xB(yP−yA)+xP(yA−yB))∣
  2. 若 Area<ϵ,则共线,再检查坐标范围。
​​代码实现​​
复制代码

python

复制

复制代码
def is_point_on_segment_area(A, B, P, epsilon=1e-6):
    area = abs(A[0]*(B[1] - P[1]) + B[0]*(P[1] - A[1]) + P[0]*(A[1] - B[1]))
    if area > epsilon:
        return False
    return min(A[0], B[0]) <= P[0] <= max(A[0], B[0]) and \
           min(A[1], B[1]) <= P[1] <= max(A[1], B[1])

​​算法对比​​

方法 优点 缺点 适用场景
​​参数化方程法​​ 高精度,直接计算参数 t 需计算叉积和点积 通用场景(推荐)
​​距离和检验法​​ 直观易理解 浮点误差敏感 快速近似判断
​​直线方程法​​ 显式处理垂直/水平线段 需分情况处理斜率 已知线段方向时
​​边界框法​​ 快速排除明显不在的点 需额外共线性检验 预处理优化
​​面积法​​ 数学简洁 计算面积后仍需范围检查 教学演示

​​总结​​

  • ​推荐方法1(参数化方程法)​:综合精度和效率,适合大多数场景。
  • ​性能优化​:先用方法4(边界框法)快速排除,再使用方法1精确判断。
  • ​特殊处理​:垂直线段或水平线段可简化计算(如直接比较坐标)。

通过上述方法,可灵活应对不同需求下的点与线段位置关系判断问题。

相关推荐
应用市场10 分钟前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理
小lo想吃棒棒糖10 分钟前
把 启元机器人Q1 的训练搬到昇腾 910B:从 MuJoCo 到 PPO 的一次完整迁移
人工智能·python·机器人·昇腾·具身智能
weixin_3077791318 分钟前
RAG 级联失效分析——面试中的错误归因艺术
人工智能·python·面试·职场和发展
AI创界者20 分钟前
Python 进阶实战(十八):API 网关安全与异步鉴权中间件 —— 基于 AsyncIO 的 JWT 零拷贝验权与动态黑名单过滤
人工智能·python·aigc
前端精髓29 分钟前
学会调用Qwen3.7-通用文本向量
python
OxYGC33 分钟前
[工程] PHP2Shell 漏洞解析:两条 PHP 内核 RCE,为什么应用层的防护全部失效
android·开发语言·php
小徐不徐说36 分钟前
数据库存储基础:理解表结构、主键、事务与 BLOB
开发语言·数据库·c++·qt·程序设计
草莓熊Lotso1 小时前
【C++ 基于微服务的即时通讯系统】网关基建:cpp-httplib 与 WebSocketpp 从入门到实战
linux·开发语言·数据库·c++·redis·微服务·云原生
李纲明1 小时前
WordPress 媒体库上传失败或一直转圈:先核 PHP 上传限制与目录权限,再查安全插件与对象存储
运维·开发语言·安全·php·wordpress·媒体库·devdiy
第九序言T9 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理