コード例 #1
0
    private void InspectLeaf([NotNull] QuadTreeLeaf visitedLeaf, [NotNull] IAABBox viewBox)
    {
        var planetRawData = visitedLeaf.GetPlanetsRawData();

        if (planetRawData == null)
        {
            return;
        }
        for (int i = 0; i < planetRawData.Length; ++i)
        {
            if (!IsPlanetInCamera(i, viewBox, visitedLeaf))
            {
                continue;
            }

            var posToInsert = FindPosToInsert(mVisiblePlanets, i, visitedLeaf);

            if (posToInsert != -1)
            {
                mVisiblePlanets.Insert(posToInsert, visitedLeaf.GetPlanetData(i));
                if (mVisiblePlanets.Count > mConstants.GetPlanetsToVisualize())
                {
                    mVisiblePlanets.RemoveAt(mVisiblePlanets.Count - 1);
                }
                continue;
            }
            if (mVisiblePlanets.Count < mConstants.GetPlanetsToVisualize())
            {
                mVisiblePlanets.Add(visitedLeaf.GetPlanetData(i));
                continue;
            }
            break;
        }
    }
コード例 #2
0
        public IEnumerable <T> Query(float in_left, float in_top, float in_width, float in_height)
        {
            Stack <QuadTreeNode> stack   = new Stack <QuadTreeNode>();
            QuadTreeNode         current = m_root;

            while (current != null)
            {
                if (current.Children != null)
                {
                    QuadTreeNode[] children = current.Children;

                    if (children[2].Bounds != null && children[2].Bounds.IsOverlapping(in_left, in_top, in_width, in_height))
                    {
                        stack.Push(children[2]);
                    }

                    if (children[1].Bounds != null && children[1].Bounds.IsOverlapping(in_left, in_top, in_width, in_height))
                    {
                        stack.Push(children[1]);
                    }

                    if (children[3].Bounds != null && children[3].Bounds.IsOverlapping(in_left, in_top, in_width, in_height))
                    {
                        stack.Push(children[3]);
                    }

                    if (children[0].Bounds != null && children[0].Bounds.IsOverlapping(in_left, in_top, in_width, in_height))
                    {
                        stack.Push(children[0]);
                    }
                }
                else
                {
                    QuadTreeLeaf node = current.Data;

                    while (node != null)
                    {
                        if (node.Data.X > in_left && node.Data.X < in_left + in_width && node.Data.Y > in_top && node.Data.Y < in_top + in_height)
                        {
                            yield return(node.Data);
                        }

                        node = node.Next;
                    }
                }

                if (stack.Count > 0)
                {
                    current = stack.Pop();
                }
                else
                {
                    break;
                }
            }
        }
コード例 #3
0
    private bool IsPlanetInCamera(int planetIndex, [NotNull] IAABBox cameraBox, [NotNull] QuadTreeLeaf visitedLeaf)
    {
        var planetData   = visitedLeaf.GetPlanetData(planetIndex);
        var cameraTop    = cameraBox.GetY() + cameraBox.GetHeight() / 2f;
        var cameraBottom = cameraTop - cameraBox.GetHeight();
        var cameraLeft   = cameraBox.GetX() - cameraBox.GetWidth() / 2f;
        var cameraRight  = cameraLeft + cameraBox.GetWidth();

        if ((cameraTop >= planetData.Y && cameraBottom <= planetData.Y) &&
            (cameraLeft <= planetData.X && cameraRight >= planetData.X))
        {
            return(true);
        }

        return(false);
    }
