我有两个封闭的 QPolygonF,我需要找出它们的边缘(即它们的轮廓)是否相交。由于这些多边形可能相互包含,因此仅查看多边形的交点是行不通的。
PyQt5 有一个内置函数来检查一个点是否在多边形的轮廓线上, contains(QPointF(x,y))。因此,对 QPolygonF 中的每个点使用这种方法似乎很明显:
def check_if_two_polygons_share_contour(polygon1,polygon2):
for i in range(polygon1.size()):
if polygon2.contains(QPointF(polygon1[i].x(),polygon1[i].y()))
print("polygon contours touch!")
return 1
return 0
但是,由于我的 QPolygons 仅由它们的角点组成,因此这是行不通的。
获取构成 QPolygonF 轮廓的所有点并在其上运行相同的函数(iso polygon1.size())似乎是合乎逻辑的下一步。
应该怎么做呢?
为了更好地说明这个概念,该函数应为下图中的第 1、第 4 和第 5 个插图返回 1。
编辑:在此处添加了一些代码以显示某些建议的答案不起作用。
输入:
@alec 建议的功能:
def check_if_two_polygons_share_contour(polygon1,polygon2):
polygon = polygon1.intersected(polygon2)
return polygon and polygon not in (polygon1, polygon2)
@Yves Daoust 建议的逻辑:
def line_intersection(line1, line2):
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
div = det(xdiff, ydiff)
if div == 0:
# print("Weak Exception 67892: Lines do not interact (function line_intersection). Return 9999999,9999999")
return 9999999, 9999999
# raise Exception('lines do not intersect')
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
return x, y
def check_if_two_polygons_share_contour(polygon1,polygon2):
for i in range(polygon1.size()):
if i != polygon1.size() - 1:
j = i + 1
point1 = [polygon1[i].x(), polygon1[i].y()]
point2 = [polygon1[j].x(), polygon1[j].y()]
for k in range(polygon2.size()):
if k != polygon2.size() - 1:
l = k + 1
point3 = [polygon2[k].x(), polygon2[k].y()]
point4 = [polygon2[l].x(), polygon2[l].y()]
value_ = line_intersection([point1, point2], [point3, point4])
if value_ != (9999999, 9999999):
return 1
用户界面
import PyQt5
from PyQt5 import QtCore
import cv2
import numpy as np
import math
from scipy.ndimage.interpolation import rotate
import sys
import PyQt5
from PyQt5.QtCore import *#QPointF, QRectF
from PyQt5.QtGui import *#QPainterPath, QPolygonF, QBrush,QPen,QFont,QColor, QTransform
from PyQt5.QtWidgets import *#QApplication, QGraphicsScene, QGraphicsView, QGraphicsSimpleTextItem
import math
polycoords1_main_object=[PyQt5.QtCore.QPointF(1162.12, 302.37), PyQt5.QtCore.QPointF(1141.65, 304.13), PyQt5.QtCore.QPointF(1133.45, 307.05), PyQt5.QtCore.QPointF(1124.1, 315.83), PyQt5.QtCore.QPointF(1116.5, 332.2), PyQt5.QtCore.QPointF(1109.48, 365.54), PyQt5.QtCore.QPointF(1099.53, 396.53), PyQt5.QtCore.QPointF(1096.02, 419.93), PyQt5.QtCore.QPointF(1096.62, 457.94), PyQt5.QtCore.QPointF(1100.7, 464.96), PyQt5.QtCore.QPointF(1110.06, 471.98), PyQt5.QtCore.QPointF(1123.51, 471.4), PyQt5.QtCore.QPointF(1129.36, 467.3), PyQt5.QtCore.QPointF(1137.55, 466.13), PyQt5.QtCore.QPointF(1146.91, 466.72), PyQt5.QtCore.QPointF(1155.1, 470.23), PyQt5.QtCore.QPointF(1163.88, 464.38), PyQt5.QtCore.QPointF(1170.3, 450.93), PyQt5.QtCore.QPointF(1170.89, 431.62), PyQt5.QtCore.QPointF(1165.63, 414.07), PyQt5.QtCore.QPointF(1215.0, 448.0), PyQt5.QtCore.QPointF(1227.0, 443.0), PyQt5.QtCore.QPointF(1249.0, 388.0), PyQt5.QtCore.QPointF(1249.0, 362.0), PyQt5.QtCore.QPointF(1240.0, 336.0), PyQt5.QtCore.QPointF(1234.0, 310.0), PyQt5.QtCore.QPointF(1226.0, 288.0), PyQt5.QtCore.QPointF(1227.0, 275.0), PyQt5.QtCore.QPointF(1220.0, 257.0), PyQt5.QtCore.QPointF(1197.0, 247.0), PyQt5.QtCore.QPointF(1174.0, 249.0), PyQt5.QtCore.QPointF(1168.0, 260.0), PyQt5.QtCore.QPointF(1162.0, 278.0), PyQt5.QtCore.QPointF(1179.0, 273.0), PyQt5.QtCore.QPointF(1161.0, 287.0), PyQt5.QtCore.QPointF(1159.0, 291.0)]
polycoords2_secondary_not_touching=[PyQt5.QtCore.QPointF(1234.0, 395.0), PyQt5.QtCore.QPointF(1228.0, 411.0), PyQt5.QtCore.QPointF(1229.0, 417.0), PyQt5.QtCore.QPointF(1209.0, 408.0), PyQt5.QtCore.QPointF(1212.0, 392.0), PyQt5.QtCore.QPointF(1214.0, 390.0)]
polycoords3_secondary_touching = [PyQt5.QtCore.QPointF(1179.0, 401.0), PyQt5.QtCore.QPointF(1169.0, 407.0), PyQt5.QtCore.QPointF(1157.0, 424.0), PyQt5.QtCore.QPointF(1170.0, 448.0), PyQt5.QtCore.QPointF(1178.0, 446.0), PyQt5.QtCore.QPointF(1184.0, 442.0), PyQt5.QtCore.QPointF(1193.0, 434.0), PyQt5.QtCore.QPointF(1193.0, 421.0), PyQt5.QtCore.QPointF(1189.0, 412.0)]
polycoords4_secondary_touching_barely = [PyQt5.QtCore.QPointF(1116.0, 335.0), PyQt5.QtCore.QPointF(1115.0, 346.0), PyQt5.QtCore.QPointF(1111.0, 355.0), PyQt5.QtCore.QPointF(1107.0, 378.0), PyQt5.QtCore.QPointF(1129.0, 381.0), PyQt5.QtCore.QPointF(1130.0, 375.0), PyQt5.QtCore.QPointF(1139.0, 358.0), PyQt5.QtCore.QPointF(1139.0, 347.0), PyQt5.QtCore.QPointF(1141.0, 341.0), PyQt5.QtCore.QPointF(1141.0, 341.0)]
polygon1_main_object= QPolygonF(polycoords1_main_object)
polygon2_secondary_not_touching=QPolygonF(polycoords2_secondary_not_touching)
polygon3_secondary_touching = QPolygonF(polycoords3_secondary_touching)
polygon4_secondary_touching_barely = QPolygonF(polycoords4_secondary_touching_barely)
def main():
app = QApplication(sys.argv)
scene = QGraphicsScene()
view = QGraphicsView(scene)
a = check_if_two_polygons_share_contour(polygon1_main_object,polygon2_secondary_not_touching)
if a == 1:
print("polygon1_main_object and polygon2 touch")
else:
print("polygon1_main_object and polygon2 do not touch")
a = check_if_two_polygons_share_contour(polygon1_main_object, polygon3_secondary_touching)
if a == 1:
print("polygon1_main_object and polygon3 touch")
else:
print("polygon1_main_object and polygon3do not touch")
a = check_if_two_polygons_share_contour(polygon1_main_object, polygon4_secondary_touching_barely)
if a == 1:
print("polygon1_main_object and polygon4 touch")
else:
print("polygon1_main_object and polygon4 do not touch")
scene.addPolygon(polygon1_main_object,QPen(QColor(0, 20, 0)))
scene.addPolygon(polygon2_secondary_not_touching, QPen(QColor(240, 20, 0)))
scene.addPolygon(polygon3_secondary_touching, QPen(QColor(0, 20, 250)))
scene.addPolygon(polygon4_secondary_touching_barely, QPen(QColor(0, 250, 8)))
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
musicamante 建议的解决方案:
def return_path_from_points(poly_coords_in):
path = QPainterPath()
path.moveTo(poly_coords_in[0])
for points in poly_coords_in:
path.lineTo(points)
path.lineTo(poly_coords_in[0])
return path
def check_if_two_polygons_share_contour(polygon_coords_a,polygon_coords_b):
path_a = return_path_from_points(polygon_coords_a)
path_b = return_path_from_points(polygon_coords_b)
if path_a.intersects(path_b):
return 1
else:
return 0
当然需要在 UI 文件中编辑 check_if_two_polygons_share_contour 以包含 polycoords iso 多边形check_if_two_polygons_share_contour(polygon1_main_object,polygon2_secondary_not_touching) ---> check_if_two_polygons_share_contour(polycoords1_main_object, polycoords2_secondary_not_touching)
所有情况的输出:
polygon1_main_object and polygon2 touch
polygon1_main_object and polygon3 touch
polygon1_main_object and polygon4 touch
正确的输出:
polygon1_main_object and polygon2 do not touch
polygon1_main_object and polygon3 touch
polygon1_main_object and polygon4 touch