1use crate::error::SpatialResult;
2use crate::rtree::node::{Entry, Node, RTree, Rectangle};
3use scirs2_core::ndarray::Array1;
4use std::collections::HashSet;
5
6impl<T: Clone> RTree<T> {
7 pub fn insert(&mut self, point: Array1<f64>, data: T) -> SpatialResult<()> {
18 if point.len() != self.ndim() {
19 return Err(crate::error::SpatialError::DimensionError(format!(
20 "Point dimension {} does not match RTree dimension {}",
21 point.len(),
22 self.ndim()
23 )));
24 }
25
26 let mbr = Rectangle::from_point(&point.view());
28 let entry = Entry::Leaf {
29 mbr,
30 data,
31 index: self.size(),
32 };
33
34 self.insert_entry(&entry, 0)?;
36
37 self.increment_size();
39
40 Ok(())
41 }
42
43 pub fn insert_rectangle(
55 &mut self,
56 min: Array1<f64>,
57 max: Array1<f64>,
58 data: T,
59 ) -> SpatialResult<()> {
60 if min.len() != self.ndim() {
61 return Err(crate::error::SpatialError::DimensionError(format!(
62 "Min coordinate dimension {} does not match RTree dimension {}",
63 min.len(),
64 self.ndim()
65 )));
66 }
67
68 if max.len() != self.ndim() {
69 return Err(crate::error::SpatialError::DimensionError(format!(
70 "Max coordinate dimension {} does not match RTree dimension {}",
71 max.len(),
72 self.ndim()
73 )));
74 }
75
76 let mbr = Rectangle::new(min, max)?;
78 let entry = Entry::Leaf {
79 mbr,
80 data,
81 index: self.size(),
82 };
83
84 self.insert_entry(&entry, 0)?;
86
87 self.increment_size();
89
90 Ok(())
91 }
92
93 pub(crate) fn insert_entry(
95 &mut self,
96 entry: &Entry<T>,
97 level: usize,
98 ) -> SpatialResult<Option<Node<T>>> {
99 if self.root._isleaf && level == 0 {
102 self.root.entries.push(entry.clone());
103
104 if self.root.size() > self.maxentries {
106 let mut root = std::mem::replace(&mut self.root, Node::new(true, 0));
108 let (node1, node2) = self.split_node(&mut root)?;
109
110 let mut new_root = Node::new(false, 1);
112
113 if let Ok(Some(mbr1)) = node1.mbr() {
115 new_root.entries.push(Entry::NonLeaf {
116 mbr: mbr1,
117 child: Box::new(node1),
118 });
119 }
120
121 if let Ok(Some(mbr2)) = node2.mbr() {
122 new_root.entries.push(Entry::NonLeaf {
123 mbr: mbr2,
124 child: Box::new(node2),
125 });
126 }
127
128 self.root = new_root;
129 self.increment_height();
130 }
131
132 return Ok(None);
133 }
134
135 if !self.root._isleaf {
137 let subtree_index = self.choose_subtree(&self.root, entry.mbr(), level)?;
139
140 let child: &mut Box<Node<T>> = match &mut self.root.entries[subtree_index] {
142 Entry::NonLeaf { child, .. } => child,
143 Entry::Leaf { .. } => {
144 return Err(crate::error::SpatialError::ComputationError(
145 "Expected a non-leaf entry".into(),
146 ))
147 }
148 };
149
150 let child_ptr = Box::as_mut(child) as *mut Node<T>;
152
153 let maybe_split =
155 unsafe { self.insert_entry_recursive(entry, level, &mut *child_ptr) }?;
156
157 if let Some(split_node) = maybe_split {
159 if let Ok(Some(mbr)) = split_node.mbr() {
161 self.root.entries.push(Entry::NonLeaf {
162 mbr,
163 child: Box::new(split_node),
164 });
165
166 if self.root.size() > self.maxentries {
168 let mut root = std::mem::replace(&mut self.root, Node::new(false, 1));
170 let root_level = root.level;
171 let (node1, node2) = self.split_node(&mut root)?;
172
173 let mut new_root = Node::new(false, root_level + 1);
175
176 if let Ok(Some(mbr1)) = node1.mbr() {
178 new_root.entries.push(Entry::NonLeaf {
179 mbr: mbr1,
180 child: Box::new(node1),
181 });
182 }
183
184 if let Ok(Some(mbr2)) = node2.mbr() {
185 new_root.entries.push(Entry::NonLeaf {
186 mbr: mbr2,
187 child: Box::new(node2),
188 });
189 }
190
191 self.root = new_root;
192 self.increment_height();
193 }
194 }
195 }
196
197 if let Entry::NonLeaf { mbr, child } = &mut self.root.entries[subtree_index] {
199 if let Ok(Some(child_mbr)) = child.mbr() {
200 *mbr = child_mbr;
201 }
202 }
203 }
204
205 Ok(None)
206 }
207
208 pub(crate) fn insert_entry_recursive(
210 &mut self,
211 entry: &Entry<T>,
212 level: usize,
213 node: &mut Node<T>,
214 ) -> SpatialResult<Option<Node<T>>> {
215 if level == node.level {
217 node.entries.push(entry.clone());
218
219 if node.size() > self.maxentries {
221 let (new_node, split_node) = self.split_node(node)?;
222 *node = new_node;
223 return Ok(Some(split_node));
224 }
225
226 return Ok(None);
227 }
228
229 let subtree_index = self.choose_subtree(node, entry.mbr(), level)?;
231
232 let child: &mut Box<Node<T>> = match &mut node.entries[subtree_index] {
234 Entry::NonLeaf { child, .. } => child,
235 Entry::Leaf { .. } => {
236 return Err(crate::error::SpatialError::ComputationError(
237 "Expected a non-leaf entry".into(),
238 ))
239 }
240 };
241
242 let child_ptr = Box::as_mut(child) as *mut Node<T>;
244
245 let maybe_split = unsafe { self.insert_entry_recursive(entry, level, &mut *child_ptr) }?;
247
248 if let Some(split_node) = maybe_split {
250 if let Ok(Some(mbr)) = split_node.mbr() {
252 node.entries.push(Entry::NonLeaf {
253 mbr,
254 child: Box::new(split_node),
255 });
256
257 if node.size() > self.maxentries {
259 let (new_node, split_node) = self.split_node(node)?;
260 *node = new_node;
261 return Ok(Some(split_node));
262 }
263 }
264 }
265
266 if let Entry::NonLeaf { mbr, child } = &mut node.entries[subtree_index] {
268 if let Ok(Some(child_mbr)) = child.mbr() {
269 *mbr = child_mbr;
270 }
271 }
272
273 Ok(None)
274 }
275
276 pub(crate) fn choose_subtree(
278 &self,
279 node: &Node<T>,
280 mbr: &Rectangle,
281 level: usize,
282 ) -> SpatialResult<usize> {
283 let mut min_enlargement = f64::MAX;
284 let mut min_area = f64::MAX;
285 let mut chosen_index = 0;
286
287 if node._isleaf {
289 return Err(crate::error::SpatialError::ComputationError(
290 "Cannot choose subtree in a leaf node".into(),
291 ));
292 }
293
294 for (i, entry) in node.entries.iter().enumerate() {
295 let entry_mbr = entry.mbr();
296
297 let enlargement = entry_mbr.enlargement_area(mbr)?;
299
300 if enlargement < min_enlargement
302 || (enlargement == min_enlargement && entry_mbr.area() < min_area)
303 {
304 min_enlargement = enlargement;
305 min_area = entry_mbr.area();
306 chosen_index = i;
307 }
308 }
309
310 Ok(chosen_index)
311 }
312
313 pub(crate) fn split_node(&self, node: &mut Node<T>) -> SpatialResult<(Node<T>, Node<T>)> {
315 let mut node1 = Node::new(node._isleaf, node.level);
317 let mut node2 = Node::new(node._isleaf, node.level);
318
319 let (seed1, seed2) = self.choose_split_seeds(node)?;
321
322 node1.entries.push(node.entries[seed1].clone());
324 node2.entries.push(node.entries[seed2].clone());
325
326 let mut assigned = HashSet::new();
328 assigned.insert(seed1);
329 assigned.insert(seed2);
330
331 let mut mbr1 = node1.entries[0].mbr().clone();
333 let mut mbr2 = node2.entries[0].mbr().clone();
334
335 while assigned.len() < node.size() {
337 let remaining = node.size() - assigned.len();
339 if node1.size() + remaining == self.min_entries {
340 for i in 0..node.size() {
342 if !assigned.contains(&i) {
343 node1.entries.push(node.entries[i].clone());
344 mbr1 = mbr1.enlarge(node.entries[i].mbr())?;
345 }
346 }
347 break;
348 } else if node2.size() + remaining == self.min_entries {
349 for i in 0..node.size() {
351 if !assigned.contains(&i) {
352 node2.entries.push(node.entries[i].clone());
353 mbr2 = mbr2.enlarge(node.entries[i].mbr())?;
354 }
355 }
356 break;
357 }
358
359 let mut max_diff = -f64::MAX;
361 let mut chosen_index = 0;
362 let mut add_to_group1 = true;
363
364 for i in 0..node.size() {
365 if assigned.contains(&i) {
366 continue;
367 }
368
369 let entry_mbr = node.entries[i].mbr();
371 let enlargement1 = mbr1.enlargement_area(entry_mbr)?;
372 let enlargement2 = mbr2.enlargement_area(entry_mbr)?;
373
374 let diff = (enlargement1 - enlargement2).abs();
376 if diff > max_diff {
377 max_diff = diff;
378 chosen_index = i;
379 add_to_group1 = enlargement1 < enlargement2;
380 }
381 }
382
383 if add_to_group1 {
385 node1.entries.push(node.entries[chosen_index].clone());
386 mbr1 = mbr1.enlarge(node.entries[chosen_index].mbr())?;
387 } else {
388 node2.entries.push(node.entries[chosen_index].clone());
389 mbr2 = mbr2.enlarge(node.entries[chosen_index].mbr())?;
390 }
391
392 assigned.insert(chosen_index);
393 }
394
395 *node = node1;
397
398 Ok((node.clone(), node2))
399 }
400
401 pub(crate) fn choose_split_seeds(&self, node: &Node<T>) -> SpatialResult<(usize, usize)> {
403 let mut max_waste = -f64::MAX;
404 let mut seed1 = 0;
405 let mut seed2 = 0;
406
407 for i in 0..node.size() - 1 {
409 for j in i + 1..node.size() {
410 let mbr_i = node.entries[i].mbr();
411 let mbr_j = node.entries[j].mbr();
412
413 let combined_mbr = mbr_i.enlarge(mbr_j)?;
415 let combined_area = combined_mbr.area();
416
417 let waste = combined_area - mbr_i.area() - mbr_j.area();
419
420 if waste > max_waste {
421 max_waste = waste;
422 seed1 = i;
423 seed2 = j;
424 }
425 }
426 }
427
428 Ok((seed1, seed2))
429 }
430}
431
432#[cfg(test)]
433mod tests {
434 use super::*;
435 use scirs2_core::ndarray::array;
436
437 #[test]
438 fn test_rtree_insert_and_search() {
439 let mut rtree: RTree<i32> = RTree::new(2, 2, 4).unwrap();
441
442 let points = vec![
444 (array![0.0, 0.0], 0),
445 (array![1.0, 0.0], 1),
446 (array![0.0, 1.0], 2),
447 (array![1.0, 1.0], 3),
448 (array![0.5, 0.5], 4),
449 (array![2.0, 2.0], 5),
450 (array![3.0, 3.0], 6),
451 (array![4.0, 4.0], 7),
452 (array![5.0, 5.0], 8),
453 (array![6.0, 6.0], 9),
454 ];
455
456 for (point, value) in points {
457 rtree.insert(point, value).unwrap();
458 }
459
460 assert_eq!(rtree.size(), 10);
462 assert!(!rtree.is_empty());
463 }
464
465 #[test]
466 fn test_rtree_insert_rectangle() {
467 let mut rtree: RTree<&str> = RTree::new(2, 2, 4).unwrap();
469
470 let rectangles = vec![
472 (array![0.0, 0.0], array![1.0, 1.0], "A"),
473 (array![2.0, 2.0], array![3.0, 3.0], "B"),
474 (array![1.5, 0.0], array![2.5, 1.0], "C"),
475 (array![0.0, 1.5], array![1.0, 2.5], "D"),
476 ];
477
478 for (min, max, value) in rectangles {
479 rtree.insert_rectangle(min, max, value).unwrap();
480 }
481
482 assert_eq!(rtree.size(), 4);
484
485 let results = rtree
487 .search_range(&array![0.5, 0.5].view(), &array![2.0, 2.0].view())
488 .unwrap();
489
490 assert_eq!(results.len(), 4);
492
493 let result_values: Vec<&str> = results.iter().map(|(_, v)| *v).collect();
495 assert!(result_values.contains(&"A"));
496 assert!(result_values.contains(&"B")); assert!(result_values.contains(&"C"));
498 assert!(result_values.contains(&"D"));
499 }
500}