// Limited Best-Bin-First k-d-tree nearest neighbour search. // // (Using the algorithm described in the paper "Shape indexing using // approximate nearest-neighbour search in high-dimensional spaces", // available at http://www.cs.ubc.ca/spider/lowe/papers/cvpr97-abs.html) // // Find the approximate nearest neighbour to the hyperspace point 'target' // within the kd-tree using 'searchSteps' tail recursions at most (each // recursion deciding about one neighbours' fitness). // // After return 'resDist' contains the absolute distance of the // approximate nearest neighbour from the target point. The approximate // nearest neighbour is returned. public ArrayList NearestNeighbourListBBF(IKDTreeDomain target, int q, int searchSteps) { HyperRectangle hr = HyperRectangle.CreateUniverseRectangle(target.DimensionCount); SortedLimitedList best = new SortedLimitedList(q); SortedLimitedList searchHr = new SortedLimitedList(searchSteps); float dummyDist; IKDTreeDomain nearest = NearestNeighbourListBBFI(best, q, target, hr, Int32.MaxValue, out dummyDist, searchHr, ref searchSteps); foreach (BestEntry be in best) { be.Distance = Math.Sqrt(be.DistanceSq); } return(best); }
public ArrayList NearestNeighbourList(IKDTreeDomain target, out double resDist, int q) { HyperRectangle hr = HyperRectangle.CreateUniverseRectangle(target.DimensionCount); SortedLimitedList best = new SortedLimitedList(q); IKDTreeDomain nearest = NearestNeighbourListI(best, q, target, hr, Double.PositiveInfinity, out resDist); resDist = Math.Sqrt(resDist); foreach (BestEntry be in best) { be.Distance = Math.Sqrt(be.Distance); } return(best); }
private IKDTreeDomain NearestNeighbourListBBFI(SortedLimitedList best, int q, IKDTreeDomain target, HyperRectangle hr, float maxDistSq, out float resDistSq, SortedLimitedList searchHr, ref int searchSteps) { //Console.WriteLine ("C NearestNeighbourI called"); resDistSq = Int32.MaxValue; IKDTreeDomain pivot = dr; best.Add(new BestEntry(dr, KDTree.DistanceSq(target, dr), true)); HyperRectangle leftHr = hr; HyperRectangle rightHr = leftHr.SplitAt(splitDim, pivot.GetDimensionElement(splitDim)); HyperRectangle nearerHr, furtherHr; KDTree nearerKd, furtherKd; // step 5-7 if (target.GetDimensionElement(splitDim) <= pivot.GetDimensionElement(splitDim)) { nearerKd = left; nearerHr = leftHr; furtherKd = right; furtherHr = rightHr; } else { nearerKd = right; nearerHr = rightHr; furtherKd = left; furtherHr = leftHr; } // step 8 IKDTreeDomain nearest = null; float distSq; searchHr.Add(new HREntry(furtherHr, furtherKd, pivot, furtherHr.Distance(target))); // No child, bottom reached! if (nearerKd == null) { distSq = Int32.MaxValue; } else { nearest = nearerKd.NearestNeighbourListBBFI(best, q, target, nearerHr, maxDistSq, out distSq, searchHr, ref searchSteps); } // step 9 if (best.Count >= q) { maxDistSq = ((BestEntry)best[q - 1]).DistanceSq; } else { maxDistSq = Int32.MaxValue; } if (searchHr.Count > 0) { HREntry hre = (HREntry)searchHr[0]; searchHr.RemoveAt(0); furtherHr = hre.HR; furtherKd = hre.Tree; pivot = hre.Pivot; } // step 10 searchSteps -= 1; if (searchSteps > 0 && furtherHr.IsInReach(target, Math.Sqrt(maxDistSq))) { float ptDistSq = KDTree.DistanceSq(pivot, target); if (ptDistSq < distSq) { // steps 10.1.1 to 10.1.3 nearest = pivot; distSq = ptDistSq; maxDistSq = distSq; } // step 10.2 float tempDistSq; IKDTreeDomain tempNearest = null; if (furtherKd == null) { tempDistSq = Int32.MaxValue; } else { tempNearest = furtherKd.NearestNeighbourListBBFI(best, q, target, furtherHr, maxDistSq, out tempDistSq, searchHr, ref searchSteps); } // step 10.3 if (tempDistSq < distSq) { nearest = tempNearest; distSq = tempDistSq; } } resDistSq = distSq; return(nearest); }
private IKDTreeDomain NearestNeighbourListI(SortedLimitedList best, int q, IKDTreeDomain target, HyperRectangle hr, double maxDistSq, out double resDistSq) { //Console.WriteLine ("C NearestNeighbourI called"); resDistSq = Double.PositiveInfinity; IKDTreeDomain pivot = dr; best.Add(new BestEntry(dr, KDTree.DistanceSq(target, dr))); HyperRectangle leftHr = hr; HyperRectangle rightHr = leftHr.SplitAt(splitDim, pivot.GetDimensionElement(splitDim)); HyperRectangle nearerHr, furtherHr; KDTree nearerKd, furtherKd; // step 5-7 if (target.GetDimensionElement(splitDim) <= pivot.GetDimensionElement(splitDim)) { nearerKd = left; nearerHr = leftHr; furtherKd = right; furtherHr = rightHr; } else { nearerKd = right; nearerHr = rightHr; furtherKd = left; furtherHr = leftHr; } // step 8 IKDTreeDomain nearest = null; double distSq; // No child, bottom reached! if (nearerKd == null) { distSq = Double.PositiveInfinity; } else { nearest = nearerKd.NearestNeighbourListI(best, q, target, nearerHr, maxDistSq, out distSq); } // step 9 //maxDistSq = Math.Min (maxDistSq, distSq); if (best.Count >= q) { maxDistSq = ((BestEntry)best[q - 1]).Distance; } else { maxDistSq = Double.PositiveInfinity; } // step 10 if (furtherHr.IsInReach(target, Math.Sqrt(maxDistSq))) { double ptDistSq = KDTree.DistanceSq(pivot, target); if (ptDistSq < distSq) { // steps 10.1.1 to 10.1.3 nearest = pivot; distSq = ptDistSq; // TODO: use k-element list /* * best.Add (new BestEntry (pivot, ptDistSq)); * best.Sort (); */ maxDistSq = distSq; } // step 10.2 double tempDistSq; IKDTreeDomain tempNearest = null; if (furtherKd == null) { tempDistSq = Double.PositiveInfinity; } else { tempNearest = furtherKd.NearestNeighbourListI(best, q, target, furtherHr, maxDistSq, out tempDistSq); } // step 10.3 if (tempDistSq < distSq) { nearest = tempNearest; distSq = tempDistSq; } } resDistSq = distSq; return(nearest); }