精确检测两个图形项之间的碰撞

Precise detection of collision between two graphical items

我有两个图形项目,RectItemCurveItem。我需要精确检测这两个项目之间的碰撞。我为展位项目实施了 shape() 方法。当我从场景 self.collidingItems(self.rect_item, mode=Qt.IntersectsItemShape 中移动其中一项时,我验证是否检测到碰撞。

我通过在场景中移动项目来碰撞它们,但仅在 CurveItem 的顶部检测到碰撞。我不明白我哪里弄错了。

代码:

class RectItem(QGraphicsRectItem):
    def __init__(self, x, y, w, h):
        super().__init__(x, y, w, h)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setPen(QPen(Qt.cyan))

    def shape(self):
        path = QPainterPath()
        path.addRect(self.boundingRect())
        return path


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 QRectF()

    def shape(self):
        return self.path

    def _setupPath(self):
        path = QPainterPath()
        path.moveTo(0, 0)
        path.cubicTo(99, 0, 50, 50, 99, 99)
        path.cubicTo(0, 99, 50, 50, 0, 0)
        return path


class Scene(QGraphicsScene):
    def __init__(self):
        super().__init__()
        self.curve_item = CurveItem()
        self.rect_item = RectItem(-50, -50, 25, 25)

        self.addItem(self.curve_item)
        self.addItem(self.rect_item)

    def mouseMoveEvent(self, e):
        print(self.collidingItems(self.rect_item, mode=Qt.IntersectsItemShape))
        super().mouseMoveEvent(e)

尽管您不会使用 boundingRect() 来检测碰撞,但您必须 return 一个 QRect,这是覆盖 shape 的最小尺寸,为此我们可以使用QPainterPathboundingRect()方法,而且不需要覆盖QGraphicsRectItem.

的形状
class RectItem(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()
        path.moveTo(0, 0)
        path.cubicTo(99, 0, 50, 50, 99, 99)
        path.cubicTo(0, 99, 50, 50, 0, 0)
        return path


class Scene(QGraphicsScene):
    def __init__(self):
        super().__init__()
        self.curve_item = CurveItem()
        self.rect_item = RectItem(-50, -50, 25, 25)

        self.addItem(self.curve_item)
        self.addItem(self.rect_item)

    def mouseMoveEvent(self, e):
        print(self.collidingItems(self.rect_item, mode=Qt.IntersectsItemShape))
        super().mouseMoveEvent(e)