QPolygons 边缘的交点/获取 QPolygon 边缘上的所有点 [英] Intersection of QPolygons' edges / Getting all the points on Qpolygon's Edge

查看:39
本文介绍了QPolygons 边缘的交点/获取 QPolygon 边缘上的所有点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个封闭的 QPolygonF,我需要找出它们的边缘(即它们的轮廓)是否相交.由于这些多边形可能相互包含,因此仅查看多边形的交点是行不通的.

I have two closed QPolygonFs and I need to find out whether their edges (that is their contours) intersect. As these polygons may be included in one another, looking simply at the intersection of the polygons does not work.

PyQt5 有一个内置函数来检查一个点是否在多边形的轮廓线上,contains(QPointF(x,y)).因此,对 QPolygonF 中的每个点使用这种方法似乎很明显:

PyQt5 has a built-in function for checking if a point is on the contourline of the polygon, contains(QPointF(x,y)). Thus, it seemed obvious to use this method for each point in the 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

但是,由于我的 QPolygon 仅由它们的角点组成,所以这不起作用.

However, as my QPolygons are made up only of their cornerpoints, this does not work.

获取构成 QPolygonF 轮廓的所有点并在其上运行相同的函数(iso polygon1.size())似乎是合乎逻辑的下一步.

It seems like the logical next step to get all of the points that make up the QPolygonF's contour, and run the same function on it (iso polygon1.size()).

应该怎么做呢?

为了更好地说明这个概念,函数应该为下图中的第 1、第 4 和第 5 个插图返回 1.

To illustrate the concept a bit better, the function should return 1 for the 1st, 4th and 5th illustration in the image below.

在此处添加了一些代码以显示某些建议的答案不起作用.

Added some code here to show that some of the suggested answers do not work.

输入:

@alec 建议的功能:

Function suggested by @alec:

def check_if_two_polygons_share_contour(polygon1,polygon2):
    polygon = polygon1.intersected(polygon2)
    return polygon and polygon not in (polygon1, polygon2)

@Yves Daoust 建议的逻辑:

Logic suggested by @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 建议的解决方案:

The solution as suggested by 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)

and ofcourse one needs to edit check_if_two_polygons_share_contour in the UI file to include polycoords iso polygons 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

推荐答案

如果你需要验证拦截但不是包含,你必须同时检查;以下内容就足够了:

If you need to verify the interception but not the containement, you have to check for both; the following should suffice:

def check_if_two_polygons_share_contour(p1, p2):
    path1 = QPainterPath()
    path1.addPolygon(p1)
    path2 = QPainterPath()
    path2.addPolygon(p2)
    return path1.intersects(path2) and not (
        path1.contains(path2) or path2.contains(path1))

这篇关于QPolygons 边缘的交点/获取 QPolygon 边缘上的所有点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