对于我正在研究的项目,我试图编写一些代码来检测2D空间中非点粒子之间的碰撞。我的目标是尝试每次至少几次检测几千个粒子的碰撞,我知道这对于python是一个很高的命令。我已经按照blog post执行了一个四叉树来显着减少我需要进行的成对检查次数。因此,我相信我遇到的问题就是这个功能:
def get_index(self, particle):
index = -1
bounds = particle.aabb
v_midpoint = self.bounds.x + self.bounds.width/2
h_midpoint = self.bounds.y + self.bounds.height/2
top_quad = bounds.y < h_midpoint and bounds.y + bounds.height < h_midpoint
bot_quad = bounds.y > h_midpoint
if bounds.x < v_midpoint and bounds.x + bounds.width < v_midpoint:
if top_quad:
index = 1
elif bot_quad:
index = 2
elif bounds.x > v_midpoint:
if top_quad:
index = 0
elif bot_quad:
index = 3
return index
我最初的分析中的这个功能是瓶颈,我需要它快速起泡,因为它的通话次数很高。最初我只是提供一个物体轴对齐的边界框,它几乎以我需要的速度工作,然后意识到我无法确定哪些颗粒实际上可能会发生碰撞。所以现在我将粒子列表传递给我的四叉树构造函数,并使用类属性aabb来获取我的界限。
有没有我可以将一些类似物传递给对象指针而不是整个对象?另外还有其他建议来优化上面的代码吗?
答案 0 :(得分:0)
不知道他们是否会提供帮助,但这里有一些想法:
为添加到四叉树中的每个粒子重新计算v_midpoint和h_midpoint。相反,在初始化Quad时计算它们一次,然后将它们作为属性访问。
我不认为计算top_quad需要and
。 bounds.x + bounds.width < v_midpoint
就足够了。对于left_quad也一样。
首先进行更简单的检查,只在必要时进行更长的检查:bounds.x&gt; v_midpoint vs. bounds.x + bounds.width&lt; v_midpoint
bounds.x + bounds.width
计算多次。也许bounds.left和bounds.right可以作为每个粒子的属性计算一次。
如果top_quad为True,则无需计算bot_quad。或者反之亦然。
也许是这样的:
def get_index(self, particle):
bounds = particle.aabb
# right
if bounds.x > self.v_midpoint:
# bottom
if bounds.y > self.h_midpoint:
return 3
# top
elif bounds.y + bounds.height < self.h_midpoint:
return 0
# left
elif bounds.x + bounds.width < self.v_midpoint:
# bottom
if bounds.y > self.h_midpoint:
return 2
# top
elif bounds.y + bounds.height < self.h_midpoint:
return 1
return -1