基于Python的两点视距验证:判断矩形障碍物是否遮挡视线
Python 两点视距遮挡判断(矩形障碍物)
核心思路
要验证两点间视距是否被矩形遮挡,本质是判断两点连线(线段)是否与矩形存在交集,包括两种核心情况:
- 任一站点位于矩形内部(直接被障碍物包裹)
- 站点连线与矩形的四条边中任意一条相交(连线穿过障碍物)
代码实现
辅助工具函数
def point_in_rect(point, x_min, x_max, y_min, y_max): """判断点是否在矩形范围内(含边界)""" x, y = point return x_min <= x <= x_max and y_min <= y <= y_max def ccw(A, B, C): """计算三点叉积,判断转向:正=逆时针,负=顺时针,0=共线""" return (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]) def segments_intersect(A, B, C, D): """判断两条线段AB和CD是否相交(含端点重合、共线重叠情况)""" ccw1 = ccw(A, B, C) ccw2 = ccw(A, B, D) ccw3 = ccw(C, D, A) ccw4 = ccw(C, D, B) # 跨立相交(两条线段互相穿过对方) if (ccw1 * ccw2 < 0) and (ccw3 * ccw4 < 0): return True # 端点落在另一条线段上的情况 if ccw1 == 0 and point_in_rect(C, min(A[0], B[0]), max(A[0], B[0]), min(A[1], B[1]), max(A[1], B[1])): return True if ccw2 == 0 and point_in_rect(D, min(A[0], B[0]), max(A[0], B[0]), min(A[1], B[1]), max(A[1], B[1])): return True if ccw3 == 0 and point_in_rect(A, min(C[0], D[0]), max(C[0], D[0]), min(C[1], D[1]), max(C[1], D[1])): return True if ccw4 == 0 and point_in_rect(B, min(C[0], D[0]), max(C[0], D[0]), min(C[1], D[1]), max(C[1], D[1])): return True return False
视距遮挡判断主函数
def is_line_of_sight_blocked(sta1, sta2, x_min, x_max, y_min, y_max): """判断两点间视距是否被矩形障碍物遮挡""" # 获取站点坐标(适配题目中sta1.position的调用方式) p1 = sta1.position p2 = sta2.position # 情况1:任一站点在矩形内部,直接判定遮挡 if point_in_rect(p1, x_min, x_max, y_min, y_max) or point_in_rect(p2, x_min, x_max, y_min, y_max): return True # 定义矩形的四条边线段 rect_edges = [ ((x_min, y_min), (x_max, y_min)), # 底边 ((x_max, y_min), (x_max, y_max)), # 右边 ((x_max, y_max), (x_min, y_max)), # 顶边 ((x_min, y_max), (x_min, y_min)) # 左边 ] # 情况2:检查连线是否与矩形任意一条边相交 for edge in rect_edges: if segments_intersect(p1, p2, edge[0], edge[1]): return True # 两种情况都不满足,视距畅通 return False
测试示例
# 模拟站点类(匹配题目中sta1.position的调用逻辑) class Station: def __init__(self, x, y): self._position = (x, y) @property def position(self): return self._position # 实例化题目给定的站点和矩形参数 sta1 = Station(1, 5) sta2 = Station(5, 1) x_min, x_max = 3, 4 y_min, y_max = 2, 3 # 执行判断并输出结果 blocked = is_line_of_sight_blocked(sta1, sta2, x_min, x_max, y_min, y_max) print(f"视距是否被遮挡: {blocked}") # 输出:True(连线穿过矩形的(3,3)和(4,2)顶点)
关键说明
- 叉积计算(
ccw函数)是线段相交检测的核心,能高效判断点的相对位置关系 - 函数覆盖了所有边界情况:端点重合、线段共线重叠、站点在障碍物内部等
- 完全适配题目中给定的
sta1.position调用方式,无需修改现有站点类结构
内容的提问来源于stack exchange,提问作者searcher__dm01
相关产品推荐
相关产品推荐

