Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Removes object from it's node.
        /// </summary>
        /// <param name="object">The object to remove.</param>
        public void Remove(WorldObject @object)
        {
            if (!_objectToNodeLookup.ContainsKey(@object))
            {
                throw new KeyNotFoundException("QuadTree:Remove() - Object not found in dictionary for removal.");
            }

            QuadNode containingNode = _objectToNodeLookup[@object]; // get the object.

            RemoveObjectFromNode(@object);                          // remove it.

            if (containingNode.Parent != null)
            {
                CheckChildNodes(containingNode.Parent); // check all child nodes of parent.
            }
        }
Exemplo n.º 3
0
        private void ObjectPositionChanged(object sender, EventArgs e)
        {
            var @object = sender as WorldObject;

            if (@object == null)
            {
                return;
            }

            QuadNode node = this._objectToNodeLookup[@object];

            if (node.Bounds.Contains(@object.Bounds) && !node.HasChildNodes())
            {
                return;
            }

            this.RemoveObjectFromNode(@object);
            Insert(@object);
            if (node.Parent != null)
            {
                CheckChildNodes(node.Parent);
            }
        }
Exemplo n.º 4
0
        /// <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;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Inserts a new object.
        /// </summary>
        /// <param name="object">The object to be inserted.</param>
        public void Insert(WorldObject @object)
        {
            if (RootNode == null) // create a new root-node if it does not exist yet.
            {
                var rootSize = new Size(System.Math.Ceiling(@object.Bounds.Width / MinimumLeafSize.Width),
                                        System.Math.Ceiling(@object.Bounds.Height / MinimumLeafSize.Height));

                double multiplier = System.Math.Max(rootSize.Width, rootSize.Height);
                rootSize = new Size(MinimumLeafSize.Width * multiplier, MinimumLeafSize.Height * multiplier);
                var center = new Point(@object.Bounds.X + @object.Bounds.Width / 2,
                                       @object.Bounds.Y + @object.Bounds.Height / 2);
                var rootOrigin = new Point(center.X - rootSize.Width / 2, center.Y - rootSize.Height / 2);

                this.RootNode = new QuadNode(new Rect(rootOrigin, rootSize));
            }

            while (!RootNode.Bounds.Contains(@object.Bounds))
            // if root-node's bounds does not contain object, expand the root.
            {
                this.ExpandRoot(@object.Bounds);
            }

            this.InsertNodeObject(RootNode, @object); // insert the object to rootNode.
        }
Exemplo n.º 6
0
 /// <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;
 }
Exemplo n.º 7
0
        /// <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;
                }
            }
        }
Exemplo n.º 8
0
 /// <summary>
 /// Adds an object to a given node.
 /// </summary>
 /// <param name="node"></param>
 /// <param name="object"></param>
 private void AddObjectToNode(QuadNode node, WorldObject @object)
 {
     node.ContainedObjects.TryAdd(@object.DynamicID, @object);
     _objectToNodeLookup.TryAdd(@object, node);
     @object.PositionChanged += ObjectPositionChanged;
 }