Example #1
0
        /// <summary>
        ///   Creates the root node for a new <see cref="KdTree{T}"/> given
        ///   a set of data points and their respective stored values.
        /// </summary>
        ///
        /// <param name="points">The data points to be inserted in the tree.</param>
        /// <param name="values">The values associated with each point.</param>
        /// <param name="leaves">Return the number of leaves in the root subtree.</param>
        /// <param name="inPlace">Whether the given <paramref name="points"/> vector
        ///   can be ordered in place. Passing true will change the original order of
        ///   the vector. If set to false, all operations will be performed on an extra
        ///   copy of the vector.</param>
        ///
        /// <returns>The root node for a new <see cref="KdTree{T}"/>
        ///   contained the given <paramref name="points"/>.</returns>
        ///
        protected static KDTreeNode <T> CreateRoot(double[][] points, T[] values, bool inPlace, out int leaves)
        {
            // Initial argument checks for creating the tree
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            if (values != null && points.Length != values.Length)
            {
                throw new Exception("values");
            }

            if (!inPlace)
            {
                points = (double[][])points.Clone();

                if (values != null)
                {
                    values = (T[])values.Clone();
                }
            }

            leaves = 0;

            int dimensions = points[0].Length;

            // Create a comparer to compare individual array
            // elements at specified positions when sorting
            ElementComparer comparer = new ElementComparer();

            // Call the recursive algorithm to operate on the whole array (from 0 to points.Length)
            KDTreeNode <T> root = create(points, values, 0, dimensions, 0, points.Length, comparer, ref leaves);

            // Create and return the newly formed tree
            return(root);
        }
Example #2
0
        private static KDTreeNode <T> create(double[][] points, T[] values,
                                             int depth, int k, int start, int length, ElementComparer comparer, ref int leaves)
        {
            if (length <= 0)
            {
                return(null);
            }

            // We will be doing sorting in place
            int axis = comparer.Index = depth % k;

            Array.Sort(points, values, start, length, comparer);

            // Middle of the input section
            int half = start + length / 2;

            // Start and end of the left branch
            int leftStart  = start;
            int leftLength = half - start;

            // Start and end of the right branch
            int rightStart  = half + 1;
            int rightLength = length - length / 2 - 1;

            // The median will be located halfway in the sorted array
            var median = points[half];
            var value  = values != null ? values[half] : default(T);

            depth++;

            // Continue with the recursion, passing the appropriate left and right array sections
            KDTreeNode <T> left  = create(points, values, depth, k, leftStart, leftLength, comparer, ref leaves);
            KDTreeNode <T> right = create(points, values, depth, k, rightStart, rightLength, comparer, ref leaves);

            if (left == null && right == null)
            {
                leaves++;
            }

            // Backtrack and create
            return(new KDTreeNode <T>()
            {
                Axis = axis,
                Position = median,
                Value = value,
                Left = left,
                Right = right,
            });
        }