/// <summary> /// Returns node count for given node including it's childs. /// </summary> /// <param name="node">The node</param> /// <param name="count">Starting value for count.</param> /// <returns>The counf on nodes.</returns> private int GetQuadNodeCount(QuadNode node, int count) { if (node == null) { return(count); } foreach (QuadNode childNode in node.Nodes) { if (childNode != null) { count++; } } return(count); }
/// <summary> /// Expands the root node bounds. /// </summary> /// <param name="newChildBounds"></param> private void ExpandRoot(Rect newChildBounds) { bool isNorth = RootNode.Bounds.Y < newChildBounds.Y; bool isWest = RootNode.Bounds.X < newChildBounds.X; Direction rootDirection = isNorth // find the direction. ? (isWest ? Direction.NorthWest : Direction.NorthEast) : (isWest ? Direction.SouthWest : Direction.SouthEast); double newX = (rootDirection == Direction.NorthWest || rootDirection == Direction.SouthWest) ? RootNode.Bounds.X : RootNode.Bounds.X - RootNode.Bounds.Width; double newY = (rootDirection == Direction.NorthWest || rootDirection == Direction.NorthEast) ? RootNode.Bounds.Y : RootNode.Bounds.Y - RootNode.Bounds.Height; var newRootBounds = new Rect(newX, newY, RootNode.Bounds.Width * 2, RootNode.Bounds.Height * 2); var newRoot = new QuadNode(newRootBounds); this.setupChildNodes(newRoot); newRoot[rootDirection] = RootNode; this.RootNode = newRoot; }
/// <summary> /// Creates a new QuadTree. /// </summary> /// <param name="minimumLeafSize">The smallest size a leaf will split into.</param> /// <param name="maximumObjectsPerLeaf">Maximum number of objects per left before it's forced to split into sub-quadrans.</param> public QuadTree(Size minimumLeafSize, int maximumObjectsPerLeaf) { this.RootNode = null; this.MinimumLeafSize = minimumLeafSize; this.MaximumObjectsPerLeaf = maximumObjectsPerLeaf; }
/// <summary> /// Checks child nodes of the node. /// </summary> /// <param name="node">The parent node.</param> private void checkChildNodes(QuadNode node) { if (GetTotalObjectCount(node) > MaximumObjectsPerLeaf) { return; } // Move child objects into this node, and delete sub nodes List <WorldObject> subChildObjects = GetChildObjects(node); foreach (WorldObject childObject in subChildObjects) { if (node.ContainedObjects.Values.Contains(childObject)) { continue; } RemoveObjectFromNode(childObject); addObjectToNode(node, childObject); } if (node[Direction.NorthWest] != null) { node[Direction.NorthWest].Parent = null; node[Direction.NorthWest] = null; } if (node[Direction.NorthEast] != null) { node[Direction.NorthEast].Parent = null; node[Direction.NorthEast] = null; } if (node[Direction.SouthWest] != null) { node[Direction.SouthWest].Parent = null; node[Direction.SouthWest] = null; } if (node[Direction.SouthEast] != null) { node[Direction.SouthEast].Parent = null; node[Direction.SouthEast] = null; } if (node.Parent != null) { checkChildNodes(node.Parent); } else { // Its the root node, see if we're down to one quadrant, with none in local storage - if so, ditch the other three. int numQuadrantsWithObjects = 0; QuadNode nodeWithObjects = null; foreach (QuadNode childNode in node.Nodes) { if (childNode == null || GetTotalObjectCount(childNode) <= 0) { continue; } numQuadrantsWithObjects++; nodeWithObjects = childNode; if (numQuadrantsWithObjects > 1) { break; } } if (numQuadrantsWithObjects == 1) // if we have only one quadrand with objects, make it the new rootNode. { foreach (QuadNode childNode in node.Nodes) { if (childNode != nodeWithObjects) { childNode.Parent = null; } } this.RootNode = nodeWithObjects; } } }