use alloc::rc::Rc;
use alloc::sync::Arc;
use crate::aabb::AABB;
use crate::envelope::Envelope;
use crate::point::{Point, PointExt};
#[allow(type_alias_bounds)]
pub(crate) type Distance<T: PointDistance> = <<T::Envelope as Envelope>::Point as Point>::Scalar;
pub trait RTreeObject {
type Envelope: Envelope;
fn envelope(&self) -> Self::Envelope;
}
pub trait PointDistance: RTreeObject {
fn distance_2(&self, point: &<Self::Envelope as Envelope>::Point) -> Distance<Self>;
fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
self.distance_2(point) <= num_traits::zero()
}
fn distance_2_if_less_or_equal(
&self,
point: &<Self::Envelope as Envelope>::Point,
max_distance_2: Distance<Self>,
) -> Option<Distance<Self>> {
let envelope_distance = self.envelope().distance_2(point);
if envelope_distance <= max_distance_2 {
let distance_2 = self.distance_2(point);
if distance_2 <= max_distance_2 {
return Some(distance_2);
}
}
None
}
}
impl<P> RTreeObject for P
where
P: Point,
{
type Envelope = AABB<P>;
fn envelope(&self) -> AABB<P> {
AABB::from_point(self.clone())
}
}
impl<P> PointDistance for P
where
P: Point,
{
fn distance_2(&self, point: &P) -> P::Scalar {
<Self as PointExt>::distance_2(self, point)
}
fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
self == point
}
fn distance_2_if_less_or_equal(
&self,
point: &<Self::Envelope as Envelope>::Point,
max_distance_2: Distance<Self>,
) -> Option<P::Scalar> {
let distance_2 = <Self as PointExt>::distance_2(self, point);
if distance_2 <= max_distance_2 {
Some(distance_2)
} else {
None
}
}
}
impl<T> RTreeObject for Arc<T>
where
T: RTreeObject + ?Sized,
{
type Envelope = T::Envelope;
fn envelope(&self) -> Self::Envelope {
(**self).envelope()
}
}
impl<T> PointDistance for Arc<T>
where
T: PointDistance + ?Sized,
{
fn distance_2(&self, point: &<Self::Envelope as Envelope>::Point) -> Distance<Self> {
(**self).distance_2(point)
}
fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
(**self).contains_point(point)
}
fn distance_2_if_less_or_equal(
&self,
point: &<Self::Envelope as Envelope>::Point,
max_distance_2: Distance<Self>,
) -> Option<Distance<Self>> {
(**self).distance_2_if_less_or_equal(point, max_distance_2)
}
}
impl<T> RTreeObject for Rc<T>
where
T: RTreeObject + ?Sized,
{
type Envelope = T::Envelope;
fn envelope(&self) -> Self::Envelope {
(**self).envelope()
}
}
impl<T> PointDistance for Rc<T>
where
T: PointDistance + ?Sized,
{
fn distance_2(&self, point: &<Self::Envelope as Envelope>::Point) -> Distance<Self> {
(**self).distance_2(point)
}
fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
(**self).contains_point(point)
}
fn distance_2_if_less_or_equal(
&self,
point: &<Self::Envelope as Envelope>::Point,
max_distance_2: Distance<Self>,
) -> Option<Distance<Self>> {
(**self).distance_2_if_less_or_equal(point, max_distance_2)
}
}