| 179 | |
| 180 | #[inline(never)] |
| 181 | fn vp_search_node(mut node: &Node, needle: &f_pixel, best_candidate: &mut Visitor) { |
| 182 | loop { |
| 183 | let distance_squared = node.vantage_point.diff(needle); |
| 184 | let distance = distance_squared.sqrt(); |
| 185 | |
| 186 | best_candidate.visit(distance, distance_squared, node.idx); |
| 187 | |
| 188 | match node.inner { |
| 189 | NodeInner::Nodes { radius, radius_squared, ref near, ref far } => { |
| 190 | // Recurse towards most likely candidate first to narrow best candidate's distance as soon as possible |
| 191 | if distance_squared < radius_squared { |
| 192 | vp_search_node(near, needle, best_candidate); |
| 193 | // The best node (final answer) may be just ouside the radius, but not farther than |
| 194 | // the best distance we know so far. The vp_search_node above should have narrowed |
| 195 | // best_candidate->distance, so this path is rarely taken. |
| 196 | if distance >= radius - best_candidate.distance { |
| 197 | node = far; |
| 198 | continue; |
| 199 | } |
| 200 | } else { |
| 201 | vp_search_node(far, needle, best_candidate); |
| 202 | if distance <= radius + best_candidate.distance { |
| 203 | node = near; |
| 204 | continue; |
| 205 | } |
| 206 | } |
| 207 | break; |
| 208 | }, |
| 209 | NodeInner::Leaf { len: num, ref idxs, ref colors } => { |
| 210 | colors.iter().zip(idxs.iter().copied()).take(num as usize).for_each(|(color, idx)| { |
| 211 | let distance_squared = color.diff(needle); |
| 212 | best_candidate.visit(distance_squared.sqrt(), distance_squared, idx); |
| 213 | }); |
| 214 | break; |
| 215 | }, |
| 216 | } |
| 217 | } |
| 218 | } |