Algorithm 基于R树的数据结构:当一个节点已满时创建新的子节点,但如果在同一位置有很多对象,该怎么办?

Algorithm 基于R树的数据结构:当一个节点已满时创建新的子节点,但如果在同一位置有很多对象,该怎么办?,algorithm,data-structures,tree,Algorithm,Data Structures,Tree,我意识到我的标题不是很清楚,但我很难想出更好的标题。如果有人想改正,请改正 我正在为我的无限宇宙的二维游戏开发一个数据结构。数据结构基于简单的(!)节点/叶系统,如 这是基本概念:设置节点(容器)的最大子节点数。如果要添加叶,但叶所在的节点已满,则它将在此节点内创建一组新节点,并将所有当前叶移动到其新(更精确)节点。这样,人口稠密的地区将比一个非常大但很少访问的地区有更多的细分 这适用于普通对象。当我有多个maxChildsPerNode对象具有完全相同的X,Y位置时,唯一的问题出现了:因为节点

我意识到我的标题不是很清楚,但我很难想出更好的标题。如果有人想改正,请改正

我正在为我的无限宇宙的二维游戏开发一个数据结构。数据结构基于简单的(!)节点/叶系统,如

这是基本概念:设置节点(容器)的最大子节点数。如果要添加叶,但叶所在的节点已满,则它将在此节点内创建一组新节点,并将所有当前叶移动到其新(更精确)节点。这样,人口稠密的地区将比一个非常大但很少访问的地区有更多的细分

这适用于普通对象。当我有多个maxChildsPerNode对象具有完全相同的X,Y位置时,唯一的问题出现了:因为节点已满,它将创建更精确的子节点,但旧叶将再次全部放在完全相同的节点中,因为它们具有完全相同的位置——导致创建更多节点和更多节点的无限循环

那么,如果我想在树中添加比maxChildsPerNode位置完全相同的叶子更多的叶子,该怎么办

另外,如果我没有解释我的问题,请告诉我,这样我可以尝试改进解释

更新:这是检查完整节点中的所有叶是否具有相同位置的方法:

//returns whether all leafs in the given leaf list are identical
    private function allLeafsHaveSamePos(leafArr:Array<RTLeaf<T>>):Bool {
        if (leafArr.length > 1) {
            var lastLeafTopX:Float = leafArr[0].topX;
            var lastLeafTopY:Float = leafArr[0].topY;
            for (i in 1...leafArr.length) {
                if ((leafArr[i].topX != lastLeafTopX) || (leafArr[i].topY != lastLeafTopY)) return false;
            }
        }
        return true;
    }
//返回给定叶列表中的所有叶是否相同
私有函数allLeafsHaveSamePos(leafArr:Array):Bool{
如果(叶栅长度>1){
var lastLeafTopX:Float=leafArr[0].topX;
var lastLeafTopY:Float=leafArr[0]。topY;
用于(i/1…叶面积长度){
if((leafArr[i].topX!=lastLeafTopX)| |(leafArr[i].topY!=lastLeafTopY))返回false;
}
}
返回true;
}

根据常识,我不会假设两个物体在同一位置,但如果这是想法的一部分,那么我会再引入一个轴,比如“自旋”,一个整数,并施加一个限制,即所有物体都是费米子(不能同时具有相同的位置和自旋).

看起来您的数据和结构之间有点不匹配,因为当您在无限小的点上为其提供>N个对象时,您的结构假设任意大的区域内有N个对象。是否值得为该数据使用不同的结构

黑客修正:对新创建的对象应用一个微小的随机位移。这应该允许通过现有算法对空间进行细分


更好的解决方法:确保分割叶节点的算法始终生成至少2个新叶节点。将对象重新指定给新叶节点时,或在执行正常插入时,迭代所有候选对象,如果有多个对象同样适用,则可以根据它们的填充程度进行平分。这将导致您的同一位置的玩家在其他相同节点上平均分配。

我想问一个问题

  • 遵守
    maxChildsPerNode
    约束是否有那么重要
我宁愿将此最大值视为结构何时拆分的提示,而在没有有意义的方式执行拆分时忽略它

当然你最好重新考虑一下这个名字,否则对下一个维护人员来说会很奇怪

在伪代码中,我将使用如下内容:

def AddToNode(node, item):
  node.items.append(item)
  if len(node.items) > node.splitHint:
    leftNode = Node(node.splitHint)
    rightNode = Node(node.splitHint)
    node.split(leftNode, rightNode)
    if len(leftNode.items) == 0 or len(rightNode.items) == 0:
      node.splitHint *= 1.5 # famous golden ratio ;)
    else:
      node.items = [leftNode, rightNode]

重要的一步是在检测到提示时修改它,使我们无法遵守它,以便在每次插入时不执行此检查(这样我们可以获得一个固定的摊销成本)。

如果在同一地点有一组对象,则对包含一个对象的区域的任何查询都应返回all-因此没有理由拆分它们,因为这不会给你带来任何好处。在决定拆分时,只需计算不同位置的数量,或者让叶节点上的每个元素都是一个封装的对象(坐标,[这些坐标处的对象列表])。

如果不以编程方式完成,则不太可能。然而,想象游戏在一个繁殖点繁殖多个玩家,这将是完全相同的位置。我不太清楚你说的旋转是什么意思,整数反映了什么?即使两个玩家在同一点上繁殖,也有可能给他们一个稍微不同的坐标(添加随机增量)。自旋只是使对象不同的另一个参数,仅在您的数据结构中用于解决所有坐标相同的问题。许多游戏在另一个玩家已经存在的地方产生第二个玩家时,会杀死第一个玩家,惩罚她。游戏逻辑的实现与我的问题无关。你不能期望一个游戏设计师使用我的类按照我希望的方式编写代码。如果他们想在同一位置添加多个玩家,他们应该能够这样做,并且不会看到服务器端处于无限循环中。为什么数据和结构不匹配?该结构不假定一定数量的对象,它可以是任何对象,这就是创建新节点的原因。它只是确保在一个节点内不超过X个叶。当然,随机选择是没有选择的。我的分割算法总是创建最大数量的节点,在当前节点上分割。但我想我必须改变这种行为?这是不匹配的,因为你使用的是2D分区方案,用于在这两个维度上没有差异的对象。这就像是按作者的字母顺序对一本书进行排序,而这些书都是由同一个人写的。(不过,我知道你可能还有其他更适合这个方案的对象。)至于拆分,唯一的问题是