/// <summary> /// Search for closest elements to the given query in increasing order of distance (L2) /// </summary> public IEnumerable <T> Find(IVector x) { // Setup the priority queue for the search _pq = new PriorityQueue <PQEntry, PQEntry>(); _closest = new Vector(x.Dimensions); // Search is started at root this.Tree.InternalBounds.Closest(x, ref _closest); double dist2 = VectorReductions.SquaredL2NormDistance(x, _closest); if (dist2 <= this.SquaredDistanceLimit) { PQEntry root_entry = PQEntry.CreateNodeEntry(dist2, this.Tree); _pq.Push(root_entry, root_entry); } int found = 0; while (found < this.CountLimit && _pq.Count > 0) { PQEntry entry = _pq.Pop(); if (entry.NodeEntry) { this.ProcessNodeEntry(entry, x); } else { yield return(entry.Element); found += 1; } } }
/// <summary> /// Process a node /// </summary> private void ProcessNodeEntry(PQEntry entry, IVector x) { KdNode <T> node = entry.Node; double dist2; if (node.Leaf) { foreach (T t in node.Vectors) { dist2 = VectorReductions.SquaredL2NormDistance(x, t); if (dist2 <= this.SquaredDistanceLimit) { PQEntry e = PQEntry.CreateElementEntry(dist2, t); _pq.Push(e, e); } } } else { node.Left.InternalBounds.Closest(x, ref _closest); dist2 = VectorReductions.SquaredL2NormDistance(x, _closest); if (dist2 <= this.SquaredDistanceLimit) { PQEntry left = PQEntry.CreateNodeEntry(dist2, node.Left); _pq.Push(left, left); } node.Right.InternalBounds.Closest(x, ref _closest); dist2 = VectorReductions.SquaredL2NormDistance(x, _closest); if (dist2 <= this.SquaredDistanceLimit) { PQEntry right = PQEntry.CreateNodeEntry(dist2, node.Right); _pq.Push(right, right); } } }