PyQt5:填补 QPolygon 中的空隙 // 增加 QPolygon 的大小(高度)

3
我有以下的QPolygon: enter image description here 我需要将其高度增加,得到如下的QPolygon: enter image description here 其中,qpolygon的下边界保持不变,在第一幅图中为x1,y1,在第二幅图中仍为x1,y1,而添加在上方的黑色区域应该是qpolygon本身高度的一半(最好是直线,但不太重要)。
为了实现这个目标,我使用了QPolygon的bounding box: poly1_bounding_rect=QPolygonF(poly_1_coords).boundingRect() 以及X0、Y0坐标、宽度和高度,然后使用联合操作与原始多边形进行并集运算。
max_y, min_x, height_, width_ = poly1_bounding_rect.y(), poly1_bounding_rect.x(), poly1_bounding_rect.height(), poly1_bounding_rect.width()
poly1_addition = QPolygonF(
    [QPointF(min_x, max_y), QPointF(min_x, max_y - height_ * .5),
     QPointF(min_x + width_, max_y - height_ * .5),
     QPointF(min_x + width_, max_y)])

然而,这个解决方案留下了一个有孔的 QPolygon,我不确定应该如何填充它们,或者在第一次创建 QPolygon 时就避免这些洞。

非常感谢任何指导,谢谢!

图片描述

以下是一个最小可复现的示例:

import PyQt5
from PyQt5 import QtCore

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


poly_1_coords= [PyQt5.QtCore.QPointF(412.01, 257.98), PyQt5.QtCore.QPointF(372.24, 197.66), PyQt5.QtCore.QPointF(358.88, 230.95), PyQt5.QtCore.QPointF(371.46, 278.4), PyQt5.QtCore.QPointF(381.16, 291.77), PyQt5.QtCore.QPointF(428.34, 308.81), PyQt5.QtCore.QPointF(483.66, 341.84), PyQt5.QtCore.QPointF(648.02, 373.29), PyQt5.QtCore.QPointF(945.05, 386.61), PyQt5.QtCore.QPointF(1087.66, 374.02), PyQt5.QtCore.QPointF(1285.26, 331.05), PyQt5.QtCore.QPointF(1317.34, 304.71), PyQt5.QtCore.QPointF(1345.85, 265.03), PyQt5.QtCore.QPointF(1340.6, 214.96), PyQt5.QtCore.QPointF(1326.19, 197.39), PyQt5.QtCore.QPointF(1303.38, 243.79), PyQt5.QtCore.QPointF(1134.3, 290.19), PyQt5.QtCore.QPointF(1091.57, 306.71), PyQt5.QtCore.QPointF(1067.45, 295.44), PyQt5.QtCore.QPointF(1017.38, 250.09), PyQt5.QtCore.QPointF(993.53, 218.63), PyQt5.QtCore.QPointF(925.89, 219.41), PyQt5.QtCore.QPointF(852.23, 233.31), PyQt5.QtCore.QPointF(723.52, 219.41), PyQt5.QtCore.QPointF(671.51, 309.58), PyQt5.QtCore.QPointF(638.88, 313.37), PyQt5.QtCore.QPointF(583.5, 299.71), PyQt5.QtCore.QPointF(485.61, 240.53), PyQt5.QtCore.QPointF(451.47, 270.88)]

def main():
    app = QApplication(sys.argv)



    scene = QGraphicsScene()
    view = QGraphicsView(scene)
    pen_ = QPen(QColor(0, 20, 255))
    brush_ = QBrush(QColor(0,0,0))

    poly_1 = QPolygonF(poly_1_coords)
    #scene.addPolygon(poly_1,pen_,brush_)

    poly1_bounding_rect = poly_1.boundingRect()
    max_y, min_x, height_, width_ = poly1_bounding_rect.y(), poly1_bounding_rect.x(), poly1_bounding_rect.height(), poly1_bounding_rect.width()

    poly1_addition = QPolygonF(
        [QPointF(min_x, max_y), QPointF(min_x, max_y - height_ * .5),
         QPointF(min_x + width_, max_y - height_ * .5),
         QPointF(min_x + width_, max_y)])

    complete_poly1 = poly_1.united(poly1_addition)




    scene.addPolygon(complete_poly1,pen_,brush_)



    view.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
2个回答

3

假设多边形始终是简单的,没有任何交叉点,则可以执行以下操作:

  • 找到处于最小和最大x(左和右)以及最大y(底)的点;
  • 从上述两个点开始构建两条分开的路径,这些路径将成为顶部和底部边缘;
  • 查找哪个包括底部点,这将意味着它是“底部边缘”;
  • 按照其高度的一半平移边界矩形,并使用其角点作为多边形的其他点;
    poly_1 = QPolygonF(poly_1_coords)
    poly_1_bounding_rect = poly_1.boundingRect()
    # translate the bounding rect by half its height to get the top corners
    poly_1_bounding_rect.translate(
        QPointF(0, -poly_1_bounding_rect.height() * .5))

    # find the left/right/bottom-most points
    left = right = bottom = None
    for point in poly_1_coords:
        if not left or left.x() > point.x():
            left = point
        if not right or right.x() < point.x():
            right = point
        if not bottom or bottom.y() < point.y():
            bottom = point

    # assuming points are in correct order and there is no intersection between
    # lines, get the indexes of the left and right points to build two separate
    # paths, one from the top side, one for the bottom
    leftIndex = poly_1_coords.index(left)
    rightIndex = poly_1_coords.index(right)
    if leftIndex < rightIndex:
        side_a = poly_1_coords[leftIndex:rightIndex + 1]
        side_b = poly_1_coords[rightIndex:] + poly_1_coords[:leftIndex + 1]
    else:
        side_a = poly_1_coords[rightIndex:leftIndex + 1]
        side_b = poly_1_coords[leftIndex:] + poly_1_coords[:rightIndex + 1]

    # look for the bottom point to get the bottom side
    if bottom in side_a:
        final = side_a
    else:
        final = side_b

    # if the first point is also the left, the coordinates are counter clockwise
    # so we add the top corners accordingly, and vice versa
    if final[0] == left:
        final += [poly_1_bounding_rect.topRight(), poly_1_bounding_rect.topLeft()]
    else:
        final += [poly_1_bounding_rect.topLeft(), poly_1_bounding_rect.topRight()]

    item = scene.addPolygon(QPolygonF(final))
    item.setPen(pen_)
    item.setBrush(brush_)

或者,您可以根据需要将顶部添加到翻译中:

    # look for the bottom point to get the bottom side and add the other
    # by translating by half the bounding rect height
    delta = QPointF(0, -poly_1_bounding_rect.height() * .5)
    if bottom in side_a:
        final = side_a + [p + delta for p in side_b]
    else:
        final = side_b + [p + delta for p in side_a]

2

这并不是最优雅的答案,但可以解决问题。我循环遍历初始多边形轮廓点,减少y坐标,并将其与初始多边形合并,从而有效地创建了更接近所需结果。

如果有人提出更优化的解决方案,将被接受!

changed_polygon = QPolygonF()
for adjust in range(1,200):
    temp_polygon= QPolygonF()
    temp_coords_list = []
    for item in poly_1_coords:
        temp_coords_list.append(QPointF(item.x(),item.y()-adjust))
    changed_polygon = changed_polygon.united(QPolygonF(temp_coords_list))

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接