bool RemoveLeafFromSelf(QuadtreeLeafUpdate <T> leaf) { if (DoRemoveLeafFromSelf(leaf)) { return(true); } return(_root.RemoveLeafInTotalTree(leaf)); }
void UpdateMaxRadiusWhenSetLeaf(QuadtreeLeafUpdate <T> leaf) { if (leaf.radius > _maxRadius) //只有存入的叶子的半径超过了现在节点的最大半径才需要更新最大半径,存入更小的叶子并不会影响到检测。 { _maxRadius = leaf.radius; CallParentUpdateMaxRadius(); } }
bool DoRemoveLeafFromSelf(QuadtreeLeafUpdate <T> leaf) { if (_leafs.Remove(leaf)) //List的Remove返回有没有成功从List里移除要移除的元素,元素不存在的时候返回是 false,有了这个返回值就可以非常轻松的判断出这个树梢是不是成功移除了叶子 { UpdateMaxRadiusWhenRemoveLeaf(); Debug.Log("位置在" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + "的树梢节点移除位置在" + leaf.position + "半径是" + leaf.radius + "的叶子,移除后的最大半径是" + _maxRadius); return(true); } return(false); }
/* * 全树移除,不通过位置判断而是直接遍历整棵树移除叶子 * * 实际上在上一步就应该增加全树移除,但考虑到上一步没有实用性为了降低知识密度就没加。 * * 前面的移除都是根据叶子位置找到树梢之后进行删除,但这个寻找方式是有缺陷的,在几种情况下都会失效 * 1.叶子移出了树梢范围,叶子不在原本的树梢上按照位置当然找不到正确的树梢,不要以这种情况为有了更新就不会发生,更新每帧只进行一次,叶子的移动则是不限量的 * 2.叶子移出了整棵树的范围,情况更严重,从根节点开始就不可能找得到叶子所在的树梢 * 3.叶子根本不在树里,几乎找茬的情况,无论在哪个树梢都不可能找到这个叶子,更不可能移除掉 * * 如果是情况1,可以通过更新树或全树移除来解决,但对于2和3更新无异于自寻死路,这样唯一的解就是不通过位置寻找树梢而是遍历整棵树找到这个叶子删掉他 */ bool RemoveLeafInTotalTree(QuadtreeLeafUpdate <T> leaf) { if (DontHaveChildren()) { return(DoRemoveLeafFromSelf(leaf)); } else { return(RemoveLeafInTotalTreeFromChildren(leaf)); } }
//移除,增加了全树移除 public bool RemoveLeaf(QuadtreeLeafUpdate <T> leaf) { if (DontHaveChildren()) { return(RemoveLeafFromSelf(leaf)); } else { return(RemoveLeafFromChildren(leaf)); } }
/* * 存入增加存入叶子不在整个四叉树范围内的情况的判断 * * 这个判断在最开始就应该写上,但在前面并不会造成特别严重的后果,为了降低知识密度就没写,但在增加了更新之后,一旦有一个叶子的位置不在整个树的范围内,马上就会导致死循环 */ public bool SetLeaf(QuadtreeLeafUpdate <T> leaf) { if (DontHaveChildren()) { return(SetLeafToSelf(leaf)); } else { return(SetLeafToChildren(leaf)); } }
bool SetLeafToSelf(QuadtreeLeafUpdate <T> leaf) { if (this == _root && !_field.Contains(leaf.position)) { Debug.LogError("存入叶子失败,叶子不在四叉树范围内"); return(false); } _leafs.Add(leaf); UpdateMaxRadiusWhenSetLeaf(leaf); Debug.Log("位置在" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + "的树梢节点存入位置在" + leaf.position + "半径是" + leaf.radius + "的叶子,存入后的最大半径是" + _maxRadius); CheckAndDoSplit(); return(true); }
bool RemoveLeafInTotalTreeFromChildren(QuadtreeLeafUpdate <T> leaf) { if (_upperRightChild.RemoveLeafInTotalTree(leaf)) { return(true); //如果子节点移除成功了,那就说明不需要继续遍历剩下的节点了,直接返回 true } if (_lowerRightChild.RemoveLeafInTotalTree(leaf)) { return(true); } if (_lowerLeftChild.RemoveLeafInTotalTree(leaf)) { return(true); } if (_upperLeftChild.RemoveLeafInTotalTree(leaf)) { return(true); } return(false); }
bool RemoveLeafFromChildren(QuadtreeLeafUpdate <T> leaf) { Debug.Log("位置在(" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + ")的树枝节点从子节点移除位置在" + leaf.position + "半径是" + leaf.radius + "的叶子"); if (_upperRightChild._field.Contains(leaf.position)) { return(_upperRightChild.RemoveLeaf(leaf)); } if (_lowerRightChild._field.Contains(leaf.position)) { return(_lowerRightChild.RemoveLeaf(leaf)); } if (_lowerLeftChild._field.Contains(leaf.position)) { return(_lowerLeftChild.RemoveLeaf(leaf)); } if (_upperLeftChild._field.Contains(leaf.position)) { return(_upperLeftChild.RemoveLeaf(leaf)); } return(_root.RemoveLeafInTotalTree(leaf)); }
bool SetLeafToChildren(QuadtreeLeafUpdate <T> leaf) { Debug.Log("位置在" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + "的树枝节点向子节点存入位置在" + leaf.position + "半径是" + leaf.radius + "的叶子"); if (_upperRightChild._field.Contains(leaf.position)) { return(_upperRightChild.SetLeaf(leaf)); } if (_lowerRightChild._field.Contains(leaf.position)) { return(_lowerRightChild.SetLeaf(leaf)); } if (_lowerLeftChild._field.Contains(leaf.position)) { return(_lowerLeftChild.SetLeaf(leaf)); } if (_upperLeftChild._field.Contains(leaf.position)) { return(_upperLeftChild.SetLeaf(leaf)); } Debug.LogError("向位置在" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + "的节点存入叶子时发生错误:叶子不在所有子节点的范围里。"); //Debug.LogError:在Console面板输出Error,就是红色那种消息 return(false); }
public static bool RemoveLeaf(QuadtreeLeafUpdate <GameObject> leaf) { return(_quadtree.RemoveLeaf(leaf)); }
private void Awake() { _transform = transform; _leaf = new QuadtreeLeafUpdate <GameObject>(gameObject, GetLeafPosition(), _radius); }
void ResetLeaf(QuadtreeLeafUpdate <T> leaf) { Debug.Log("位置在" + _field.top + "," + _field.right + "," + _field.bottom + "," + _field.left + "的树梢节点移除位置在" + leaf.position + "半径是" + leaf.radius + "的叶子,重新存入树"); RemoveLeafFromSelf(leaf); _root.SetLeaf(leaf); }