Example #1
0
 /// <summary>
 ///  FindRange method
 ///  Method for searching elements in concrete range
 /// </summary>
 /// <param name="x1"></param>
 /// <param name="y1"></param>
 /// <param name="x2"></param>
 /// <param name="y2"></param>
 /// <param name="node"></param>
 /// <param name="xDimension">True is first dimension</param>
 /// <param name="result">List of searching elements</param>
 private void FindRange(T x1, T y1, T x2, T y2, Node node, bool xDimension, ref List <TData> result)
 {
     if (node != null)
     {
         // When get leaf, control its coordinates
         // and add to result list if they in the range
         if (node is Leaf leaf)
         {
             if (IsInsideRangeX(x1, x2, leaf) &&
                 IsInsideRangeY(y1, y2, leaf))
             {
                 result.Add(leaf.Data);
             }
         }
         // Actions for navigation nodes
         else
         {
             NavigationalNode navigational = node as NavigationalNode;
             // Search in first dimension
             if (xDimension)
             {
                 // If whole interval is inside the range go to second dimension
                 if (x1.CompareTo(navigational.Min) <= 0 &&
                     navigational.Max.CompareTo(x2) <= 0)
                 {
                     FindRange(x1, y1, x2, y2, navigational.OtherDimensionNode, !xDimension, ref result);
                 }
                 // If whole interval is out of range do nothing
                 else if (navigational.Max.CompareTo(x1) <= 0 ||
                          navigational.Min.CompareTo(x2) >= 0)
                 {
                 }
                 // If part of interval is inside the range go find to both children
                 else if (navigational.Min.CompareTo(x1) <= 0 ||
                          x2.CompareTo(navigational.Max) <= 0)
                 {
                     FindRange(x1, y1, x2, y2, navigational.LeftChild, xDimension, ref result);
                     FindRange(x1, y1, x2, y2, navigational.RightChild, xDimension, ref result);
                 }
             }
             // Search in second dimension
             else
             {
                 // If whole interval is inside the range look to all leafs of subtree
                 if (y1.CompareTo(navigational.Min) <= 0 &&
                     navigational.Max.CompareTo(y2) <= 0)
                 {
                     LookAllSubtree(x1, y1, x2, y2, navigational, ref result);
                 }
                 // If part of interval is inside the range go find to both children
                 else if (navigational.Min.CompareTo(y1) <= 0 ||
                          y2.CompareTo(navigational.Max) <= 0)
                 {
                     FindRange(x1, y1, x2, y2, navigational.LeftChild, xDimension, ref result);
                     FindRange(x1, y1, x2, y2, navigational.RightChild, xDimension, ref result);
                 }
             }
         }
     }
 }
Example #2
0
        /// <summary>
        ///  GoUp method
        ///  Part of GetRightSibling
        /// </summary>
        /// <param name="node">Current node</param>
        /// <returns>Right sibling for current node</returns>
        private Leaf GoUp(Node node)
        {
            NavigationalNode parent = node.Parent;

            // We got root via its right child
            // All leafs are worked out
            if (parent == null)
            {
                return(null);
            }
            // If we came via right child, go upper
            if (node == parent.RightChild)
            {
                return(GoUp(parent));
            }
            else
            {
                // If we came via left child go to most left child of right child
                if (parent.RightChild is NavigationalNode navigationalChild)
                {
                    return(GetMostLeftChild(navigationalChild));
                }
                else
                {
                    // Or return right child if it is leaf
                    return(parent.RightChild as Leaf);
                }
            }
        }
