Nearest-neighbor search via priority queue (min-heap).
(
nodes: &[Node],
root: usize,
query_lng: f64,
query_lat: f64,
k: usize,
is_empty: bool,
)
| 47 | |
| 48 | /// Nearest-neighbor search via priority queue (min-heap). |
| 49 | pub(crate) fn nearest( |
| 50 | nodes: &[Node], |
| 51 | root: usize, |
| 52 | query_lng: f64, |
| 53 | query_lat: f64, |
| 54 | k: usize, |
| 55 | is_empty: bool, |
| 56 | ) -> Vec<NnResult> { |
| 57 | if k == 0 || is_empty { |
| 58 | return Vec::new(); |
| 59 | } |
| 60 | |
| 61 | let mut heap: BinaryHeap<HeapItem> = BinaryHeap::new(); |
| 62 | let mut results: Vec<NnResult> = Vec::with_capacity(k); |
| 63 | |
| 64 | heap.push(HeapItem { |
| 65 | dist: min_dist_point_bbox(query_lng, query_lat, &nodes[root].bbox), |
| 66 | node_idx: root, |
| 67 | }); |
| 68 | |
| 69 | while let Some(item) = heap.pop() { |
| 70 | if results.len() >= k && item.dist > results[k - 1].distance { |
| 71 | continue; |
| 72 | } |
| 73 | let node = &nodes[item.node_idx]; |
| 74 | match &node.kind { |
| 75 | NodeKind::Internal { children } => { |
| 76 | for child in children { |
| 77 | let d = min_dist_point_bbox(query_lng, query_lat, &child.bbox); |
| 78 | if results.len() < k || d <= results[results.len() - 1].distance { |
| 79 | heap.push(HeapItem { |
| 80 | dist: d, |
| 81 | node_idx: child.node_idx, |
| 82 | }); |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | NodeKind::Leaf { entries } => { |
| 87 | for entry in entries { |
| 88 | let d = min_dist_point_bbox(query_lng, query_lat, &entry.bbox); |
| 89 | if results.len() < k || d < results[results.len() - 1].distance { |
| 90 | let nn = NnResult { |
| 91 | entry_id: entry.id, |
| 92 | bbox: entry.bbox, |
| 93 | distance: d, |
| 94 | }; |
| 95 | insert_sorted(&mut results, nn, k); |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | results |
| 103 | } |
| 104 | |
| 105 | /// Min-heap item for NN traversal. |
| 106 | #[derive(Debug)] |
no test coverage detected