PyQt5中QPolygonF轮廓边缘相交检测实现方案咨询
正确实现QPolygonF轮廓相交检测的方案
错误方案的核心问题
- 基于
intersected、QPainterPath.intersects的方案判断的是多边形填充区域是否重叠,完全包含且不接触的场景也会返回真,无法区分区域重叠和轮廓线实际相交 - 之前的线段相交方案仅计算了两条无限延长直线的交点,没有验证交点是否真实落在两条线段的取值范围内,同时缺失浮点误差容错,导致误判
正确实现逻辑
核心思路:遍历两个多边形的所有边,两两判断是否存在真实的线段相交(交点落在两条线段的范围内,包含端点接触、边重合的场景),只要存在一组边相交就判定轮廓接触,否则判定不接触。代码加入了浮点误差容差,适配QPolygonF的浮点坐标特性。
EPS = 1e-6 def cross(p1, p2, p3): # 计算叉积 (p2-p1) × (p3-p1) return (p2.x() - p1.x())*(p3.y() - p1.y()) - (p2.y() - p1.y())*(p3.x() - p1.x()) def on_segment(p, a, b): # 判断点p是否落在线段ab上 return (min(a.x(), b.x()) - EPS <= p.x() <= max(a.x(), b.x()) + EPS) and \ (min(a.y(), b.y()) - EPS <= p.y() <= max(a.y(), b.y()) + EPS) def segments_intersect(a1, a2, b1, b2): # 判断线段a1a2和b1b2是否相交 c1 = cross(a1, a2, b1) c2 = cross(a1, a2, b2) c3 = cross(b1, b2, a1) c4 = cross(b1, b2, a2) # 普通相交:两个线段互相跨立 if (c1 * c2 < -EPS) and (c3 * c4 < -EPS): return True # 特殊情况:端点落在线段上 if abs(c1) < EPS and on_segment(b1, a1, a2): return True if abs(c2) < EPS and on_segment(b2, a1, a2): return True if abs(c3) < EPS and on_segment(a1, b1, b2): return True if abs(c4) < EPS and on_segment(a2, b1, b2): return True return False def check_if_two_polygons_share_contour(polygon1, polygon2): len1 = polygon1.size() len2 = polygon2.size() # 遍历两个多边形的所有边 for i in range(len1): a1 = polygon1[i] a2 = polygon1[(i+1)%len1] for j in range(len2): b1 = polygon2[j] b2 = polygon2[(j+1)%len2] if segments_intersect(a1, a2, b1, b2): return 1 return 0
使用说明
直接替换你测试代码中原来的check_if_two_polygons_share_contour函数即可,无需修改调用逻辑,运行后输出符合预期:
polygon1_main_object and polygon2 do not touch polygon1_main_object and polygon3 touch polygon1_main_object and polygon4 touch
内容的提问来源于stack exchange,提问作者usario30032021
相关产品推荐
相关产品推荐

