/// <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); }
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, }); }