rstar/algorithm/
rstar.rs

1use crate::envelope::Envelope;
2use crate::node::{envelope_for_children, ParentNode, RTreeNode};
3use crate::object::RTreeObject;
4use crate::params::{InsertionStrategy, RTreeParams};
5use crate::point::{Point, PointExt};
6use crate::rtree::RTree;
7
8#[cfg(not(test))]
9use alloc::vec::Vec;
10use num_traits::{Bounded, Zero};
11
12/// Inserts points according to the r-star heuristic.
13///
14/// The r*-heuristic focusses on good insertion quality at the costs of
15/// insertion performance. This strategy is best for use cases with few
16/// insertions and many nearest neighbor queries.
17///
18/// `RStarInsertionStrategy` is used as the default insertion strategy.
19/// See [InsertionStrategy] for more information on insertion strategies.
20pub enum RStarInsertionStrategy {}
21
22enum InsertionResult<T>
23where
24    T: RTreeObject,
25{
26    Split(RTreeNode<T>),
27    Reinsert(Vec<RTreeNode<T>>, usize),
28    Complete,
29}
30
31impl InsertionStrategy for RStarInsertionStrategy {
32    fn insert<T, Params>(tree: &mut RTree<T, Params>, t: T)
33    where
34        Params: RTreeParams,
35        T: RTreeObject,
36    {
37        use InsertionAction::*;
38
39        enum InsertionAction<T: RTreeObject> {
40            PerformSplit(RTreeNode<T>),
41            PerformReinsert(RTreeNode<T>),
42        }
43
44        let first = recursive_insert::<_, Params>(tree.root_mut(), RTreeNode::Leaf(t), 0);
45        let mut target_height = 0;
46        let mut insertion_stack = Vec::new();
47        match first {
48            InsertionResult::Split(node) => insertion_stack.push(PerformSplit(node)),
49            InsertionResult::Reinsert(nodes_to_reinsert, real_target_height) => {
50                insertion_stack.extend(nodes_to_reinsert.into_iter().map(PerformReinsert));
51                target_height = real_target_height;
52            }
53            InsertionResult::Complete => {}
54        };
55
56        while let Some(next) = insertion_stack.pop() {
57            match next {
58                PerformSplit(node) => {
59                    // The root node was split, create a new root and increase height
60                    let new_root = ParentNode::new_root::<Params>();
61                    let old_root = ::core::mem::replace(tree.root_mut(), new_root);
62                    let new_envelope = old_root.envelope.merged(&node.envelope());
63                    let root = tree.root_mut();
64                    root.envelope = new_envelope;
65                    root.children.push(RTreeNode::Parent(old_root));
66                    root.children.push(node);
67                    target_height += 1;
68                }
69                PerformReinsert(node_to_reinsert) => {
70                    let root = tree.root_mut();
71                    match forced_insertion::<T, Params>(root, node_to_reinsert, target_height) {
72                        InsertionResult::Split(node) => insertion_stack.push(PerformSplit(node)),
73                        InsertionResult::Reinsert(_, _) => {
74                            panic!("Unexpected reinsert. This is a bug in rstar.")
75                        }
76                        InsertionResult::Complete => {}
77                    }
78                }
79            }
80        }
81    }
82}
83
84fn forced_insertion<T, Params>(
85    node: &mut ParentNode<T>,
86    t: RTreeNode<T>,
87    target_height: usize,
88) -> InsertionResult<T>
89where
90    T: RTreeObject,
91    Params: RTreeParams,
92{
93    node.envelope.merge(&t.envelope());
94    let expand_index = choose_subtree(node, &t);
95
96    if target_height == 0 || node.children.len() < expand_index {
97        // Force insertion into this node
98        node.children.push(t);
99        return resolve_overflow_without_reinsertion::<_, Params>(node);
100    }
101
102    if let RTreeNode::Parent(ref mut follow) = node.children[expand_index] {
103        match forced_insertion::<_, Params>(follow, t, target_height - 1) {
104            InsertionResult::Split(child) => {
105                node.envelope.merge(&child.envelope());
106                node.children.push(child);
107                resolve_overflow_without_reinsertion::<_, Params>(node)
108            }
109            other => other,
110        }
111    } else {
112        unreachable!("This is a bug in rstar.")
113    }
114}
115
116fn recursive_insert<T, Params>(
117    node: &mut ParentNode<T>,
118    t: RTreeNode<T>,
119    current_height: usize,
120) -> InsertionResult<T>
121where
122    T: RTreeObject,
123    Params: RTreeParams,
124{
125    node.envelope.merge(&t.envelope());
126    let expand_index = choose_subtree(node, &t);
127
128    if node.children.len() < expand_index {
129        // Force insertion into this node
130        node.children.push(t);
131        return resolve_overflow::<_, Params>(node, current_height);
132    }
133
134    let expand = if let RTreeNode::Parent(ref mut follow) = node.children[expand_index] {
135        recursive_insert::<_, Params>(follow, t, current_height + 1)
136    } else {
137        panic!("This is a bug in rstar.")
138    };
139
140    match expand {
141        InsertionResult::Split(child) => {
142            node.envelope.merge(&child.envelope());
143            node.children.push(child);
144            resolve_overflow::<_, Params>(node, current_height)
145        }
146        InsertionResult::Reinsert(a, b) => {
147            node.envelope = envelope_for_children(&node.children);
148            InsertionResult::Reinsert(a, b)
149        }
150        other => other,
151    }
152}
153
154fn choose_subtree<T>(node: &ParentNode<T>, to_insert: &RTreeNode<T>) -> usize
155where
156    T: RTreeObject,
157{
158    let all_leaves = match node.children.first() {
159        Some(RTreeNode::Leaf(_)) => return usize::MAX,
160        Some(RTreeNode::Parent(ref data)) => data
161            .children
162            .first()
163            .map(RTreeNode::is_leaf)
164            .unwrap_or(true),
165        None => return usize::MAX,
166    };
167
168    let zero: <<T::Envelope as Envelope>::Point as Point>::Scalar = Zero::zero();
169    let insertion_envelope = to_insert.envelope();
170    let mut inclusion_count = 0;
171    let mut min_area = <<T::Envelope as Envelope>::Point as Point>::Scalar::max_value();
172    let mut min_index = 0;
173    for (index, child) in node.children.iter().enumerate() {
174        let envelope = child.envelope();
175        if envelope.contains_envelope(&insertion_envelope) {
176            inclusion_count += 1;
177            let area = envelope.area();
178            if area < min_area {
179                min_area = area;
180                min_index = index;
181            }
182        }
183    }
184    if inclusion_count == 0 {
185        // No inclusion found, subtree depends on overlap and area increase
186        let mut min = (zero, zero, zero);
187
188        for (index, child1) in node.children.iter().enumerate() {
189            let envelope = child1.envelope();
190            let mut new_envelope = envelope.clone();
191            new_envelope.merge(&insertion_envelope);
192            let overlap_increase = if all_leaves {
193                // Calculate minimal overlap increase
194                let mut overlap = zero;
195                let mut new_overlap = zero;
196                for child2 in &node.children {
197                    if child1 as *const _ != child2 as *const _ {
198                        let child_envelope = child2.envelope();
199                        let temp1 = envelope.intersection_area(&child_envelope);
200                        overlap = overlap + temp1;
201                        let temp2 = new_envelope.intersection_area(&child_envelope);
202                        new_overlap = new_overlap + temp2;
203                    }
204                }
205                new_overlap - overlap
206            } else {
207                // Don't calculate overlap increase if not all children are leaves
208                zero
209            };
210            // Calculate area increase and area
211            let area = new_envelope.area();
212            let area_increase = area - envelope.area();
213            let new_min = (overlap_increase, area_increase, area);
214            if new_min < min || index == 0 {
215                min = new_min;
216                min_index = index;
217            }
218        }
219    }
220    min_index
221}
222
223// Never returns a request for reinsertion
224fn resolve_overflow_without_reinsertion<T, Params>(node: &mut ParentNode<T>) -> InsertionResult<T>
225where
226    T: RTreeObject,
227    Params: RTreeParams,
228{
229    if node.children.len() > Params::MAX_SIZE {
230        let off_split = split::<_, Params>(node);
231        InsertionResult::Split(off_split)
232    } else {
233        InsertionResult::Complete
234    }
235}
236
237fn resolve_overflow<T, Params>(node: &mut ParentNode<T>, current_depth: usize) -> InsertionResult<T>
238where
239    T: RTreeObject,
240    Params: RTreeParams,
241{
242    if Params::REINSERTION_COUNT == 0 {
243        resolve_overflow_without_reinsertion::<_, Params>(node)
244    } else if node.children.len() > Params::MAX_SIZE {
245        let nodes_for_reinsertion = get_nodes_for_reinsertion::<_, Params>(node);
246        InsertionResult::Reinsert(nodes_for_reinsertion, current_depth)
247    } else {
248        InsertionResult::Complete
249    }
250}
251
252fn split<T, Params>(node: &mut ParentNode<T>) -> RTreeNode<T>
253where
254    T: RTreeObject,
255    Params: RTreeParams,
256{
257    let axis = get_split_axis::<_, Params>(node);
258    let zero = <<T::Envelope as Envelope>::Point as Point>::Scalar::zero();
259    debug_assert!(node.children.len() >= 2);
260    // Sort along axis
261    T::Envelope::sort_envelopes(axis, &mut node.children);
262    let mut best = (zero, zero);
263    let min_size = Params::MIN_SIZE;
264    let mut best_index = min_size;
265
266    for k in min_size..=node.children.len() - min_size {
267        let mut first_envelope = node.children[k - 1].envelope();
268        let mut second_envelope = node.children[k].envelope();
269        let (l, r) = node.children.split_at(k);
270        for child in l {
271            first_envelope.merge(&child.envelope());
272        }
273        for child in r {
274            second_envelope.merge(&child.envelope());
275        }
276
277        let overlap_value = first_envelope.intersection_area(&second_envelope);
278        let area_value = first_envelope.area() + second_envelope.area();
279        let new_best = (overlap_value, area_value);
280        if new_best < best || k == min_size {
281            best = new_best;
282            best_index = k;
283        }
284    }
285    let off_split = node.children.split_off(best_index);
286    node.envelope = envelope_for_children(&node.children);
287    RTreeNode::Parent(ParentNode::new_parent(off_split))
288}
289
290fn get_split_axis<T, Params>(node: &mut ParentNode<T>) -> usize
291where
292    T: RTreeObject,
293    Params: RTreeParams,
294{
295    let mut best_goodness = <<T::Envelope as Envelope>::Point as Point>::Scalar::max_value();
296    let mut best_axis = 0;
297    let min_size = Params::MIN_SIZE;
298    let until = node.children.len() - min_size + 1;
299    for axis in 0..<T::Envelope as Envelope>::Point::DIMENSIONS {
300        // Sort children along the current axis
301        T::Envelope::sort_envelopes(axis, &mut node.children);
302        let mut first_envelope = T::Envelope::new_empty();
303        let mut second_envelope = T::Envelope::new_empty();
304        for child in &node.children[..min_size] {
305            first_envelope.merge(&child.envelope());
306        }
307        for child in &node.children[until..] {
308            second_envelope.merge(&child.envelope());
309        }
310        for k in min_size..until {
311            let mut first_modified = first_envelope.clone();
312            let mut second_modified = second_envelope.clone();
313            let (l, r) = node.children.split_at(k);
314            for child in l {
315                first_modified.merge(&child.envelope());
316            }
317            for child in r {
318                second_modified.merge(&child.envelope());
319            }
320
321            let perimeter_value =
322                first_modified.perimeter_value() + second_modified.perimeter_value();
323            if best_goodness > perimeter_value {
324                best_axis = axis;
325                best_goodness = perimeter_value;
326            }
327        }
328    }
329    best_axis
330}
331
332fn get_nodes_for_reinsertion<T, Params>(node: &mut ParentNode<T>) -> Vec<RTreeNode<T>>
333where
334    T: RTreeObject,
335    Params: RTreeParams,
336{
337    let center = node.envelope.center();
338    // Sort with increasing order so we can use Vec::split_off
339    node.children.sort_unstable_by(|l, r| {
340        let l_center = l.envelope().center();
341        let r_center = r.envelope().center();
342        l_center
343            .sub(&center)
344            .length_2()
345            .partial_cmp(&(r_center.sub(&center)).length_2())
346            .unwrap()
347    });
348    let num_children = node.children.len();
349    let result = node
350        .children
351        .split_off(num_children - Params::REINSERTION_COUNT);
352    node.envelope = envelope_for_children(&node.children);
353    result
354}