barnes hut树在insert和internalInsert之间无休止地循环

时间:2013-06-09 18:30:53

标签: algorithm

我正在尝试实现这个数据结构Barnes-Hut Octree,并且我一直运行到无限循环,由内存不足异常终止。

完整的小提琴在这里:http://jsfiddle.net/cWvex/ 但我正在循环的功能是:

OctreeNode.prototype.insert = function (body) {

    console.log('insert');

    if(this.isInternal){

        this.internalInsert(body);

        return;
    }


    if(this.isExternal){

        // insert the body into the spec. quadrant, call internalUpdate
        for(var quadrant in this.internal.quadrants){
            if(this.internal.quadrants.hasOwnProperty(quadrant)){
                this.internal.quadrants[quadrant] = new OctreeNode();
            }
        }
        this.isExternal = false;
        this.isInternal = true;

        this.internalInsert(this.external);
        this.external = null;
        this.internalInsert(body);

        return;
    }


    if(this.isEmpty){

        this.external = body;
        this.isEmpty = false;
        this.isExternal = true;

        return;
    }

};

// Precondition: quadrants' nodes must be instantiated
OctreeNode.prototype.internalInsert = function(body) {

    console.log('internalInsert');

    this.internal.quadrants[this.quadrant(body)].insert(body);
    this.internalUpdate(body);

};

任何人都知道我错过了什么?

1 个答案:

答案 0 :(得分:2)

我认为问题与象限功能有关:

OctreeNode.prototype.quadrant = function (body) {

    console.log('quadrant');

    var pos = this.internal.pos;

    var quadrant = (body.pos.x < pos ? 'l' : 'r') + 
        (body.pos.y < pos ? 'u' : 'd') + 
        (body.pos.z < pos ? 'i' : 'o');

    return quadrant; 
};

所选象限应基于象限的中心,而不是质心。我认为您需要创建一个新变量来定义象限的中心。

请注意,当您添加节点时,质心(存储在pos中)可以更改,但象限的中心保持固定(否则当您进入octtree时会出现问题)。

目前,每个新节点都生成一个0,0,0的pos,所以每个点总是最终被分配到节点的同一象限。因此,当您尝试将两个实体放入树中时,最终会得到无限递归:

  1. 正文1插入节点x
  2. 将Body 2插入节点x
  3. 节点1被拆分。
  4. 将主体1插入节点x的象限1
  5. 将主体2插入节点x的象限1
  6. 返回步骤1,x更改为节点x的象限1的节点
  7. 修改

    顺便提一下,在代码中写道:

    avgPos.x = (body.pos.x*body.mass + 
                avgPos.x * totalMass) / totalMass + body.mass
    

    我认为您需要更多括号才能成为

    avgPos.x = (body.pos.x*body.mass + 
                avgPos.x * totalMass) / (totalMass + body.mass)
    

    或者质量中心的更新会出错。