【发布时间】:2020-09-05 19:46:57
【问题描述】:
我正在使用四叉树来有效地收集某个 2D 区域中的粒子。粒子随着时间的推移逐渐消失并最终消失,因此我需要在它们死亡时将它们从四叉树中移除。
我面临的问题是如何最好地修剪四叉树以删除空节点,并在节点不再有足够的粒子来证明被分割时合并节点。
我的第一个想法是递归遍历树,检查每个子节点。如果所有 4 个节点都是空的,那么我将使用标志将其传回调用堆栈(空为 true,否则为 false),否则,我将检查每个子节点中的粒子数,以及它们是否' re 都小于 MAX_PER_NODE, 将所有粒子拉入父级并删除子级。
可能类似于以下内容(这个伪代码实际上是我写这篇文章时的意识流,所以请谨慎对待):
class QuadTreeNode
{
public bool prune();
public void deleteChildren(); //just assume it does what you expect...
private:
std::vector<ParticleType> particles;
std::vector<QuadTreeNode*> children; // size <= 4
};
bool QuadTreeNode::prune()
{
bool allChildrenEmpty = true;
for(QuadTreeNode & n : children)
{
allChildrenEmpty &= n.prune();
}
//Merging could be handled by returning the number of particles instead of true/false
//If the total number of particles falls below the max per bucket, pull the particles into the
//current node and delete the children...
if(allChildrenEmpty) this.deleteChildren();
return allChildrenEmpty && (!this.particles.size());
}
但是,这似乎效率低下,因为我觉得它需要我触摸树中的每个节点(尽管我想这比访问 每个 粒子要好)。
有没有更好的方法来实现这种修剪和合并操作?
【问题讨论】:
-
所有粒子的寿命都一样吗?如果是这样,您可以将它们排成四个队列,每个象限一个。然后,您只需检查最早的粒子是否已过期。