1use alloc::boxed::Box;
11use alloc::vec::Vec;
12use core::marker::PhantomData;
13
14use crate::bounds::{Bounds, union_all};
15use crate::indexable::Indexable;
16use crate::node::Node;
17use crate::predicate::Predicate;
18use crate::split::{Quadratic, SplitParameters};
19
20#[derive(Debug)]
41pub struct Rtree<T: Indexable, Params: SplitParameters = Quadratic> {
42 root: Node<T>,
43 len: usize,
44 _params: PhantomData<Params>,
45}
46
47impl<T: Indexable, Params: SplitParameters> Default for Rtree<T, Params> {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl<T: Indexable, Params: SplitParameters> Rtree<T, Params> {
54 #[must_use]
56 pub fn new() -> Self {
57 Self {
58 root: Node::Leaf(Vec::new()),
59 len: 0,
60 _params: PhantomData,
61 }
62 }
63
64 #[must_use]
66 pub fn len(&self) -> usize {
67 self.len
68 }
69
70 #[must_use]
72 pub fn is_empty(&self) -> bool {
73 self.len == 0
74 }
75
76 #[must_use]
78 pub fn height(&self) -> usize {
79 self.root.height()
80 }
81
82 pub fn insert(&mut self, value: T) {
88 self.len += 1;
89 if let Some((b1, n1, b2, n2)) = insert_into::<T, Params>(&mut self.root, value) {
90 self.root = Node::Branch(Vec::from([(b1, n1), (b2, n2)]));
94 }
95 }
96
97 #[must_use]
102 pub fn query(&self, predicate: Predicate) -> Vec<&T> {
103 let mut out = Vec::new();
104 query_node(&self.root, &predicate, &mut out);
105 out
106 }
107
108 #[must_use]
113 pub fn nearest(&self, query: [f64; 2], k: usize) -> Vec<&T> {
114 if k == 0 {
115 return Vec::new();
116 }
117 let mut candidates: Vec<(f64, &T)> = Vec::new();
118 collect_with_distance(&self.root, query, &mut candidates);
119 candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(core::cmp::Ordering::Equal));
120 candidates.into_iter().take(k).map(|(_, v)| v).collect()
121 }
122}
123
124impl<T: Indexable, Params: SplitParameters> FromIterator<T> for Rtree<T, Params> {
125 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
130 let values: Vec<T> = iter.into_iter().collect();
131 let len = values.len();
132 if len <= Params::MAX {
133 return Self {
134 root: Node::Leaf(values),
135 len,
136 _params: PhantomData,
137 };
138 }
139 let root = str_pack::<T, Params>(values);
140 Self {
141 root,
142 len,
143 _params: PhantomData,
144 }
145 }
146}
147
148type Split<T> = (Bounds, Box<Node<T>>, Bounds, Box<Node<T>>);
151
152fn insert_into<T: Indexable, Params: SplitParameters>(
153 node: &mut Node<T>,
154 value: T,
155) -> Option<Split<T>> {
156 match node {
157 Node::Leaf(values) => {
158 values.push(value);
159 if values.len() > Params::MAX {
160 Some(split_leaf::<T, Params>(values))
161 } else {
162 None
163 }
164 }
165 Node::Branch(children) => {
166 let vb = value.bounds();
168 let choice = choose_child(children, &vb);
169 let (_, child) = &mut children[choice];
170 let split = insert_into::<T, Params>(child, value);
171
172 children[choice].0 = children[choice]
174 .1
175 .bounds()
176 .unwrap_or_else(|| children[choice].0);
177
178 if let Some((b1, n1, b2, n2)) = split {
179 children[choice] = (b1, n1);
180 children.push((b2, n2));
181 if children.len() > Params::MAX {
182 return Some(split_branch::<T, Params>(children));
183 }
184 }
185 None
186 }
187 }
188}
189
190#[allow(
193 clippy::float_cmp,
194 reason = "exact tie-break between equal enlargements, as Boost's choose_next_node does"
195)]
196fn choose_child<T>(children: &[(Bounds, Box<Node<T>>)], vb: &Bounds) -> usize {
197 let mut best = 0;
198 let mut best_enl = f64::INFINITY;
199 let mut best_area = f64::INFINITY;
200 for (i, (b, _)) in children.iter().enumerate() {
201 let enl = b.enlargement(vb);
202 let area = b.area();
203 if enl < best_enl || (enl == best_enl && area < best_area) {
204 best = i;
205 best_enl = enl;
206 best_area = area;
207 }
208 }
209 best
210}
211
212fn split_leaf<T: Indexable, Params: SplitParameters>(values: &mut Vec<T>) -> Split<T> {
214 let taken = core::mem::take(values);
215 let boxes: Vec<Bounds> = taken.iter().map(Indexable::bounds).collect();
216 let (g1, g2) = Params::split(&boxes);
217
218 let mut in_g1 = alloc::vec![false; taken.len()];
221 for &i in &g1 {
222 in_g1[i] = true;
223 }
224 let mut v1: Vec<T> = Vec::new();
225 let mut v2: Vec<T> = Vec::new();
226 for (i, v) in taken.into_iter().enumerate() {
227 if in_g1[i] {
228 v1.push(v);
229 } else {
230 v2.push(v);
231 }
232 }
233 debug_assert_eq!(v1.len(), g1.len());
234 debug_assert_eq!(v2.len(), g2.len());
235
236 let b1 = union_all(&v1.iter().map(Indexable::bounds).collect::<Vec<_>>());
237 let b2 = union_all(&v2.iter().map(Indexable::bounds).collect::<Vec<_>>());
238 (b1, Box::new(Node::Leaf(v1)), b2, Box::new(Node::Leaf(v2)))
239}
240
241fn split_branch<T: Indexable, Params: SplitParameters>(
243 children: &mut Vec<(Bounds, Box<Node<T>>)>,
244) -> Split<T> {
245 let taken = core::mem::take(children);
246 let boxes: Vec<Bounds> = taken.iter().map(|(b, _)| *b).collect();
247 let (g1, _g2) = Params::split(&boxes);
248
249 let mut in_g1 = alloc::vec![false; taken.len()];
250 for &i in &g1 {
251 in_g1[i] = true;
252 }
253 let mut c1: Vec<(Bounds, Box<Node<T>>)> = Vec::new();
254 let mut c2: Vec<(Bounds, Box<Node<T>>)> = Vec::new();
255 for (i, c) in taken.into_iter().enumerate() {
256 if in_g1[i] {
257 c1.push(c);
258 } else {
259 c2.push(c);
260 }
261 }
262
263 let b1 = union_all(&c1.iter().map(|(b, _)| *b).collect::<Vec<_>>());
264 let b2 = union_all(&c2.iter().map(|(b, _)| *b).collect::<Vec<_>>());
265 (
266 b1,
267 Box::new(Node::Branch(c1)),
268 b2,
269 Box::new(Node::Branch(c2)),
270 )
271}
272
273fn query_node<'a, T: Indexable>(node: &'a Node<T>, predicate: &Predicate, out: &mut Vec<&'a T>) {
275 match node {
276 Node::Leaf(values) => {
277 for v in values {
278 if predicate.matches(&v.bounds()) {
279 out.push(v);
280 }
281 }
282 }
283 Node::Branch(children) => {
284 for (b, child) in children {
285 if predicate.could_match(b) {
286 query_node(child, predicate, out);
287 }
288 }
289 }
290 }
291}
292
293fn collect_with_distance<'a, T: Indexable>(
298 node: &'a Node<T>,
299 query: [f64; 2],
300 out: &mut Vec<(f64, &'a T)>,
301) {
302 match node {
303 Node::Leaf(values) => {
304 for v in values {
305 let b = v.bounds();
306 out.push((b.min_distance_to(query), v));
307 }
308 }
309 Node::Branch(children) => {
310 for (_, child) in children {
311 collect_with_distance(child, query, out);
312 }
313 }
314 }
315}
316
317fn str_pack<T: Indexable, Params: SplitParameters>(mut values: Vec<T>) -> Node<T> {
319 values.sort_by(|a, b| {
322 a.bounds().center()[0]
323 .partial_cmp(&b.bounds().center()[0])
324 .unwrap_or(core::cmp::Ordering::Equal)
325 });
326
327 let leaf_count = values.len().div_ceil(Params::MAX);
328 let strip_count = isqrt_ceil(leaf_count).max(1);
329 let per_strip = values.len().div_ceil(strip_count);
330
331 let mut leaves: Vec<(Bounds, Box<Node<T>>)> = Vec::new();
332 let mut rest = values;
333 while !rest.is_empty() {
334 let take = per_strip.min(rest.len());
336 let tail = rest.split_off(take);
337 let mut strip = core::mem::replace(&mut rest, tail);
338
339 strip.sort_by(|a, b| {
340 a.bounds().center()[1]
341 .partial_cmp(&b.bounds().center()[1])
342 .unwrap_or(core::cmp::Ordering::Equal)
343 });
344
345 let mut strip_iter = strip.into_iter();
347 loop {
348 let leaf_vals: Vec<T> = (&mut strip_iter).take(Params::MAX).collect();
349 if leaf_vals.is_empty() {
350 break;
351 }
352 let boxes: Vec<Bounds> = leaf_vals.iter().map(Indexable::bounds).collect();
353 let b = union_all(&boxes);
354 leaves.push((b, Box::new(Node::Leaf(leaf_vals))));
355 }
356 }
357
358 build_branches::<T, Params>(leaves)
359}
360
361fn build_branches<T: Indexable, Params: SplitParameters>(
364 children: Vec<(Bounds, Box<Node<T>>)>,
365) -> Node<T> {
366 if children.len() <= Params::MAX {
367 return Node::Branch(children);
368 }
369 let mut level: Vec<(Bounds, Box<Node<T>>)> = Vec::new();
370 let mut it = children.into_iter();
371 loop {
372 let group: Vec<(Bounds, Box<Node<T>>)> = (&mut it).take(Params::MAX).collect();
373 if group.is_empty() {
374 break;
375 }
376 let boxes: Vec<Bounds> = group.iter().map(|(b, _)| *b).collect();
377 let b = union_all(&boxes);
378 level.push((b, Box::new(Node::Branch(group))));
379 }
380 build_branches::<T, Params>(level)
381}
382
383fn isqrt_ceil(n: usize) -> usize {
386 if n < 2 {
387 return n;
388 }
389 let mut x = n;
390 let mut y = x.div_ceil(2);
391 while y < x {
392 x = y;
393 y = usize::midpoint(x, n / x);
394 }
395 if x * x == n { x } else { x + 1 }
397}
398
399#[cfg(test)]
400#[allow(clippy::float_cmp, reason = "exact integer-valued point coordinates")]
401mod tests {
402 use super::Rtree;
403 use crate::bounds::Bounds;
404 use crate::predicate::Predicate;
405 use crate::split::Linear;
406 use geometry_cs::Cartesian;
407 use geometry_model::Point2D;
408 use geometry_trait::Point as _;
409
410 type P = Point2D<f64, Cartesian>;
411
412 #[test]
413 fn empty_tree() {
414 let t: Rtree<P> = Rtree::new();
415 assert!(t.is_empty());
416 assert_eq!(t.len(), 0);
417 }
418
419 #[test]
420 fn insert_many_points_keeps_len() {
421 let mut t: Rtree<P> = Rtree::new();
422 for i in 0..1000 {
423 let x = f64::from(i % 100);
424 let y = f64::from(i / 100);
425 t.insert(P::new(x, y));
426 }
427 assert_eq!(t.len(), 1000);
428 assert!(
429 t.height() >= 2,
430 "1000 points should build a multi-level tree"
431 );
432 }
433
434 #[test]
435 fn query_intersects_finds_the_point() {
436 let mut t: Rtree<P> = Rtree::new();
437 for i in 0..200 {
438 t.insert(P::new(f64::from(i), 0.0));
439 }
440 let hits = t.query(Predicate::Intersects(Bounds::new([9.5, -1.0], [10.5, 1.0])));
441 assert_eq!(hits.len(), 1);
442 }
443
444 #[test]
445 fn query_within_a_window() {
446 let mut t: Rtree<P> = Rtree::new();
447 for x in 0..10 {
448 for y in 0..10 {
449 t.insert(P::new(f64::from(x), f64::from(y)));
450 }
451 }
452 let hits = t.query(Predicate::Within(Bounds::new([2.0, 2.0], [5.0, 5.0])));
454 assert_eq!(hits.len(), 16);
455 }
456
457 #[test]
458 fn nearest_returns_closest_first() {
459 let mut t: Rtree<P> = Rtree::new();
460 for i in 0..100 {
461 t.insert(P::new(f64::from(i), 0.0));
462 }
463 let near = t.nearest([10.2, 0.0], 3);
464 assert_eq!(near.len(), 3);
465 let mut xs: Vec<f64> = near.iter().map(|p| p.get::<0>()).collect();
467 xs.sort_by(|a, b| a.partial_cmp(b).unwrap());
468 assert_eq!(xs, [9.0, 10.0, 11.0]);
469 }
470
471 #[test]
472 fn linear_split_also_works() {
473 let mut t: Rtree<P, Linear<8, 3>> = Rtree::new();
474 for i in 0..500 {
475 t.insert(P::new(f64::from(i % 25), f64::from(i / 25)));
476 }
477 assert_eq!(t.len(), 500);
478 let hits = t.query(Predicate::Intersects(Bounds::new([0.0, 0.0], [3.0, 3.0])));
479 assert!(!hits.is_empty());
480 }
481
482 #[test]
483 fn bulk_load_balances() {
484 let points: Vec<P> = (0..10_000)
485 .map(|i| P::new(f64::from(i % 100), f64::from(i / 100)))
486 .collect();
487 let t: Rtree<P> = points.into_iter().collect();
488 assert_eq!(t.len(), 10_000);
489 assert!(t.height() <= 6, "STR tree too tall: {}", t.height());
491 }
492}