【问题标题】:Efficient quadtree implementation in pythonpython中高效的四叉树实现
【发布时间】:2016-03-21 15:27:17
【问题描述】:

对于我正在进行的项目,我正在尝试编写一些代码来检测二维空间中非点粒子之间的碰撞。我的目标是尝试在每个时间步至少检测几千个粒子的碰撞,我知道这对 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 来获取我的边界。

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

【问题讨论】:

  • Python 已经通过引用传递(这可能是为什么有人匿名否决了您的问题),因此对象复制不会减慢您的代码速度。对于每个对象,您可以在时间步长中为其向量构造一个边界框。然后你只需要检查边界框在同一个四叉树区域中的对象,看看它们是否相交,就可以进行详细的碰撞检查。

标签: python pointers optimization quadtree


【解决方案1】:

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

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

  2. 我认为在计算 top_quad 时不需要 andbounds.x + bounds.width &lt; v_midpoint 就足够了。 left_quad 也一样。

  3. 先做较简单的检查,必要时只做较长的检查:bounds.x > v_midpoint vs. bounds.x + bounds.width

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

  5. 如果 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

【讨论】:

  • 哦,这些都是非常好的观点。我已经着手实施了它们,足以说明我的瓶颈现在在其他地方。我不确定这给出的确切加速,但是当我的树中有大量粒子时,中点的缓存值给出 10 倍或更大
猜你喜欢
  • 1970-01-01
  • 2011-10-05
  • 2011-02-08
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多