Skip to main content

rstar/algorithm/
rstar.rs

1use crate::node::{envelope_for_children, ParentNode, RTreeNode};
2use crate::object::RTreeObject;
3use crate::params::{InsertionStrategy, RTreeParams};
4use crate::point::{Point, PointExt};
5use crate::rtree::RTree;
6use crate::{envelope::Envelope, object::Distance};
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        InsertionResult::Complete => InsertionResult::Complete,
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::Parent(ref data)) => data.children.first().is_none_or(RTreeNode::is_leaf),
160        None | Some(RTreeNode::Leaf(_)) => return usize::MAX,
161    };
162
163    let zero: Distance<T> = Zero::zero();
164    let insertion_envelope = to_insert.envelope();
165    let mut inclusion_count = 0;
166    let mut min_area = Distance::<T>::max_value();
167    let mut min_index = 0;
168    for (index, child) in node.children.iter().enumerate() {
169        let envelope = child.envelope();
170        if envelope.contains_envelope(&insertion_envelope) {
171            inclusion_count += 1;
172            let area = envelope.area();
173            if area < min_area {
174                min_area = area;
175                min_index = index;
176            }
177        }
178    }
179    if inclusion_count == 0 {
180        // No inclusion found, subtree depends on overlap and area increase
181        let mut min = (zero, zero, zero);
182
183        for (index1, child1) in node.children.iter().enumerate() {
184            let envelope = child1.envelope();
185            let mut new_envelope = envelope.clone();
186            new_envelope.merge(&insertion_envelope);
187            let overlap_increase = if all_leaves {
188                // Calculate minimal overlap increase
189                let mut overlap = zero;
190                let mut new_overlap = zero;
191                for (index2, child2) in node.children.iter().enumerate() {
192                    if index2 != index1 {
193                        let child_envelope = child2.envelope();
194                        let temp1 = envelope.intersection_area(&child_envelope);
195                        overlap = overlap + temp1;
196                        let temp2 = new_envelope.intersection_area(&child_envelope);
197                        new_overlap = new_overlap + temp2;
198                    }
199                }
200                new_overlap - overlap
201            } else {
202                // Don't calculate overlap increase if not all children are leaves
203                zero
204            };
205            // Calculate area increase and area
206            let area = new_envelope.area();
207            let area_increase = area - envelope.area();
208            let new_min = (overlap_increase, area_increase, area);
209            if new_min < min || index1 == 0 {
210                min = new_min;
211                min_index = index1;
212            }
213        }
214    }
215    min_index
216}
217
218// Never returns a request for reinsertion
219fn resolve_overflow_without_reinsertion<T, Params>(node: &mut ParentNode<T>) -> InsertionResult<T>
220where
221    T: RTreeObject,
222    Params: RTreeParams,
223{
224    if node.children.len() > Params::MAX_SIZE {
225        let off_split = split::<_, Params>(node);
226        InsertionResult::Split(off_split)
227    } else {
228        InsertionResult::Complete
229    }
230}
231
232fn resolve_overflow<T, Params>(node: &mut ParentNode<T>, current_depth: usize) -> InsertionResult<T>
233where
234    T: RTreeObject,
235    Params: RTreeParams,
236{
237    if Params::REINSERTION_COUNT == 0 {
238        resolve_overflow_without_reinsertion::<_, Params>(node)
239    } else if node.children.len() > Params::MAX_SIZE {
240        let nodes_for_reinsertion = get_nodes_for_reinsertion::<_, Params>(node);
241        InsertionResult::Reinsert(nodes_for_reinsertion, current_depth)
242    } else {
243        InsertionResult::Complete
244    }
245}
246
247fn split<T, Params>(node: &mut ParentNode<T>) -> RTreeNode<T>
248where
249    T: RTreeObject,
250    Params: RTreeParams,
251{
252    let axis = get_split_axis::<_, Params>(node);
253    let zero = Distance::<T>::zero();
254    debug_assert!(node.children.len() >= 2);
255    // Sort along axis
256    T::Envelope::sort_envelopes(axis, &mut node.children);
257    let mut best = (zero, zero);
258    let min_size = Params::MIN_SIZE;
259    let mut best_index = min_size;
260
261    for k in min_size..=node.children.len() - min_size {
262        let mut first_envelope = node.children[k - 1].envelope();
263        let mut second_envelope = node.children[k].envelope();
264        let (l, r) = node.children.split_at(k);
265        for child in l {
266            first_envelope.merge(&child.envelope());
267        }
268        for child in r {
269            second_envelope.merge(&child.envelope());
270        }
271
272        let overlap_value = first_envelope.intersection_area(&second_envelope);
273        let area_value = first_envelope.area() + second_envelope.area();
274        let new_best = (overlap_value, area_value);
275        if new_best < best || k == min_size {
276            best = new_best;
277            best_index = k;
278        }
279    }
280    let off_split = node.children.split_off(best_index);
281    node.envelope = envelope_for_children(&node.children);
282    RTreeNode::Parent(ParentNode::new_parent(off_split))
283}
284
285fn get_split_axis<T, Params>(node: &mut ParentNode<T>) -> usize
286where
287    T: RTreeObject,
288    Params: RTreeParams,
289{
290    let mut best_goodness = Distance::<T>::max_value();
291    let mut best_axis = 0;
292    let min_size = Params::MIN_SIZE;
293    let until = node.children.len() - min_size + 1;
294    for axis in 0..<T::Envelope as Envelope>::Point::DIMENSIONS {
295        // Sort children along the current axis
296        T::Envelope::sort_envelopes(axis, &mut node.children);
297        let mut first_envelope = T::Envelope::new_empty();
298        let mut second_envelope = T::Envelope::new_empty();
299        for child in &node.children[..min_size] {
300            first_envelope.merge(&child.envelope());
301        }
302        for child in &node.children[until..] {
303            second_envelope.merge(&child.envelope());
304        }
305        for k in min_size..until {
306            let mut first_modified = first_envelope.clone();
307            let mut second_modified = second_envelope.clone();
308            let (l, r) = node.children.split_at(k);
309            for child in l {
310                first_modified.merge(&child.envelope());
311            }
312            for child in r {
313                second_modified.merge(&child.envelope());
314            }
315
316            let perimeter_value =
317                first_modified.perimeter_value() + second_modified.perimeter_value();
318            if best_goodness > perimeter_value {
319                best_axis = axis;
320                best_goodness = perimeter_value;
321            }
322        }
323    }
324    best_axis
325}
326
327fn get_nodes_for_reinsertion<T, Params>(node: &mut ParentNode<T>) -> Vec<RTreeNode<T>>
328where
329    T: RTreeObject,
330    Params: RTreeParams,
331{
332    let center = node.envelope.center();
333    // Sort with increasing order so we can use Vec::split_off
334    node.children.sort_unstable_by(|l, r| {
335        let l_center = l.envelope().center();
336        let r_center = r.envelope().center();
337        l_center
338            .sub(&center)
339            .length_2()
340            .partial_cmp(&(r_center.sub(&center)).length_2())
341            .unwrap()
342    });
343    let num_children = node.children.len();
344    let result = node
345        .children
346        .split_off(num_children - Params::REINSERTION_COUNT);
347    node.envelope = envelope_for_children(&node.children);
348    result
349}