rigidity_core/
neighbors.rs1use nalgebra::Vector3;
4
5use crate::cloud::PointCloud;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct Neighbor {
10 pub index: u32,
12 pub distance_squared: f64,
16}
17
18pub fn compare_neighbors(a: &Neighbor, b: &Neighbor) -> std::cmp::Ordering {
25 a.distance_squared
26 .total_cmp(&b.distance_squared)
27 .then(a.index.cmp(&b.index))
28}
29
30pub trait NeighborSearch {
34 fn knn_into(&self, query: &Vector3<f64>, k: usize, out: &mut Vec<Neighbor>);
40
41 fn radius_into(&self, query: &Vector3<f64>, radius: f64, out: &mut Vec<Neighbor>);
43
44 fn knn(&self, query: &Vector3<f64>, k: usize) -> Vec<Neighbor> {
46 let mut out = Vec::with_capacity(k);
47 self.knn_into(query, k, &mut out);
48 out
49 }
50
51 fn radius(&self, query: &Vector3<f64>, radius: f64) -> Vec<Neighbor> {
53 let mut out = Vec::new();
54 self.radius_into(query, radius, &mut out);
55 out
56 }
57}
58
59pub struct BruteForce<'a> {
64 cloud: &'a PointCloud,
65}
66
67impl<'a> BruteForce<'a> {
68 pub fn new(cloud: &'a PointCloud) -> Self {
70 Self { cloud }
71 }
72
73 fn all_distances(&self, query: &Vector3<f64>, out: &mut Vec<Neighbor>) {
74 out.clear();
75 out.reserve(self.cloud.len());
76 for i in 0..self.cloud.len() {
77 out.push(Neighbor {
78 index: i as u32,
79 distance_squared: (self.cloud.point(i) - query).norm_squared(),
80 });
81 }
82 }
83}
84
85impl NeighborSearch for BruteForce<'_> {
86 fn knn_into(&self, query: &Vector3<f64>, k: usize, out: &mut Vec<Neighbor>) {
87 self.all_distances(query, out);
88 out.sort_unstable_by(compare_neighbors);
89 out.truncate(k);
90 }
91
92 fn radius_into(&self, query: &Vector3<f64>, radius: f64, out: &mut Vec<Neighbor>) {
93 let limit = radius * radius;
94 self.all_distances(query, out);
95 out.retain(|n| n.distance_squared <= limit);
96 out.sort_unstable_by(compare_neighbors);
97 }
98}