コード例 #4
0
        public void TraverseNodesAndLeafs(DataProcessCallback in_data_process_callback, NodeProcessCallback in_node_process_callback)
        {
            Stack <QuadTreeNode> stack   = new Stack <QuadTreeNode>();
            QuadTreeNode         current = m_root;

            while (true)
            {
                if (current.Children != null)
                {
                    if (in_node_process_callback != null)
                    {
                        foreach (QuadTreeNode node in current.Children)
                        {
                            in_node_process_callback(node.Bounds);
                        }
                    }

                    stack.Push(current.Children[2]);
                    stack.Push(current.Children[1]);
                    stack.Push(current.Children[3]);
                    current = current.Children[0];
                }
                else
                {
                    QuadTreeLeaf node = current.Data;

                    while (node != null)
                    {
                        in_data_process_callback(node.Data);


                        node = node.Next;
                    }

                    if (stack.Count > 0)
                    {
                        current = stack.Pop();
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
コード例 #5
0
            private void Read(BinaryReader input)
            {
                flag = input.ReadInt16();
                var bitMask = flag;

                for (int i = 0; i < 16; i++)
                {
                    if ((bitMask & 1) == 1)
                    {
                        subTrees[i] = new QuadTreeNode(input);
                    }
                    else
                    {
                        subTrees[i] = new QuadTreeLeaf(input);
                    }
                    bitMask >>= 1;
                }
            }
コード例 #6
0
            public QuadTreeParent(Rect rect, GetBoundingRectangle getBoundingRectangle, IEnumerable <T> items)
            {
                Rect = rect;

                _getBounding = getBoundingRectangle;

                var left       = rect.Left;
                var top        = rect.Top;
                var halfWidth  = rect.Width / 2.0;
                var halfHeight = rect.Height / 2.0;

                NodeTopLeft     = new QuadTreeLeaf(new Rect(left, top, halfWidth, halfHeight), _getBounding);
                NodeTopRight    = new QuadTreeLeaf(new Rect(left + halfWidth, top, halfWidth, halfHeight), _getBounding);
                NodeBottomLeft  = new QuadTreeLeaf(new Rect(left, top + halfHeight, halfWidth, halfHeight), _getBounding);
                NodeBottomRight = new QuadTreeLeaf(new Rect(left + halfWidth, top + halfHeight, halfWidth, halfHeight), _getBounding);

                foreach (var item in items)
                {
                    AddItem(item);
                }
            }
コード例 #7
0
        public IEnumerator <T> GetEnumerator()
        {
            Stack <QuadTreeNode> stack   = new Stack <QuadTreeNode>();
            QuadTreeNode         current = m_root;

            while (current != null)
            {
                if (current.Children != null)
                {
                    stack.Push(current.Children[2]);
                    stack.Push(current.Children[1]);
                    stack.Push(current.Children[3]);
                    stack.Push(current.Children[0]);
                }
                else
                {
                    QuadTreeLeaf node = current.Data;

                    while (node != null)
                    {
                        yield return(node.Data);

                        node = node.Next;
                    }
                }

                if (stack.Count > 0)
                {
                    current = stack.Pop();
                }
                else
                {
                    break;
                }
            }
        }
コード例 #8
0
    private int FindPosToInsert([NotNull] List <PlanetData> planets, int planetIndex, [NotNull] QuadTreeLeaf visitedLeaf)
    {
        var posToInsert = -1;

        for (int j = mConstants.GetPlanetsToVisualize() - 1; j > -1; --j)
        {
            if (j > planets.Count - 1)
            {
                continue;
            }

            var inStoreDistance   = Math.Abs(mPlayer.Score - planets[j].Score);
            var pretenderDistance = Math.Abs(mPlayer.Score - visitedLeaf.GetPlanetRating(planetIndex));
            if (inStoreDistance > pretenderDistance)
            {
                posToInsert = j;
                continue;
            }
            if (inStoreDistance == pretenderDistance)
            {
                var pretenderPlanet = visitedLeaf.GetPlanetData(planetIndex);
                var distanceToStore = (mPlayer.GetX() - planets[j].X) * (mPlayer.GetX() - planets[j].X)
                                      + (mPlayer.GetY() - planets[j].Y) * (mPlayer.GetY() - planets[j].Y);
                var distanceToPretender = (mPlayer.GetX() - pretenderPlanet.X) * (mPlayer.GetX() - pretenderPlanet.X)
                                          + (mPlayer.GetY() - pretenderPlanet.Y) * (mPlayer.GetY() - pretenderPlanet.Y);
                if (distanceToPretender < distanceToStore)
                {
                    posToInsert = j;
                    continue;
                }
            }
            break;
        }
        return(posToInsert);
    }
コード例 #9
0
 public void AddVisited(QuadTreeLeaf visitedLeaf)
 {
     mVisibleLeaves.Add(visitedLeaf);
 }
コード例 #10
0
        public List <T> QueryNeighbours(float in_x, float in_y, int in_neighbours_count)
        {
            QuadTreeFloatPointRegion neighbour_region = new QuadTreeFloatPointRegion(in_x, in_y, 0);
            Stack <QuadTreeNode>     stack            = new Stack <QuadTreeNode>();
            QuadTreeNode             current;

            List <T> neighbours = new List <T>();

            double[] neighbour_distances       = new double[in_neighbours_count];
            double   neighbours_worst_distance = 0;
            int      neighbours_worst_index    = 0;

            // set root node as current
            current = m_root;

            while (current != null)
            {
                // move downwards if this node has child nodes
                if (current.Children != null)
                {
                    // store regions in the stack and continue with the closest region
                    double closest_region_distance;
                    int    closest_region_index;

                    // find closest region
                    closest_region_index    = 0;
                    closest_region_distance = current.Children[0].Bounds.GetSquaredDistanceOfCenter(in_x, in_y);

                    for (int i = 0; i < 4; i++)
                    {
                        double distance = current.Children[i].Bounds.GetSquaredDistanceOfCenter(in_x, in_y);
                        if (distance < closest_region_distance)
                        {
                            closest_region_distance = distance;
                            closest_region_index    = i;
                        }
                    }

                    // store regions
                    for (int i = 0; i < 4; i++)
                    {
                        if (i == closest_region_index)
                        {
                            continue;
                        }

                        // if the neighbor region is defined then store only the overlapping regions, otherwise store all regions
                        if (neighbour_region.HalfSize == 0 || current.Children[i].Bounds.IsOverlapping(neighbour_region))
                        {
                            stack.Push(current.Children[i]);
                        }
                    }

                    // continue processing with the closest	region
                    current = current.Children[closest_region_index];
                }
                else
                {
                    // process data points
                    QuadTreeLeaf current_leaf_entry = current.Data;

                    while (current_leaf_entry != null)
                    {
                        // calculate distance (squared)
                        double squared_distance = current_leaf_entry.GetSquaredDistance(in_x, in_y);

                        if (current.Data != null)
                        {
                            // simply store data point if the list is not full
                            if (neighbours.Count < in_neighbours_count)
                            {
                                if (neighbours.Count == 0)
                                {
                                    neighbours_worst_distance = squared_distance;
                                    neighbours_worst_index    = 0;
                                }
                                else
                                {
                                    if (squared_distance > neighbours_worst_distance)
                                    {
                                        neighbours_worst_distance = squared_distance;
                                        neighbours_worst_index    = neighbours.Count;
                                    }
                                }

                                // add this item to the neighbours list
                                neighbour_distances[neighbours.Count] = squared_distance;
                                neighbours.Add(current_leaf_entry.Data);

                                // if the required number of neighbour is found store the worst distance in the region
                                if (neighbours.Count == in_neighbours_count)
                                {
                                    neighbour_region.HalfSize = (float)Math.Sqrt(neighbours_worst_distance);
                                }
                            }
                            else
                            {
                                // list is full, store only when this item is closer than the worst item (largest distance) in the list
                                if (squared_distance < neighbours_worst_distance)
                                {
                                    // replace worst element
                                    neighbour_distances[neighbours_worst_index] = squared_distance;
                                    neighbours[neighbours_worst_index]          = current_leaf_entry.Data;

                                    // find the current worst element
                                    neighbours_worst_index    = 0;
                                    neighbours_worst_distance = neighbour_distances[0];
                                    for (int i = 1; i < in_neighbours_count; i++)
                                    {
                                        if (neighbour_distances[i] > neighbours_worst_distance)
                                        {
                                            neighbours_worst_distance = neighbour_distances[i];
                                            neighbours_worst_index    = i;
                                        }
                                    }

                                    neighbour_region.HalfSize = (float)Math.Sqrt(neighbours_worst_distance);
                                }
                            }
                        }

                        current_leaf_entry = current_leaf_entry.Next;
                    }

                    // get new element from the stack or exit if no more element to investigate
                    do
                    {
                        if (stack.Count > 0)
                        {
                            current = stack.Pop();
                        }
                        else
                        {
                            current = null;
                            break;
                        }

                        // if the neighbour region is know skip all elements with a non-overlapping region
                    } while (neighbour_region.HalfSize > 0 && !current.Bounds.IsOverlapping(neighbour_region));
                }
            }

            return(neighbours);
        }
コード例 #11
0
        /// <summary>
        /// Internal recursive insert function
        /// </summary>
        /// <param name="in_current_node"></param>
        /// <param name="in_node_to_insert"></param>
        private void Insert(QuadTreeNode in_current_node, QuadTreeLeaf in_node_to_insert)
        {
            // check if point ot insert is inside -> if it is not then it can not be child of this node
            if (!in_current_node.Bounds.IsPointInside(in_node_to_insert.Data))
            {
                return;
            }

            QuadTreeLeaf nodes_to_insert = null;
            QuadTreeLeaf node;
            int          quadrant;

            // if this node is leaf
            if (in_current_node.Children == null)
            {
                // this is the first data item in the leaf
                if (in_current_node.Data == null)
                {
                    in_current_node.Data = in_node_to_insert;

                    return;
                }
                else
                {
                    int item_count = 0;

                    // add to the end of list of data
                    node = in_current_node.Data;
                    while (true)
                    {
                        if (Math.Abs(in_node_to_insert.Data.X - node.Data.X) <= float.Epsilon && Math.Abs(in_node_to_insert.Data.Y - node.Data.Y) <= float.Epsilon)
                        {
                            throw new ArgumentException("Key already exists");
                        }

                        item_count++;

                        if (node.Next != null)
                        {
                            node = node.Next;
                        }
                        else
                        {
                            break;
                        }
                    }

                    // there is room for this item
                    if (item_count < m_bucket_capacity)
                    {
                        // add node to the list of data
                        node.Next = in_node_to_insert;

                        return;
                    }

                    // current node needs to be splitted
                    nodes_to_insert = (QuadTreeLeaf)in_current_node.Data;

                    // remove data
                    in_current_node.Data = null;
                }
            }
            else
            {
                // move downward on the tree following the apropriate quadrant
                quadrant = in_current_node.Bounds.GetQuadrantIndex(in_node_to_insert.Data);

                Insert(in_current_node.Children[quadrant], in_node_to_insert);

                return;
            }

            // subdivide current node
            QuadTreeFloatPointRegion bounds = in_current_node.Bounds;
            float half = bounds.HalfSize / 2;

            QuadTreeNode[] subdivision = new QuadTreeNode[4] {
                new QuadTreeNode(new QuadTreeFloatPointRegion(bounds.CenterX - half, bounds.CenterY - half, half)),
                new QuadTreeNode(new QuadTreeFloatPointRegion(bounds.CenterX + half, bounds.CenterY - half, half)),
                new QuadTreeNode(new QuadTreeFloatPointRegion(bounds.CenterX - half, bounds.CenterY + half, half)),
                new QuadTreeNode(new QuadTreeFloatPointRegion(bounds.CenterX + half, bounds.CenterY + half, half))
            };

            // insert node
            quadrant = bounds.GetQuadrantIndex(in_node_to_insert.Data);

            Insert(subdivision[quadrant], in_node_to_insert);

            // insert nodes from the splitted node
            node = nodes_to_insert;
            QuadTreeLeaf next_node;

            while (node != null)
            {
                next_node = node.Next;
                node.Next = null;

                quadrant = bounds.GetQuadrantIndex(node.Data);

                Insert(subdivision[quadrant], node);

                node = next_node;
            }

            in_current_node.Children = subdivision;
        }
コード例 #12
0
        /// <summary>
        /// Inserts a new node
        /// </summary>
        /// <param name="in_data"></param>
        public void Insert(T in_data)
        {
            QuadTreeLeaf node = new QuadTreeLeaf(in_data);

            Insert(m_root, node);
        }
コード例 #13
0
 public QuadTreeNode(QuadTreeFloatPointRegion in_region)
 {
     Bounds   = in_region;
     Children = null;
     Data     = null;
 }
コード例 #14
0
 public QuadTreeLeaf(T in_data)
 {
     Data = in_data;
     Next = null;
 }