将 boundingRect() 映射到父项并相交会产生意外的碰撞处理结果
Mapping boundingRect()'s to parent item and intersecting yields unexpected results for collision handling
下面是我如何处理两个图形项目的冲突。它在 mouseMoveEvent 和 itemChange 中被调用。像这样:
void GraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
auto delta = event->pos() - event->lastPos();
auto new_pos = handleCollisions(pos() + delta);
setPos(new_pos);
}
new_pos 这样我就可以在 itemChange 中调用它,return 将其作为值。但是,此版本的碰撞处理保留 new_pos 不变。相反,我们移动与这个碰撞的项目(就像我们用鼠标移动这个一样)。我正在尝试获取两个涉及的边界矩形的交集,并将另一个边界矩形移动矩形交集的较短维度。出乎意料的结果是矩形并没有移动那么小的量,而是移动了 boundingRects() 中的任何一个的整个宽度(或高度)(它们的大小相同)。我已经追踪到它,所以下面的代码计算父位置 space 中边界矩形的交集(其中 pos()、setPos() 是相对的)是错误的。
那么我该如何实现呢?
这是我想要的图片:
QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
auto collisions = collidingItems();
auto rect = mapToParent(boundingRect().translated(new_pos - pos())).boundingRect();
for(int k=0; k < collisions.count(); k++)
{
auto item = collisions[k];
if (item->parentItem() == parentItem()) {
auto rect1 = mapToParent(item->boundingRect()).boundingRect();
rect1 = rect1.intersected(rect);
qDebug() << (rect1.width());
qDebug() << (rect1.height());
auto v = rect1.center() - rect.center();
if (v.x() >= 0) {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(-rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
else {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
}
}
return new_pos; // return this position unchanged
}
找到了
item->mapToParent(...)
而不是
mapToParent(...)
应该在循环中调用。
下面是我如何处理两个图形项目的冲突。它在 mouseMoveEvent 和 itemChange 中被调用。像这样:
void GraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
auto delta = event->pos() - event->lastPos();
auto new_pos = handleCollisions(pos() + delta);
setPos(new_pos);
}
new_pos 这样我就可以在 itemChange 中调用它,return 将其作为值。但是,此版本的碰撞处理保留 new_pos 不变。相反,我们移动与这个碰撞的项目(就像我们用鼠标移动这个一样)。我正在尝试获取两个涉及的边界矩形的交集,并将另一个边界矩形移动矩形交集的较短维度。出乎意料的结果是矩形并没有移动那么小的量,而是移动了 boundingRects() 中的任何一个的整个宽度(或高度)(它们的大小相同)。我已经追踪到它,所以下面的代码计算父位置 space 中边界矩形的交集(其中 pos()、setPos() 是相对的)是错误的。
那么我该如何实现呢?
这是我想要的图片:
QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
auto collisions = collidingItems();
auto rect = mapToParent(boundingRect().translated(new_pos - pos())).boundingRect();
for(int k=0; k < collisions.count(); k++)
{
auto item = collisions[k];
if (item->parentItem() == parentItem()) {
auto rect1 = mapToParent(item->boundingRect()).boundingRect();
rect1 = rect1.intersected(rect);
qDebug() << (rect1.width());
qDebug() << (rect1.height());
auto v = rect1.center() - rect.center();
if (v.x() >= 0) {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(-rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
else {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
}
}
return new_pos; // return this position unchanged
}
找到了
item->mapToParent(...)
而不是
mapToParent(...)
应该在循环中调用。