예제 #1
0
 private void MergeEmptyChildren(PartitionNode <T> node)
 {
     if (node.HasChildren() && node.AreExistingChildrenEmpty())
     {
         node.MergeEmptyChildren();
     }
     if (node.IsRootNode() || !node.IsEmpty() || node.HasChildren())
     {
         return;
     }
     foreach (var parent in node.GetParent())
     {
         MergeEmptyChildren(parent);
     }
 }
예제 #2
0
        public List <SpatialObj <T> > WindowQuery(Rectangle window)
        {
            // Finds objects within a Rectangular range (window)
            List <SpatialObj <T> >     answer          = new List <SpatialObj <T> >();
            Queue <PartitionNode <T> > searching_nodes = new Queue <PartitionNode <T> >();

            searching_nodes.Enqueue(rootNode);
            while (searching_nodes.Count > 0)
            {
                PartitionNode <T> current_node = searching_nodes.Dequeue();
                if (current_node.IntersectsWith(window))
                {
                    answer.AddRange(current_node.GetRangeQueryObj(window));
                    if (current_node.HasChildren())
                    {
                        foreach (PartitionNode <T> child in current_node.GetChildren())
                        {
                            if (!searching_nodes.Contains(child))
                            {
                                searching_nodes.Enqueue(child);
                            }
                        }
                    }
                }
            }
            return(answer);
        }
예제 #3
0
        public PartitionNode <T> AddRectangle(SpatialObj <T> rect, bool reorganize = true)
        {
            PartitionNode <T> deepest_field = FindContainingField(rect, rootNode);

            if (deepest_field.IsFull() && !deepest_field.HasChildren())
            {
                PartitionField(deepest_field);
                PartitionNode <T> node = AddRectangle(rect);
                if (reorganize)
                {
                    ReorganizeOverflownNodes();
                }
                if (node != null)
                {
                    return(node);
                }
            }
            else
            {
                bool overflown = deepest_field.StoreRectangle(rect);
            }
            if (deepest_field != null)
            {
                Count += 1;
            }
            return(deepest_field);
        }
예제 #4
0
        public Tuple <PartitionNode <T>, SpatialObj <T> > IncrementalNNFindNext()
        {
            if (incrNN_queue is null)
            {
                return(null);
            }

            while (incrNN_queue.Count > 0)
            {
                NodeOrObj current_element = incrNN_queue.Dequeue();
                while (incrNN_queue.Count > 0 && incrNN_queue.First().Equals(current_element))
                {
                    incrNN_queue.Dequeue();
                }

                if (current_element.IsObj())
                {
                    return(Tuple.Create(current_element.GetNode(), current_element.GetObj()));
                }
                else
                {
                    PartitionNode <T> current_node = current_element.GetNode();
                    double            current_dist = current_node.GetDistanceToPointSq(incrNN_origin);

                    if (!current_node.IsEmpty())
                    {
                        foreach (SpatialObj <T> obj in current_node.GetAllObjects())
                        {
                            double distance = obj.boundingBox.GetDistanceSqToPoint(incrNN_origin);
                            if (distance >= current_dist)
                            {
                                NodeOrObj obj_nodeOrObj = new NodeOrObj();
                                obj_nodeOrObj.SetNode(current_node);
                                obj_nodeOrObj.SetObj(obj);
                                incrNN_queue.Enqueue(obj_nodeOrObj, (float)distance);
                            }
                        }
                    }
                    if (current_node.HasChildren())
                    {
                        foreach (PartitionNode <T> child_node in current_node.GetChildren())
                        {
                            double distance = child_node.GetDistanceToPointSq(incrNN_origin);
                            if (distance >= current_dist)
                            {
                                NodeOrObj node_nodeOrObj = new NodeOrObj();
                                node_nodeOrObj.SetNode(child_node);
                                incrNN_queue.Enqueue(node_nodeOrObj, (float)distance);
                            }
                        }
                    }
                }
            }
            return(null);
        }
예제 #5
0
        private Dictionary <PartitionNode <T>, SpatialObj <T> > FindNearestRectToPoint(Point p, PartitionNode <T> node)
        {
            Dictionary <PartitionNode <T>, SpatialObj <T> > answer_dict     = new Dictionary <PartitionNode <T>, SpatialObj <T> >();
            SimplePriorityQueue <PartitionNode <T> >        searching_nodes = new SimplePriorityQueue <PartitionNode <T> >();

            searching_nodes.Enqueue(node, 0);

            SpatialObj <T>    answer      = default(SpatialObj <T>);
            PartitionNode <T> answer_node = null;
            bool used = false;

            double min_distance_sq = rootNode.GetMaxDistance();

            while (searching_nodes.Count > 0)
            {
                PartitionNode <T> current_node = searching_nodes.Dequeue();
                Dictionary <SpatialObj <T>, double> nearest_rect = current_node.GetNearestRectangle(p);
                if (nearest_rect.Count > 0)
                {
                    foreach (KeyValuePair <SpatialObj <T>, double> entry in nearest_rect)
                    {
                        if (entry.Value <= min_distance_sq || entry.Value < Statics.EPSILON)
                        {
                            min_distance_sq = entry.Value;
                            answer          = entry.Key;
                            answer_node     = current_node;
                            used            = false;
                            if (min_distance_sq < Statics.EPSILON)
                            {
                                answer_dict.Add(answer_node, answer);
                                used = true;
                            }
                        }
                    }
                }
                if (current_node.HasChildren())
                {
                    foreach (PartitionNode <T> child in current_node.GetChildren())
                    {
                        double field_dist = child.GetDistanceToPointSq(p);
                        if (field_dist <= min_distance_sq)
                        {
                            searching_nodes.Enqueue(child, (float)field_dist);
                        }
                    }
                }
            }
            if (!used)
            {
                answer_dict.Add(answer_node, answer);
            }
            return(answer_dict);
        }
예제 #6
0
        private void ReorganizeNode(PartitionNode <T> node)
        {
            // After adding objects and creating new partitions, checks to see if any of the upper level objects can go deeper into the tree.
            Queue <PartitionNode <T> > all_nodes = new Queue <PartitionNode <T> >();

            all_nodes.Enqueue(node);

            while (all_nodes.Count > 0)
            {
                List <SpatialObj <T> > rects_removed = new List <SpatialObj <T> >();
                PartitionNode <T>      current_node  = all_nodes.Dequeue();

                foreach (SpatialObj <T> rect in current_node.GetOverflowObjs())
                {
                    PartitionNode <T> deepest_field = FindContainingField(rect, current_node);

                    if (!deepest_field.Equals(current_node))
                    {
                        bool overflown = deepest_field.StoreRectangle(rect);
                        rects_removed.Add(rect);
                    }
                }
                if (rects_removed.Count > 0)
                {
                    current_node.DeleteRectangles(rects_removed, true);
                }

                if (current_node.HasChildren())
                {
                    foreach (PartitionNode <T> child in current_node.GetChildren())
                    {
                        all_nodes.Enqueue(child);
                    }
                }
            }
        }
예제 #7
0
 public bool IsEmpty()
 {
     return(rootNode.IsEmpty() && !rootNode.HasChildren());
 }