1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
use crate::algorithm::rstar::RStarInsertionStrategy; use crate::{Envelope, Point, RTree, RTreeObject}; /// Defines static parameters for an r-tree. /// /// Internally, an r-tree contains several nodes, similar to a b-tree. These parameters change /// the size of these nodes and can be used to fine tune the tree's performance. /// /// # Example /// ``` /// use rstar::{RTreeParams, RTree, RStarInsertionStrategy}; /// /// // This example uses an rtree with larger internal nodes. /// struct LargeNodeParameters; /// /// impl RTreeParams for LargeNodeParameters /// { /// const MIN_SIZE: usize = 10; /// const MAX_SIZE: usize = 30; /// const REINSERTION_COUNT: usize = 5; /// type DefaultInsertionStrategy = RStarInsertionStrategy; /// } /// /// // Optional but helpful: Define a type alias for the new r-tree /// type LargeNodeRTree<T> = RTree<T, LargeNodeParameters>; /// /// # fn main() { /// // The only difference from now on is the usage of "new_with_params" instead of "new" /// let mut large_node_tree: LargeNodeRTree<_> = RTree::new_with_params(); /// // Using the r-tree should allow inference for the point type /// large_node_tree.insert([1.0, -1.0f32]); /// // There is also a bulk load method with parameters: /// # let some_elements = vec![[0.0, 0.0]]; /// let tree: LargeNodeRTree<_> = RTree::bulk_load_with_params(some_elements); /// # } /// ``` pub trait RTreeParams: Send + Sync { /// The minimum size of an internal node. Must be at most half as large as `MAX_SIZE`. /// Choosing a value around one half or one third of `MAX_SIZE` is recommended. Higher /// values should yield slightly better tree quality while lower values may benefit /// insertion performance. const MIN_SIZE: usize; /// The maximum size of an internal node. Larger values will improve insertion performance /// but increase the average query time. const MAX_SIZE: usize; /// The number of nodes that the insertion strategy tries to reinsert sometimes to /// maintain a good tree quality. Must be smaller than `MAX_SIZE` - `MIN_SIZE`. /// Larger values will improve query times but increase insertion time. const REINSERTION_COUNT: usize; /// The insertion strategy which is used when calling [insert](struct.RTree.html#method.insert). type DefaultInsertionStrategy: InsertionStrategy; } /// The default parameters used when creating an r-tree without specific parameters. #[derive(Clone, Copy, PartialEq, Eq)] pub struct DefaultParams; impl RTreeParams for DefaultParams { const MIN_SIZE: usize = 3; const MAX_SIZE: usize = 6; const REINSERTION_COUNT: usize = 2; type DefaultInsertionStrategy = RStarInsertionStrategy; } /// Defines how points are inserted into an r-tree. /// /// Different strategies try to minimize both _insertion time_ (how long does it take to add a new /// object into the tree?) and _querying time_ (how long does an average nearest neighbor query /// take?). /// Currently, only one insertion strategy is implemented: R* (R-star) insertion. R* insertion /// tries to minimize querying performance while yielding reasonable insertion times, making it a /// good default strategy. More strategies might be implemented in the future. /// /// Only calls to [insert](struct.RTree.html#method.insert) are affected by this strategy. /// /// This trait is not meant to be implemented by the user. pub trait InsertionStrategy { #[doc(hidden)] fn insert<T, Params>(tree: &mut RTree<T, Params>, t: T) where Params: RTreeParams, T: RTreeObject; } pub fn verify_parameters<T: RTreeObject, P: RTreeParams>() { assert!( P::MAX_SIZE >= 4, "MAX_SIZE too small. Must be larger than 4." ); let max_min_size = (P::MAX_SIZE + 1) / 2; assert!( P::MIN_SIZE <= max_min_size, "MIN_SIZE too large. Must be less or equal to {:?}", max_min_size ); let max_reinsertion_count = P::MAX_SIZE - P::MIN_SIZE; assert!( P::REINSERTION_COUNT < max_reinsertion_count, "REINSERTION_COUNT too large. Must be smaller than {:?}", max_reinsertion_count ); let dimension = <T::Envelope as Envelope>::Point::DIMENSIONS; assert!( dimension > 1, "Point dimension too small - must be at least 2" ); }