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