/// <summary>
        ///   Creates a new k-dimensional tree from the given points.
        /// </summary>
        ///
        /// <typeparam name="T">The type of the value to be stored.</typeparam>
        ///
        /// <param name="points">The points to be added to the tree.</param>
        /// <param name="distance">The distance function to use.</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>A <see cref="KDTree{T}"/> populated with the given data points.</returns>
        ///
        public static KDTree <T> FromData <T>(double[][] points, Func <double[], double[], double> distance,
                                              bool inPlace = false)
        {
            if (distance == null)
            {
                throw new ArgumentNullException("distance");
            }

            int leaves;

            var root = KDTree <T> .CreateRoot(points, inPlace, out leaves);

            return(new KDTree <T>(points[0].Length, root, points.Length, leaves)
            {
                Distance = distance
            });
        }
        /// <summary>
        ///   Creates a new k-dimensional tree from the given points.
        /// </summary>
        ///
        /// <typeparam name="T">The type of the value to be stored.</typeparam>
        ///
        /// <param name="points">The points to be added to the tree.</param>
        /// <param name="values">The corresponding values at each data point.</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>A <see cref="KDTree{T}"/> populated with the given data points.</returns>
        ///
        public static KDTree <T> FromData <T>(double[][] points, T[] values, bool inPlace = false)
        {
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            if (points.Length == 0)
            {
                throw new ArgumentException("Insufficient points for creating a tree.");
            }

            int leaves;

            var root = KDTree <T> .CreateRoot(points, values, inPlace, out leaves);

            return(new KDTree <T>(points[0].Length, root, points.Length, leaves));
        }