如何基于QPolygon在主多边形内侧绘制间隔0.3m的相同形状
解决方案
你需要实现的是多边形的向内等距偏移效果,直接使用Qt内置的图形路径API即可实现全场景适配,无需手动计算顶点坐标,适配绝大多数凸/凹多边形场景,具体实现如下:
实现逻辑
- 你代码中已经定义了像素和实际距离的换算比例为
12.5/1056m/像素,先把0.3m的物理间距换算为像素偏移量:offset_px = 0.3 / (12.5/1056) ≈ 25.34 - 用
QPainterPath加载原多边形的所有顶点 - 利用
QPainterPathStroker生成对应宽度的描边路径,取描边的内侧边界即可得到等距偏移后的内部多边形 - 方案为Qt原生实现,无需额外引入第三方依赖
修改后完整代码
import sys from sympy import Polygon from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui import QPixmap, QPainter, QColor, QPolygon, QPainterPath, QPainterPathStroker from PyQt5 import QtGui class MyApp(QWidget): def __init__(self): super().__init__() self.window_width, self.window_height = 1200, 800 self.setMinimumSize(self.window_width, self.window_height) layout = QVBoxLayout() self.setLayout(layout) self.pix = QPixmap('image.jpg') self.resize(self.pix.width(), self.pix.height()) self.point = QPoint() self.tab = [] # 预先定义偏移参数:0.3m换算为像素值 self.px_per_m = 1056 / 12.5 self.inner_offset_px = 0.3 * self.px_per_m def paintEvent(self, event): painter = QPainter(self) pen = QtGui.QPen() pen.setColor(QtGui.QColor('red')) pen.setWidth(3) painter.setPen(pen) painter.drawPixmap(QPoint(), self.pix) if not self.point.isNull(): painter.drawPoint(self.point) def mousePressEvent(self, event): if event.buttons() & Qt.LeftButton: self.point = event.pos() self.update() def mouseReleaseEvent(self, event): pen = QtGui.QPen() painter = QPainter(self.pix) if event.button() == Qt.LeftButton: pen.setColor(QtGui.QColor('red')) pen.setWidth(3) painter.setPen(pen) painter.drawPoint(self.point) self.tab.append(self.point) print(self.point.x(), self.point.y()) self.point = QPoint() self.update() if event.button() == Qt.RightButton: # 绘制原多边形 points = QPolygon(self.tab) pen.setColor(QtGui.QColor('red')) painter.setPen(pen) painter.drawPolygon(points) # ========== 新增:生成并绘制内侧等距多边形 ========== # 1. 把原多边形加入QPainterPath path = QPainterPath() path.addPolygon(points) path.closeSubpath() # 2. 生成向内偏移的路径 stroker = QPainterPathStroker() # 描边宽度设为2倍偏移量,因为描边是居中绘制 stroker.setWidth(self.inner_offset_px * 2) stroker.setJoinStyle(Qt.MiterJoin) stroke_path = stroker.createStroke(path) # 取原路径和描边路径的交集,得到向内偏移的多边形路径 inner_path = path.intersected(stroke_path) # 3. 绘制内侧多边形,用蓝色区分 inner_pen = QtGui.QPen(QColor('blue')) inner_pen.setWidth(2) painter.setPen(inner_pen) painter.drawPath(inner_path) # ================================================== # 原有面积计算逻辑保留 polytab = [] for i in self.tab: polytab.append((i.x(), i.y())) print(Polygon(*polytab).area * (12.5 / 1056) * (12.5 / 1056)) print((self.tab[0].x() - self.tab[1].x()) * (12.5 / 1056)) self.tab = [] self.update() if __name__ == '__main__': app = QApplication(sys.argv) app.setStyleSheet('''QWidget{font-size:30px}''') myAPP = MyApp() myAPP.show() try: sys.exit(app.exec_()) except SystemExit: print('Closing Window...')
补充说明
如果需要处理带自交的特殊复杂多边形,可以引入shapely库,调用Polygon(points).buffer(-0.3)方法直接生成偏移后的多边形,适配性更强。
内容的提问来源于stack exchange,提问作者Amen0
相关产品推荐
相关产品推荐

