From 88e25e9f83dcdea676a78caa78231d5036270eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20H=C3=BCgel?= Date: Wed, 27 Sep 2023 11:20:22 +0100 Subject: [PATCH 1/4] Better distance_2 docs --- rstar/CHANGELOG.md | 1 + rstar/src/object.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/rstar/CHANGELOG.md b/rstar/CHANGELOG.md index 9cd204a..b4111d7 100644 --- a/rstar/CHANGELOG.md +++ b/rstar/CHANGELOG.md @@ -5,6 +5,7 @@ ## Changed - Fixed a stack overflow error in `DrainIterator::next` +- Clarified that the distance measure in `distance_2` is not restricted to euclidean distance # 0.11.0 diff --git a/rstar/src/object.rs b/rstar/src/object.rs index d1ddee9..b37fc1f 100644 --- a/rstar/src/object.rs +++ b/rstar/src/object.rs @@ -145,7 +145,12 @@ pub trait RTreeObject { /// assert!(circle.contains_point(&[1.0, 0.0])); /// ``` pub trait PointDistance: RTreeObject { - /// Returns the squared euclidean distance between an object to a point. + /// Returns the squared distance between an object to a point. + /// + /// # Notes + /// While euclidean distance will be the correct choice for most use cases, any distance metric + /// fulfilling the [usual axioms](https://en.wikipedia.org/wiki/Metric_space) + /// can be used when implementing this method. fn distance_2( &self, point: &::Point, From cf49703fd431430f9abb5e2b205b68ce8ed32db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20H=C3=BCgel?= Date: Wed, 27 Sep 2023 16:20:52 +0100 Subject: [PATCH 2/4] Update rstar/src/object.rs Co-authored-by: Michael Kirk --- rstar/src/object.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rstar/src/object.rs b/rstar/src/object.rs index b37fc1f..8874172 100644 --- a/rstar/src/object.rs +++ b/rstar/src/object.rs @@ -145,7 +145,7 @@ pub trait RTreeObject { /// assert!(circle.contains_point(&[1.0, 0.0])); /// ``` pub trait PointDistance: RTreeObject { - /// Returns the squared distance between an object to a point. + /// Returns the squared distance between an object and a point. /// /// # Notes /// While euclidean distance will be the correct choice for most use cases, any distance metric From e60f1a00144fbf15c8f57c940b03870b7ca2b6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20H=C3=BCgel?= Date: Wed, 27 Sep 2023 17:41:47 +0100 Subject: [PATCH 3/4] Re-order RTree docs, fix links and typos --- rstar/src/rtree.rs | 66 ++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/rstar/src/rtree.rs b/rstar/src/rtree.rs index 5f2fab7..c2d1865 100644 --- a/rstar/src/rtree.rs +++ b/rstar/src/rtree.rs @@ -41,7 +41,7 @@ where /// /// However, creating an r-tree is time consuming /// and runs in `O(n * log(n))`. Thus, r-trees are suited best if many queries and only few -/// insertions are made. rstar also supports [bulk loading](RTree::bulk_load), +/// insertions are made. `rstar` also supports [bulk loading](RTree::bulk_load), /// which cuts down the constant factors when creating an r-tree significantly compared to /// sequential insertions. /// @@ -53,16 +53,13 @@ where /// on fast insertion operations, the resulting r-trees were often suboptimally structured. Another /// heuristic, called `R*-tree` (r-star-tree), was proposed to improve the tree structure at the cost of /// longer insertion operations and is currently the crate's only implemented -/// [insertion strategy]. -/// -/// ## Further reading -/// For more information refer to the [wikipedia article](https://en.wikipedia.org/wiki/R-tree). +/// [InsertionStrategy]. /// /// # Usage /// The items inserted into an r-tree must implement the [RTreeObject] /// trait. To support nearest neighbor queries, implement the [PointDistance] /// trait. Some useful geometric primitives that implement the above traits can be found in the -/// [crate::primitives]x module. Several primitives in the [`geo-types`](https://docs.rs/geo-types/) crate also +/// [crate::primitives] module. Several primitives in the [`geo-types`](https://docs.rs/geo-types/) crate also /// implement these traits. /// /// ## Example @@ -89,26 +86,8 @@ where /// All types implementing the [Point] trait can be used as underlying point type. /// By default, fixed size arrays can be used as points. /// -/// ## Type Parameters -/// * `T`: The type of objects stored in the r-tree. -/// * `Params`: Compile time parameters that change the r-tree's internal layout. Refer to the -/// [RTreeParams] trait for more information. -/// -/// ## Defining methods generic over r-trees -/// If a library defines a method that should be generic over the r-tree type signature, make -/// sure to include both type parameters like this: -/// ``` -/// # use rstar::{RTree,RTreeObject, RTreeParams}; -/// pub fn generic_rtree_function(tree: &mut RTree) -/// where -/// T: RTreeObject, -/// Params: RTreeParams -/// { -/// // ... -/// } -/// ``` -/// Otherwise, any user of `generic_rtree_function` would be forced to use -/// a tree with default parameters. +/// # Associating Data with Geometries +/// Users wishing to store associated data with geometries can use [crate::primitives::GeomWithData]. /// /// # Runtime and Performance /// The runtime of query operations (e.g. `nearest neighbor` or `contains`) is usually @@ -116,12 +95,12 @@ where /// A naive sequential algorithm would take `O(n)` time. However, r-trees incur higher /// build up times: inserting an element into an r-tree costs `O(log(n))` time. /// -/// ## Bulk loading +/// # Bulk loading /// In many scenarios, insertion is only carried out once for many points. In this case, /// [RTree::bulk_load] will be considerably faster. Its total run time -/// is still `O(log(n))`. +/// is still `O(log(n))`. **Note the performance caveat related to the computation of the envelope**. /// -/// ## Element distribution +/// # Element distribution /// The tree's performance heavily relies on the spatial distribution of its elements. /// Best performance is achieved if: /// * No element is inserted more than once @@ -131,9 +110,33 @@ where /// For the edge case that all elements are overlapping (e.g, one and the same element /// is contained `n` times), the performance of most operations usually degrades to `O(n)`. /// +/// # Type Parameters +/// * `T`: The type of objects stored in the r-tree. +/// * `Params`: Compile time parameters that change the r-tree's internal layout. Refer to the +/// [RTreeParams] trait for more information. +/// +/// # Defining methods generic over r-trees +/// If a library defines a method that should be generic over the r-tree type signature, make +/// sure to include both type parameters like this: +/// ``` +/// # use rstar::{RTree,RTreeObject, RTreeParams}; +/// pub fn generic_rtree_function(tree: &mut RTree) +/// where +/// T: RTreeObject, +/// Params: RTreeParams +/// { +/// // ... +/// } +/// ``` +/// Otherwise, any user of `generic_rtree_function` would be forced to use +/// a tree with default parameters. +/// /// # (De)Serialization /// Enable the `serde` feature for [Serde](https://crates.io/crates/serde) support. /// +/// ## Further reading +/// For more information refer to the [wikipedia article](https://en.wikipedia.org/wiki/R-tree). +/// #[derive(Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( @@ -209,8 +212,9 @@ where /// Bulk loading runs in `O(n * log(n))`, where `n` is the number of loaded /// elements. /// - /// Note that the envelope of each element will be accessed many times, - /// so if that computation is expensive, consider memoizing it using [`CachedEnvelope`][crate::primitives::CachedEnvelope]. + /// # Note + /// The envelope of each element will be accessed many times during loading. If that computation + /// is expensive, **consider memoizing it** using [`CachedEnvelope`][crate::primitives::CachedEnvelope]. pub fn bulk_load(elements: Vec) -> Self { Self::bulk_load_with_params(elements) } From 107a17fc1c83d8366bf54d915bd3e6fa306753ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20H=C3=BCgel?= Date: Wed, 27 Sep 2023 18:43:06 +0100 Subject: [PATCH 4/4] Point out that both distance_2 implementations must use same metric --- rstar/src/envelope.rs | 8 +++++++- rstar/src/object.rs | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/rstar/src/envelope.rs b/rstar/src/envelope.rs index 91978f4..01cfac3 100644 --- a/rstar/src/envelope.rs +++ b/rstar/src/envelope.rs @@ -33,7 +33,13 @@ pub trait Envelope: Clone + PartialEq + ::core::fmt::Debug { /// Returns this envelope's area. Must be at least 0. fn area(&self) -> ::Scalar; - /// Returns the euclidean distance to the envelope's border. + /// Returns the squared distance between the envelope's border and a point. + /// + /// # Notes + /// - While euclidean distance will be the correct choice for most use cases, any distance metric + /// fulfilling the [usual axioms](https://en.wikipedia.org/wiki/Metric_space) + /// can be used when implementing this method + /// - Implementers **must** ensure that the distance metric used matches that of [crate::PointDistance::distance_2] fn distance_2(&self, point: &Self::Point) -> ::Scalar; /// Returns the squared min-max distance, a concept that helps to find nearest neighbors efficiently. diff --git a/rstar/src/object.rs b/rstar/src/object.rs index 8874172..79334f1 100644 --- a/rstar/src/object.rs +++ b/rstar/src/object.rs @@ -148,9 +148,10 @@ pub trait PointDistance: RTreeObject { /// Returns the squared distance between an object and a point. /// /// # Notes - /// While euclidean distance will be the correct choice for most use cases, any distance metric + /// - While euclidean distance will be the correct choice for most use cases, any distance metric /// fulfilling the [usual axioms](https://en.wikipedia.org/wiki/Metric_space) - /// can be used when implementing this method. + /// can be used when implementing this method + /// - Implementers **must** ensure that the distance metric used matches that of [crate::Envelope::distance_2] fn distance_2( &self, point: &::Point,