python

时间:2016-03-21 15:27:18

标签: python pointers optimization quadtree

对于我正在研究的项目,我试图编写一些代码来检测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来获取我的界限。

有没有我可以将一些类似物传递给对象指针而不是整个对象?另外还有其他建议来优化上面的代码吗?

1 个答案:

答案 0 :(得分:0)

不知道他们是否会提供帮助,但这里有一些想法:

  1. 为添加到四叉树中的每个粒子重新计算v_midpoint和h_midpoint。相反,在初始化Quad时计算它们一次,然后将它们作为属性访问。

  2. 我不认为计算top_quad需要andbounds.x + bounds.width < v_midpoint就足够了。对于left_quad也一样。

  3. 首先进行更简单的检查,只在必要时进行更长的检查:bounds.x&gt; v_midpoint vs. bounds.x + bounds.width&lt; v_midpoint

  4. 对于大多数粒子,
  5. bounds.x + bounds.width计算多次。也许bounds.left和bounds.right可以作为每个粒子的属性计算一次。

  6. 如果top_quad为True,则无需计算bot_quad。或者反之亦然。

  7. 也许是这样的:

    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