使用贝塞尔曲线形状检测矩形与项目之间的碰撞

时间:2018-04-30 15:56:41

标签: python pyqt pyqt4 pyqt5 qgraphicsitem

我需要精确检测矩形项与另一个具有贝塞尔曲线形状的项之间的碰撞。当我将矩形与贝塞尔曲线形状的底部碰撞时,正确检测到碰撞。但是当我在贝塞尔曲线内部移动矩形时,也会检测到碰撞,尽管这些物品没有碰撞。我想获得这两个项目之间的精确碰撞。我不明白我犯了什么错误。

enter image description here

class RectangleItem(QGraphicsRectItem):
    def __init__(self, *args):
        super().__init__(*args)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setPen(QPen(Qt.cyan))


class CurveItem(QGraphicsItem):
    def __init__(self):
        super().__init__()
        self.path = self._setupPath()

    def paint(self, painter, styles, widget=None):
        painter.drawPath(self.path)

    def boundingRect(self):
        return self.path.boundingRect()

    def shape(self):
        return self.path

    def _setupPath(self):
        path = QPainterPath()

        p1 = QPointF(0, 100)
        p2 = QPointF(400, 100)
        c = QPointF(200, 800)

        path.moveTo(p1)
        path.quadTo(c, p2)
        return path


class Scene(QGraphicsScene):
    def __init__(self):
        super().__init__()

        self.curve_item = CurveItem()
        self.addItem(self.curve_item)

        self.rectangle_item = RectangleItem(0, 0, 50, 50)
        self.addItem(self.rectangle_item)

    def mouseMoveEvent(self, e):
        print(self.collidingItems(self.curve_item))
        super().mouseMoveEvent(e)

1 个答案:

答案 0 :(得分:1)

为了观察问题的原因,我们可以放置一个QBrush来绘制CurveItem内容,我们得到以下内容:

def paint(self, painter, styles, widget=None):
    painter.setBrush(QBrush(QColor("green")))
    painter.drawPath(self.path)

enter image description here

为什么会这样?

如果图形未关闭,

QPainterPath会加入最终点和初始点,因此会生成一个带有内容的图形,这会导致当您将矩形移到线条上时它会发出信号它是相交的。

解决方案是什么?

返回到起始点的相同路径,从而将新的最后一行与初始行连接,而不生成内容

以下代码是解决方案:

class CurveItem(QGraphicsItem):
    def __init__(self):
        super().__init__()
        self.path = self._setupPath()

    def paint(self, painter, styles, widget):
        painter.drawPath(self.path)

    def boundingRect(self):
        return self.path.boundingRect()

    def shape(self):
        return self.path

    def _setupPath(self):
        path = QPainterPath()

        p1 = QPointF(0, 100)
        p2 = QPointF(400, 100)
        c = QPointF(200, 800)

        path.moveTo(p1)
        path.quadTo(c, p2)

        # back
        path.quadTo(c, p1)
        return path