1use crate::error::SpatialResult;
2use crate::rtree::node::{Entry, Node, RTree, Rectangle};
3use scirs2_core::ndarray::ArrayView1;
4
5impl<T: Clone> RTree<T> {
6 pub fn delete<F>(
18 &mut self,
19 point: &ArrayView1<f64>,
20 data_predicate: Option<F>,
21 ) -> SpatialResult<bool>
22 where
23 F: Fn(&T) -> bool + Copy,
24 {
25 if point.len() != self.ndim() {
26 return Err(crate::error::SpatialError::DimensionError(format!(
27 "Point dimension {} does not match RTree dimension {}",
28 point.len(),
29 self.ndim()
30 )));
31 }
32
33 let mbr = Rectangle::from_point(point);
35
36 let mut root = std::mem::take(&mut self.root);
39 let result = self.delete_internal(&mbr, &mut root, data_predicate)?;
40 self.root = root;
41
42 if result {
44 self.decrement_size();
45
46 if !self.root._isleaf && self.root.size() == 1 {
48 if let Entry::NonLeaf { child, .. } = &self.root.entries[0] {
49 let new_root = (**child).clone();
50 self.root = new_root;
51 }
53 }
54 }
55
56 Ok(result)
57 }
58
59 #[allow(clippy::type_complexity)]
61 fn delete_internal<F>(
62 &mut self,
63 mbr: &Rectangle,
64 node: &mut Node<T>,
65 data_predicate: Option<F>,
66 ) -> SpatialResult<bool>
67 where
68 F: Fn(&T) -> bool + Copy,
69 {
70 if node._isleaf {
72 let mut found_index = None;
73
74 for (i, entry) in node.entries.iter().enumerate() {
75 if let Entry::Leaf {
76 mbr: entry_mbr,
77 data,
78 ..
79 } = entry
80 {
81 if entry_mbr.min == mbr.min && entry_mbr.max == mbr.max {
83 if let Some(ref pred) = data_predicate {
85 if pred(data) {
86 found_index = Some(i);
87 break;
88 }
89 } else {
90 found_index = Some(i);
92 break;
93 }
94 }
95 }
96 }
97
98 if let Some(index) = found_index {
100 node.entries.remove(index);
101 return Ok(true);
102 }
103
104 return Ok(false);
105 }
106
107 let mut deleted = false;
109
110 for i in 0..node.size() {
111 let entry_mbr = node.entries[i].mbr();
112
113 if entry_mbr.intersects(mbr)? {
115 if let Entry::NonLeaf { child, .. } = &mut node.entries[i] {
117 let child_ptr = Box::as_mut(child) as *mut Node<T>;
119 let result =
120 unsafe { self.delete_internal(mbr, &mut *child_ptr, data_predicate)? };
121
122 if result {
123 deleted = true;
124
125 if child.size() < self.min_entries && child.size() > 0 {
127 self.handle_underfull_node(node, i)?;
129 } else if child.size() == 0 {
130 node.entries.remove(i);
132 } else {
133 if let Ok(Some(child_mbr)) = child.mbr() {
135 if let Entry::NonLeaf { mbr, .. } = &mut node.entries[i] {
136 *mbr = child_mbr;
137 }
138 }
139 }
140
141 break;
142 }
143 }
144 }
145 }
146
147 Ok(deleted)
148 }
149
150 fn handle_underfull_node(
152 &mut self,
153 parent: &mut Node<T>,
154 child_index: usize,
155 ) -> SpatialResult<()> {
156 let child: &Box<Node<T>> = match &parent.entries[child_index] {
158 Entry::NonLeaf { child, .. } => child,
159 Entry::Leaf { .. } => {
160 return Err(crate::error::SpatialError::ComputationError(
161 "Expected a non-leaf entry".into(),
162 ))
163 }
164 };
165
166 let mut best_sibling_index = None;
168 let mut min_merged_area = f64::MAX;
169
170 for i in 0..parent.size() {
171 if i == child_index {
172 continue;
173 }
174
175 let sibling_mbr = parent.entries[i].mbr();
177
178 let child_mbr = child
180 .mbr()
181 .unwrap_or_else(|_| Some(Rectangle::from_point(&Array1::zeros(self.ndim()).view())))
182 .unwrap_or_else(|| Rectangle::from_point(&Array1::zeros(self.ndim()).view()));
183
184 let merged_mbr = child_mbr.enlarge(sibling_mbr)?;
186 let merged_area = merged_mbr.area();
187
188 if merged_area < min_merged_area {
189 min_merged_area = merged_area;
190 best_sibling_index = Some(i);
191 }
192 }
193
194 let best_sibling_index = best_sibling_index.unwrap_or(0);
196 if best_sibling_index == child_index {
197 return Ok(());
198 }
199
200 let sibling: &Box<Node<T>> = match &parent.entries[best_sibling_index] {
202 Entry::NonLeaf { child, .. } => child,
203 Entry::Leaf { .. } => {
204 return Err(crate::error::SpatialError::ComputationError(
205 "Expected a non-leaf entry".into(),
206 ))
207 }
208 };
209
210 if sibling.size() > self.min_entries {
212 let (child_idx, sibling_idx) = if child_index < best_sibling_index {
216 (child_index, best_sibling_index)
217 } else {
218 (best_sibling_index, child_index)
219 };
220
221 let mut child_entry = parent.entries.remove(child_idx);
223 let mut sibling_entry = parent.entries.remove(if sibling_idx > child_idx {
224 sibling_idx - 1
225 } else {
226 sibling_idx
227 });
228
229 let child_node: &mut Box<Node<T>> = match &mut child_entry {
231 Entry::NonLeaf { child, .. } => child,
232 Entry::Leaf { .. } => {
233 return Err(crate::error::SpatialError::ComputationError(
234 "Expected a non-leaf entry for child node".into(),
235 ))
236 }
237 };
238 let sibling_node: &mut Box<Node<T>> = match &mut sibling_entry {
239 Entry::NonLeaf { child, .. } => child,
240 Entry::Leaf { .. } => {
241 return Err(crate::error::SpatialError::ComputationError(
242 "Expected a non-leaf entry for sibling node".into(),
243 ))
244 }
245 };
246
247 let total_entries = child_node.size() + sibling_node.size();
249 let target_child_size = total_entries / 2;
250
251 while child_node.size() < target_child_size && !sibling_node.entries.is_empty() {
253 let entry = sibling_node.entries.remove(0);
254 child_node.entries.push(entry);
255 }
256
257 if let Ok(Some(child_mbr)) = child_node.mbr() {
259 if let Entry::NonLeaf { mbr, .. } = &mut child_entry {
260 *mbr = child_mbr;
261 }
262 }
263 if let Ok(Some(sibling_mbr)) = sibling_node.mbr() {
264 if let Entry::NonLeaf { mbr, .. } = &mut sibling_entry {
265 *mbr = sibling_mbr;
266 }
267 }
268
269 parent.entries.insert(child_idx, child_entry);
271 parent.entries.insert(
272 if sibling_idx > child_idx {
273 sibling_idx
274 } else {
275 sibling_idx + 1
276 },
277 sibling_entry,
278 );
279
280 Ok(())
281 } else {
282 let (smaller_idx, larger_idx) = if child_index < best_sibling_index {
286 (child_index, best_sibling_index)
287 } else {
288 (best_sibling_index, child_index)
289 };
290
291 let mut child_entry = parent.entries.remove(smaller_idx);
292 let sibling_entry = parent.entries.remove(larger_idx - 1);
293
294 let child_node: &mut Box<Node<T>> = match &mut child_entry {
296 Entry::NonLeaf { child, .. } => child,
297 Entry::Leaf { .. } => {
298 return Err(crate::error::SpatialError::ComputationError(
299 "Expected a non-leaf entry for child node".into(),
300 ))
301 }
302 };
303 let sibling_node: Box<Node<T>> = match sibling_entry {
304 Entry::NonLeaf { child, .. } => child,
305 Entry::Leaf { .. } => {
306 return Err(crate::error::SpatialError::ComputationError(
307 "Expected a non-leaf entry for sibling node".into(),
308 ))
309 }
310 };
311
312 for entry in sibling_node.entries {
314 child_node.entries.push(entry);
315 }
316
317 if let Ok(Some(merged_mbr)) = child_node.mbr() {
319 if let Entry::NonLeaf { mbr, .. } = &mut child_entry {
320 *mbr = merged_mbr;
321 }
322 }
323
324 parent.entries.insert(smaller_idx, child_entry);
326
327 Ok(())
331 }
332 }
333}
334
335use scirs2_core::ndarray::Array1;
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340 use scirs2_core::ndarray::array;
341
342 #[test]
343 fn test_rtree_delete() {
344 let mut rtree: RTree<i32> = RTree::new(2, 2, 4).unwrap();
346
347 let points = vec![
349 (array![0.0, 0.0], 0),
350 (array![1.0, 0.0], 1),
351 (array![0.0, 1.0], 2),
352 (array![1.0, 1.0], 3),
353 (array![0.5, 0.5], 4),
354 ];
355
356 for (point, value) in points {
357 rtree.insert(point, value).unwrap();
358 }
359
360 let result = rtree
362 .delete::<fn(&i32) -> bool>(&array![0.5, 0.5].view(), None)
363 .unwrap();
364 assert!(result);
365
366 assert_eq!(rtree.size(), 4);
368
369 let result = rtree
371 .delete::<fn(&i32) -> bool>(&array![2.0, 2.0].view(), None)
372 .unwrap();
373 assert!(!result);
374
375 assert_eq!(rtree.size(), 4);
377
378 let result = rtree
380 .delete::<fn(&i32) -> bool>(&array![0.0, 0.0].view(), None)
381 .unwrap();
382 assert!(result);
383 let result = rtree
384 .delete::<fn(&i32) -> bool>(&array![1.0, 0.0].view(), None)
385 .unwrap();
386 assert!(result);
387 let result = rtree
388 .delete::<fn(&i32) -> bool>(&array![0.0, 1.0].view(), None)
389 .unwrap();
390 assert!(result);
391 let result = rtree
392 .delete::<fn(&i32) -> bool>(&array![1.0, 1.0].view(), None)
393 .unwrap();
394 assert!(result);
395
396 assert_eq!(rtree.size(), 0);
398 assert!(rtree.is_empty());
399 }
400}