/// <summary>
        /// Splits a node based on bucket size, the chosen split dimension selector and chosen split location selector
        /// </summary>
        public void Split <T>(KdNode <T> target) where T : IVector
        {
            // Sanity check node
            if (target.Intermediate)
            {
                throw new IntermediateNodeException();
            }

            if (target.Vectors.Count <= this.MaximumBucketSize)
            {
                throw new BucketSizeException();
            }

            // Find axis of split plane
            int split_dim = _dim_selector.Select(target);
            // Find location of split plane
            double split_loc = _loc_selector.Select(target, split_dim);

            // Possibly resolve a trivial split
            ETrivialSplitType split_type = this.IsTrivialSplit(target, split_dim, split_loc);

            if (split_type == ETrivialSplitType.EmptyLeft || split_type == ETrivialSplitType.EmptyRight)
            {
                split_loc = _trivial_resolver.Resolve(target, split_dim, split_loc, split_type);
            }

            // Pass over vectors, create leaves (one is possibly empty) and update parent
            KdNode <T> left  = target.SetLeftChild(new KdNode <T>());
            KdNode <T> right = target.SetRightChild(new KdNode <T>());

            // Assign vectors
            left.Vectors  = new List <T>();
            right.Vectors = new List <T>();

            // Classify each vector
            foreach (T t in target.Vectors)
            {
                if (t[split_dim] <= split_loc)
                {
                    left.Vectors.Add(t);
                }
                else
                {
                    right.Vectors.Add(t);
                }
            }

            // Update internal bounds
            left.InternalBounds = new AABB(target.InternalBounds.Dimensions);
            left.InternalBounds.Enlarge <T>(left.Vectors);

            right.InternalBounds = new AABB(target.InternalBounds.Dimensions);
            right.InternalBounds.Enlarge <T>(right.Vectors);

            // Update target
            target.SplitDimension = split_dim;
            target.SplitLocation  = split_loc;
        }
Пример #2
0
 public double Resolve <T> (KdNode <T> target, int split_dimension, double split_location, ETrivialSplitType tst) where T : IVector
 {
     if (tst == ETrivialSplitType.EmptyLeft)
     {
         return(ResolveLeftEmpty(target, split_dimension, split_location));
     }
     else if (tst == ETrivialSplitType.EmptyRight)
     {
         return(ResolveRightEmpty(target, split_dimension, split_location));
     }
     else
     {
         throw new SubdivisionException();
     }
 }
Пример #3
0
 /// <summary>
 /// Always keeps the trivial split.
 /// </summary>
 public double Resolve <T> (KdNode <T> target, int split_dimension, double split_location, ETrivialSplitType tst) where T : IVector
 {
     return(split_location);
 }