From 6caa058225949f90eef94e4aa4ed260c2112e546 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 3 Nov 2024 20:22:08 +0100 Subject: [PATCH] Add ObjectRef combinator to build tree referencing objects elsewhere. --- rstar/src/primitives/mod.rs | 2 + rstar/src/primitives/object_ref.rs | 62 ++++++++++++++++++++++++++++++ rstar/src/rtree.rs | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 rstar/src/primitives/object_ref.rs diff --git a/rstar/src/primitives/mod.rs b/rstar/src/primitives/mod.rs index 51dcf85..27e1ebc 100644 --- a/rstar/src/primitives/mod.rs +++ b/rstar/src/primitives/mod.rs @@ -3,11 +3,13 @@ mod cached_envelope; mod geom_with_data; mod line; +mod object_ref; mod point_with_data; mod rectangle; pub use self::cached_envelope::CachedEnvelope; pub use self::geom_with_data::GeomWithData; pub use self::line::Line; +pub use self::object_ref::ObjectRef; pub use self::point_with_data::PointWithData; pub use self::rectangle::Rectangle; diff --git a/rstar/src/primitives/object_ref.rs b/rstar/src/primitives/object_ref.rs new file mode 100644 index 0000000..0608d81 --- /dev/null +++ b/rstar/src/primitives/object_ref.rs @@ -0,0 +1,62 @@ +use crate::envelope::Envelope; +use crate::object::PointDistance; +use crate::{object::RTreeObject, point::Point}; +use core::ops::Deref; + +/// An [RTreeObject] that is a possibly short-lived reference to another object. +/// +/// Sometimes it can be useful to build an [RTree] that does not own its constituent +/// objects but references them from elsewhere. Wrapping the bare references with this +/// combinator makes this possible. +/// +/// **Note:** the wrapper implements [RTreeObject] and referenced object `T` can be +/// accessed via an implementation of `Deref`. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ObjectRef<'a, T: RTreeObject> { + inner: &'a T, +} + +impl<'a, T: RTreeObject> RTreeObject for ObjectRef<'a, T> { + type Envelope = T::Envelope; + + fn envelope(&self) -> Self::Envelope { + self.inner.envelope() + } +} + +impl<'a, T: PointDistance> PointDistance for ObjectRef<'a, T> { + fn distance_2( + &self, + point: &::Point, + ) -> <::Point as Point>::Scalar { + self.inner.distance_2(point) + } + + fn contains_point(&self, p: &::Point) -> bool { + self.inner.contains_point(p) + } + + fn distance_2_if_less_or_equal( + &self, + point: &::Point, + max_distance_2: <::Point as Point>::Scalar, + ) -> Option<<::Point as Point>::Scalar> { + self.inner + .distance_2_if_less_or_equal(point, max_distance_2) + } +} + +impl<'a, T: RTreeObject> ObjectRef<'a, T> { + /// Create a new [ObjectRef] struct using the object. + pub fn new(inner: &'a T) -> Self { + Self { inner } + } +} + +impl<'a, T: RTreeObject> Deref for ObjectRef<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.inner + } +} diff --git a/rstar/src/rtree.rs b/rstar/src/rtree.rs index 0dd1279..0d87d53 100644 --- a/rstar/src/rtree.rs +++ b/rstar/src/rtree.rs @@ -436,7 +436,7 @@ where pub fn intersection_candidates_with_other_tree<'a, U>( &'a self, other: &'a RTree, - ) -> IntersectionIterator + ) -> IntersectionIterator<'a, T, U> where U: RTreeObject, {