【发布时间】:2021-11-19 02:27:10
【问题描述】:
我有一个带有可移动 QGraphicsEllipseitem 圆圈的图形场景。我试图通过让一个正在拖动的圆圈围绕它碰撞到的其他圆圈移动来防止圆圈重叠。到目前为止,它适用于 1 个碰撞项目来设置最小距离。
我正在尝试扩展 len(colliding)==1 的代码以适用于 2 个碰撞项目,因此我尝试将代码应用于每个碰撞项目。我先应用重叠较多的那个,然后再应用第二个。
当碰撞项目的大小相同时,它部分工作,因为它在没有重叠的情况下四处移动,但它“故障”很多,所以我知道它并不完美。 但是当它们的大小不同时,它根本不起作用并且仍然重叠。 我不知道如何解决它。
class Circleitem(QGraphicsEllipseItem):
def __init__(self, size, brush):
super().__init__()
radius = size / -2
self.setRect(radius, radius, size, size)
self.setBrush(brush)
self.setFlag(self.ItemIsMovable)
self.setFlag(self.ItemIsSelectable)
def paint(self, painter, option, a):
option.state = QStyle.State_None
return super(Circleitem, self).paint(painter,option)
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
colliding = self.collidingItems()
if len(colliding)==1:
item = colliding[0]
line = QLineF(item.pos(), self.pos() + QPoint(self.pos() == item.pos(), 0))
min_distance = (self.rect().width() + item.rect().width()) / 2
if line.length() < min_distance:
line.setLength(min_distance)
self.setPos(line.p2())
elif len(colliding)==2:
item0 = colliding[0]
item1 = colliding[1]
line0 = QLineF(item0.pos(), self.pos())
line1 = QLineF(item1.pos(), self.pos())
if line0.length() < line1.length():
mindist = (self.rect().width() + item0.rect().width()) / 2
if line0.length() < mindist:
line0.setLength(mindist)
self.setPos(line0.p2())
second = item1
else:
mindist = (self.rect().width() + item1.rect().width()) / 2
if line1.length() < mindist:
line1.setLength(mindist)
self.setPos(line1.p2())
second = item0
line = QLineF(second.pos(), self.pos())
min_distance = (self.rect().width() + second.rect().width()) / 2
if line.length() < min_distance:
line.setLength(min_distance)
self.setPos(line.p2())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.gscene = QGraphicsScene(0, 0, 1000, 1000)
gview = QGraphicsView(self.gscene)
self.setCentralWidget(gview)
self.circle1 = Circleitem (123, brush=QColor(255,255,0))
self.circle2 =Circleitem(80, brush=QColor(0,255,0))
self.circle3 =Circleitem(80, brush=QColor(0,255,0))
self.gscene.addItem(self.circle1)
self.gscene.addItem(self.circle2)
self.gscene.addItem(self.circle3)
self.circle1.setPos(500, 500)
self.circle2.setPos(300, 300)
self.circle3.setPos(300, 400)
self.show()
app = QApplication([])
win = MainWindow()
app.exec()
【问题讨论】:
-
避免形状(尤其是多个/不同形状)的碰撞并非易事。您必须根据许多方面,包括项目的先前位置,自行找到适合您需求的算法。有很多关于这个问题的研究,并且没有简单/绝对的解决方案。考虑两个可能碰撞项目的矩形的基本示例,以及无法容纳其中空间的移动矩形:该移动的行为应该是什么?移动的项目应该在哪一点停止或“跳跃”?那么与移动物品发生碰撞呢?
-
椭圆使这变得更加困难,因为您必须考虑基于三角函数的碰撞,这只是假设您正在处理“常规”圆并且它们的轴是正交的。旋转的椭圆呢?请参阅有关 Collision detection 的维基百科文章。
-
感谢您的解释,我知道这是一个难题。我试图一步一步地只处理圆圈并处理 2 次碰撞
标签: python pyqt5 qgraphicsscene