vox_geometry_rust/
kdtree2.rs1use crate::vector2::Vector2D;
10use crate::bounding_box2::BoundingBox2D;
11use std::cmp::Ordering;
12
13#[derive(Clone)]
15pub struct Node {
16 flags: usize,
18
19 child: usize,
22
23 item: usize,
25
26 point: Vector2D,
28}
29
30impl Node {
31 pub fn new() -> Node {
33 return Node {
34 flags: 0,
35 child: usize::MAX,
36 item: usize::MAX,
37 point: Vector2D::new_default(),
38 };
39 }
40
41 pub fn init_leaf(&mut self, it: usize, pt: &Vector2D) {
43 self.flags = 2;
44 self.item = it;
45 self.child = usize::MAX;
46 self.point = pt.clone();
47 }
48
49 pub fn init_internal(&mut self, axis: usize, it: usize, c: usize, pt: &Vector2D) {
51 self.flags = axis;
52 self.item = it;
53 self.child = c;
54 self.point = pt.clone();
55 }
56
57 pub fn is_leaf(&self) -> bool {
59 return self.flags == 2;
60 }
61}
62
63#[derive(Clone)]
65pub struct KdTree2 {
66 _points: Vec<Vector2D>,
67 _nodes: Vec<Node>,
68}
69
70impl KdTree2 {
71 pub fn new() -> KdTree2 {
73 return KdTree2 {
74 _points: vec![],
75 _nodes: vec![],
76 };
77 }
78
79 pub fn build(&mut self, points: &Vec<Vector2D>) {
81 self._points = points.clone();
82
83 if self._points.is_empty() {
84 return;
85 }
86
87 self._nodes.clear();
88 let mut item_indices: Vec<usize> = (0..self._points.len()).collect();
89
90 self.build_internal(0, &mut item_indices, self._points.len(), 0);
91 }
92
93 pub fn for_each_nearby_point<Callback>(&self, origin: &Vector2D, radius: f64,
102 callback: &mut Callback) where Callback: FnMut(usize, &Vector2D) {
103 let r2 = radius * radius;
104
105 const K_MAX_TREE_DEPTH: usize = 8 * 32;
107 let mut todo: [Option<usize>; K_MAX_TREE_DEPTH] = [None; K_MAX_TREE_DEPTH];
108 let mut todo_pos = 0;
109
110 let mut node: usize = 0;
112 while node < self._nodes.len() {
113 if self._nodes[node].item != usize::MAX &&
114 (self._nodes[node].point - *origin).length_squared() <= r2 {
115 callback(self._nodes[node].item, &self._nodes[node].point);
116 }
117
118 if self._nodes[node].is_leaf() {
119 if todo_pos > 0 {
121 todo_pos -= 1;
123 node = todo[todo_pos].unwrap();
124 } else {
125 break;
126 }
127 } else {
128 let first_child = node + 1;
130 let second_child = self._nodes[node].child;
131
132 let axis = self._nodes[node].flags;
134 let plane = self._nodes[node].point[axis];
135 if plane - origin[axis] > radius {
136 node = first_child;
137 } else if origin[axis] - plane > radius {
138 node = second_child;
139 } else {
140 todo[todo_pos] = Some(second_child);
142 todo_pos += 1;
143 node = first_child;
144 }
145 }
146 }
147 }
148
149 pub fn has_nearby_point(&self, origin: &Vector2D, radius: f64) -> bool {
159 let r2 = radius * radius;
160
161 const K_MAX_TREE_DEPTH: usize = 8 * 32;
163 let mut todo: [Option<usize>; K_MAX_TREE_DEPTH] = [None; K_MAX_TREE_DEPTH];
164 let mut todo_pos = 0;
165
166 let mut node: usize = 0;
168 while node < self._nodes.len() {
169 if self._nodes[node].item != usize::MAX &&
170 (self._nodes[node].point - *origin).length_squared() <= r2 {
171 return true;
172 }
173
174 if self._nodes[node].is_leaf() {
175 if todo_pos > 0 {
177 todo_pos -= 1;
179 node = todo[todo_pos].unwrap();
180 } else {
181 break;
182 }
183 } else {
184 let first_child = node + 1;
186 let second_child = self._nodes[node].child;
187
188 let axis = self._nodes[node].flags;
190 let plane = self._nodes[node].point[axis];
191 if origin[axis] < plane && plane - origin[axis] > radius {
192 node = first_child;
193 } else if origin[axis] > plane && origin[axis] - plane > radius {
194 node = second_child;
195 } else {
196 todo[todo_pos] = Some(second_child);
198 todo_pos += 1;
199 node = first_child;
200 }
201 }
202 }
203
204 return false;
205 }
206
207 pub fn nearest_point(&self, origin: &Vector2D) -> usize {
209 const K_MAX_TREE_DEPTH: usize = 8 * 32;
211 let mut todo: [Option<usize>; K_MAX_TREE_DEPTH] = [None; K_MAX_TREE_DEPTH];
212 let mut todo_pos = 0;
213
214 let mut node: usize = 0;
216 let mut nearest = 0;
217 let mut min_dist2 = (self._nodes[node].point - *origin).length_squared();
218
219 while node < self._nodes.len() {
220 let new_dist2 = (self._nodes[node].point - *origin).length_squared();
221 if new_dist2 <= min_dist2 {
222 nearest = self._nodes[node].item;
223 min_dist2 = new_dist2;
224 }
225
226 if self._nodes[node].is_leaf() {
227 if todo_pos > 0 {
229 todo_pos -= 1;
231 node = todo[todo_pos].unwrap();
232 } else {
233 break;
234 }
235 } else {
236 let first_child = node + 1;
238 let second_child = self._nodes[node].child;
239
240 let axis = self._nodes[node].flags;
242 let plane = self._nodes[node].point[axis];
243 let min_dist = f64::sqrt(min_dist2);
244 if plane - origin[axis] > min_dist {
245 node = first_child;
246 } else if origin[axis] - plane > min_dist {
247 node = second_child;
248 } else {
249 todo[todo_pos] = Some(second_child);
251 todo_pos += 1;
252 node = first_child;
253 }
254 }
255 }
256
257 return nearest;
258 }
259
260 pub fn reserve(&mut self, num_points: usize, num_nodes: usize) {
262 self._points.resize(num_points, Vector2D::new_default());
263 self._nodes.resize(num_nodes, Node::new());
264 }
265
266 pub fn build_internal(&mut self, node_index: usize, item_indices: &mut [usize], n_items: usize,
267 current_depth: usize) -> usize {
268 self._nodes.push(Node::new());
270
271 if n_items == 0 {
273 self._nodes[node_index].init_leaf(usize::MAX, &Vector2D::new_default());
274 return current_depth + 1;
275 }
276 if n_items == 1 {
277 self._nodes[node_index].init_leaf(item_indices[0], &self._points[item_indices[0]]);
278 return current_depth + 1;
279 }
280
281 let mut node_bound = BoundingBox2D::new_default();
283 for i in 0..n_items {
284 node_bound.merge_vec(&self._points[item_indices[i]]);
285 }
286 let d = node_bound.upper_corner - node_bound.lower_corner;
287 let axis = d.dominant_axis();
288
289 let (left, mid, right) = item_indices.select_nth_unstable_by(n_items, |a: &usize, b: &usize| {
291 return match self._points[*a][axis] < self._points[*b][axis] {
292 true => Ordering::Less,
293 false => Ordering::Greater
294 };
295 });
296
297 let mid_point = n_items / 2;
298 let node_len = self._nodes.len();
299 let d0 = self.build_internal(node_index + 1, left, mid_point, current_depth + 1);
301 self._nodes[node_index].init_internal(axis, *mid, node_len,
302 &self._points[*mid]);
303 let d1 = self.build_internal(self._nodes[node_index].child, right,
304 n_items - mid_point - 1, current_depth + 1);
305
306 return usize::max(d0, d1);
307 }
308}