I have the following QPolygon:
and I need to increase its size in height to get a following QPolygon:
whereas the lower boundary of the qpolygon stays in the same location, that is x1,y1 in the first image, is still x1,y1 in the second image and the black area that is added above should be half of the height of the qpolygon itself (ideally with a straight line, but not too important)
To do so, I took the bounding box of the QPolygon
poly1_bounding_rect=QPolygonF(poly_1_coords).boundingRect()
and the X0,Y0 coordinates, as well as width and height, and then made the polygon addition to be united with the original polygon
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)])
However this solution leaves the QPolygon to be with holes and I am unsure how should I fill them in, or alternatively create a QPolygon without these wholes in the first place.
Any guidance is highly appreciated, thanks!
Here's a minimum reproducible example:
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()
Assuming that the polygon is always a simple one, without any intersection, you can do the following:
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_)
Alternatively, you can add the top side by translating it as required:
# 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]