geo/algorithm/sweep/
cross.rs

1use std::{fmt::Debug, rc::Rc, sync::Arc};
2
3use geo_types::Line;
4
5use super::*;
6use crate::GeoFloat;
7
8/// Interface for types that can be processed to detect crossings.
9///
10/// This type is implemented by [`LineOrPoint`], but users may also implement
11/// this on custom types to store extra information. Any type that represents an
12/// ordered line-segment may implement this.
13///
14/// # Cloning
15///
16/// Note that for usage with the planar sweep iterators, the type must
17/// also impl. `Clone`. If the custom type is not cheap to clone, use
18/// either a reference to the type, a [`Rc`] or an [`Arc`]. All these
19/// are supported via blanket trait implementations.
20pub trait Cross: Sized + Debug {
21    /// Scalar used the coordinates.
22    type Scalar: GeoFloat;
23
24    /// The geometry associated with this type. Use a `Line` with the
25    /// `start` and `end` coordinates to represent a point.
26    fn line(&self) -> LineOrPoint<Self::Scalar>;
27}
28
29impl<'a, T: Cross> Cross for &'a T {
30    type Scalar = T::Scalar;
31
32    fn line(&self) -> LineOrPoint<Self::Scalar> {
33        T::line(*self)
34    }
35}
36
37impl<T: GeoFloat> Cross for LineOrPoint<T> {
38    type Scalar = T;
39
40    fn line(&self) -> LineOrPoint<Self::Scalar> {
41        *self
42    }
43}
44
45impl<T: GeoFloat> Cross for Line<T> {
46    type Scalar = T;
47
48    fn line(&self) -> LineOrPoint<Self::Scalar> {
49        (*self).into()
50    }
51}
52
53macro_rules! blanket_impl_smart_pointer {
54    ($ty:ty) => {
55        impl<T: Cross> Cross for $ty {
56            type Scalar = T::Scalar;
57
58            fn line(&self) -> LineOrPoint<Self::Scalar> {
59                T::line(self)
60            }
61        }
62    };
63}
64blanket_impl_smart_pointer!(Box<T>);
65blanket_impl_smart_pointer!(Rc<T>);
66blanket_impl_smart_pointer!(Arc<T>);