我正在尝试实现这个数据结构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);
};
任何人都知道我错过了什么?
答案 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,所以每个点总是最终被分配到节点的同一象限。因此,当您尝试将两个实体放入树中时,最终会得到无限递归:
修改
顺便提一下,在代码中写道:
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)
或者质量中心的更新会出错。