Exemple #1
0
 /// <summary>
 /// Simple copy constructor that assumes the structure of the existing KD Tree is
 /// intact
 /// </summary>
 /// <param name="_toCopy">The KD Tree to copy</param>
 private void CopyConstructor(KDTree <T> _toCopy)
 {
     m_axisCount        = _toCopy.m_axisCount;
     m_selector         = _toCopy.m_selector;
     m_count            = _toCopy.m_count;
     m_distanceFunction = _toCopy.m_distanceFunction;
     m_tree             = _toCopy.m_tree.Clone();
 }
Exemple #2
0
 /// <summary>
 /// Construct a new K-D Tree, using the default selector for objects. This is a
 /// performance-hindered version, as it relies on
 /// <see cref="IMultiDimensionalPoint"/> .
 /// </summary>
 public KDTree()
 {
     m_distanceFunction = GetMultiDimensionalDistance;
     if (!IsTMultiDimensional())
     {
         throw new InvalidOperationException("The underlying type " + typeof(T).ToString() + " does not implement IMultidimensionalPoint and no selector was specified.");
     }
     m_tree = new SparseLeafBinaryTree <T>(1023);
 }
Exemple #3
0
 /// <summary>
 /// Construct a new K-D Tree, using the specified selector for objects
 /// </summary>
 public KDTree(int _axisCount, Func <T, int, double> _selector, Func <T, T, double> _distanceFunction = null)
 {
     if (_axisCount < 1)
     {
         throw new ArgumentOutOfRangeException("Axis Count", _axisCount, "Axis Count must be greater than 1");
     }
     m_selector         = _selector ?? throw new ArgumentNullException("_selector", "The selector cannot be null");
     m_axisCount        = _axisCount;
     m_distanceFunction = _distanceFunction ?? GetMultiDimensionalDistance;
     m_tree             = new SparseLeafBinaryTree <T>(1023);
 }
        /// <summary>
        /// Create a shallow copy of this binary tree
        /// </summary>
        /// <returns></returns>
        public SparseLeafBinaryTree <T> Clone()
        {
            var clone = new SparseLeafBinaryTree <T>(m_root.Length)
            {
                m_root = (T[])m_root.Clone()
            };

            foreach (var kv in m_leaves)
            {
                clone.m_leaves[kv.Key] = kv.Value;
            }
            return(clone);
        }
Exemple #5
0
        /// <summary>
        /// Set up the K-D Tree based on an enumeration of elements. If the enumeration is
        /// another KDTree of type T, then a copy constructor <see cref="Clone"/> will be
        /// used.
        /// </summary>
        /// <param name="_collection">The collection of objects</param>
        /// <param name="_axisCount">
        /// The number of dimensions present in this KD Tree... use default if T implements
        /// <see cref="IMultiDimensionalPoint"/>
        /// </param>
        /// <param name="_selector">
        /// The selector to use on the objects- if NULL, relies on the objects to implement
        /// <see cref="IMultiDimensionalPoint"/>
        /// </param>
        /// <param name="_distanceFunction">
        /// A function that determines the distance between two nodes in the tree. Assumes
        /// Distances are measured using double precision floating point scalar values.
        /// </param>
        /// <remarks>
        /// If _axisCount == -1 and/or _selector == null, then T MUST implement
        /// <see cref="IMultiDimensionalPoint"/> .
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if _axisCount is less than 1 AND T is not an implementation of
        /// ArgumentOutOfRangeException
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// Thrown if _selector is NULL AND T is not an implementation of
        /// ArgumentOutOfRangeException
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown if _axisCount is less than 1 AND there are no elements in the
        /// collection, even if T implements <see cref="IMultiDimensionalPoint"/> .
        /// </exception>
        public KDTree(IEnumerable <T> _collection, int _axisCount = -1, Func <T, int, double> _selector = null, Func <T, T, double> _distanceFunction = null)
        {
            if (_collection is KDTree <T> ) // we know the internal storage is already a KD Tree- simply copy it
            {
                CopyConstructor(_collection as KDTree <T>);
                return;
            }

            m_distanceFunction = _distanceFunction ?? GetMultiDimensionalDistance;
            if (!IsTMultiDimensional())
            {
                if (_axisCount < 1)
                {
                    throw new ArgumentOutOfRangeException("Axis Count", _axisCount, "Axis Count must be at least 1");
                }
                if (_selector == null)
                {
                    throw new ArgumentNullException("_selector", "The selector cannot be null if T doesn't inherit IMultiDimensionalPoint");
                }
            }

            if (_axisCount > 0)
            {
                m_axisCount = _axisCount;
            }
            if (_selector != null)
            {
                m_selector = _selector;
            }

            var array = _collection.ToArray(); // Construct using an array

            m_tree  = new SparseLeafBinaryTree <T>(array.Length);
            m_count = array.Length;

            if (m_count > 0)
            {
                if (m_axisCount < 1)
                {
                    m_axisCount = (array[0] as IMultiDimensionalPoint).GetAxisCount();
                }

                BuildComparers();
                ConstructFromArray(array, 0, array.Length - 1, 0, 0);
            }

            if (m_axisCount < 1)
            {
                throw new ArgumentException("May not specify an empty collection when an explicit Axis Count has not been specified");
            }
        }
Exemple #6
0
        /// <summary>
        /// Use this method when a significant number of nodes have been added to the tree
        /// after its construction. This has the effect of re-balancing the tree. This is
        /// not a cheap operation - O(n log n)
        /// </summary>
        public void RebuildTree(int _capacity)
        {
            var items = new T[m_count];
            var idx   = 0;

            foreach (var item in this)
            {
                items[idx++] = item;
            }

            m_tree = new SparseLeafBinaryTree <T>(_capacity);
            BuildComparers();
            ConstructFromArray(items, 0, items.Length - 1, 0, 0);
        }