Example #3
0
        /// <summary>
        ///  BuildTree method
        ///  Call BuildSubtree method for X dimension, then for Y dimension
        /// </summary>
        /// <param name="datas">Elements stored in leafs</param>
        /// <param name="otherDimensionNode">X node for Y node</param>
        /// <param name="xDimension">Dimension where we are. If it's true, it's X</param>
        /// <returns>Subtree root</returns>
        private Node BuildTree(TData[] datas, NavigationalNode otherDimensionNode, bool xDimension)
        {
            Node pointer = BuildSubtree(datas, null, xDimension);

            if (otherDimensionNode != null)
            {
                (pointer as NavigationalNode).OtherDimensionNode = otherDimensionNode;
            }
            return(pointer);
        }
Example #4
0
        /// <summary>
        ///  BuildSubtree method
        ///  This method do most of work
        ///  for tree building.
        /// </summary>
        /// <param name="datas">Elements stored in leafs</param>
        /// <param name="parent">Parent of node, that this method must return</param>
        /// <param name="xDimension">Dimension where we are. If it's true, it's X</param>
        /// <returns>Node of tree</returns>
        private Node BuildSubtree(TData[] datas, NavigationalNode parent, bool xDimension)
        {
            Node pointer = null;

            if (datas.Length > 1)
            {
                // Set range for navigational node
                NavigationalNode node = new NavigationalNode();
                if (xDimension)
                {
                    Array.Sort(datas, comparerByX);
                    node.Min = datas.First().X;
                    node.Max = datas.Last().X;
                }
                else
                {
                    Array.Sort(datas, comparerByY);
                    node.Min = datas.First().Y;
                    node.Max = datas.Last().Y;
                }

                // Halve datas. One half of datas go to left subtree
                // the other one go to right subtree
                TData[] datasL = datas.Take(datas.Length / 2).ToArray();
                TData[] datasR = datas.Skip(datas.Length / 2).ToArray();

                node.LeftChild  = BuildSubtree(datasL, node, xDimension);
                node.RightChild = BuildSubtree(datasR, node, xDimension);

                pointer = node;
            }
            else
            {
                // if datas parametr has only one element
                // this one will be a leaf
                Leaf leaf = new Leaf();
                leaf.Data = datas.First();
                pointer   = leaf;
            }

            // If we are in X dimension and current node is navigational one,
            // go to Y Dimension and build tree for it
            if (xDimension && pointer is NavigationalNode navigational)
            {
                navigational.OtherDimensionNode = (NavigationalNode)BuildTree(datas, navigational, !xDimension);
            }

            // Set parametrs that are common for both leafs and navigational nodes
            pointer.XDimension = xDimension;
            pointer.Parent     = parent;
            return(pointer);
        }
Example #5
0
        /// <summary>
        ///  GetMostLeftChild method
        ///  Returns most left child in subtree
        /// </summary>
        /// <param name="node">Subtree root</param>
        /// <returns>Most left child</returns>
        private Leaf GetMostLeftChild(NavigationalNode node)
        {
            Node pointer = node.LeftChild;

            if (pointer is Leaf leaf)
            {
                return(leaf);
            }
            else
            {
                return(GetMostLeftChild(pointer as NavigationalNode));
            }
        }
Example #6
0
        /// <summary>
        ///  LookAllSubtree method
        ///  Take every leaf of subtree and
        ///  control its coordinates. If they
        ///  are inside range add to result list
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="node">Root of subtree</param>
        /// <param name="result">List of searching elements</param>
        private void LookAllSubtree(T x1, T y1, T x2, T y2, NavigationalNode node, ref List <TData> result)
        {
            // Find the most left child in subtree
            Leaf pointer = GetMostLeftChild(node);

            // If something went wrong and not all links was built
            if (pointer.RightSibling == null)
            {
                BuildLinks(pointer);
            }
            do
            {
                // Control leaf coordinates and add to
                // result list if they are inside range
                if (IsInsideRangeX(x1, x2, pointer) &&
                    IsInsideRangeY(y1, y2, pointer))
                {
                    result.Add(pointer.Data);
                }
                // Go to next leaf
                pointer = pointer.RightSibling;
                // End when all leafs was controlled
            } while (pointer != null);
        }