geo/
types.rs

1use crate::{GeoFloat, Point};
2
3/// The result of trying to find the closest spot on an object to a point.
4#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum Closest<F: GeoFloat> {
7    /// The point actually intersects with the object.
8    Intersection(Point<F>),
9    /// There is exactly one place on this object which is closest to the point.
10    SinglePoint(Point<F>),
11    /// There are two or more (possibly infinite or undefined) possible points.
12    Indeterminate,
13}
14
15impl<F: GeoFloat> Closest<F> {
16    /// Compare two `Closest`s relative to `p` and return a copy of the best
17    /// one.
18    pub fn best_of_two(&self, other: &Self, p: Point<F>) -> Self {
19        use crate::EuclideanDistance;
20
21        let left = match *self {
22            Closest::Indeterminate => return *other,
23            Closest::Intersection(_) => return *self,
24            Closest::SinglePoint(l) => l,
25        };
26        let right = match *other {
27            Closest::Indeterminate => return *self,
28            Closest::Intersection(_) => return *other,
29            Closest::SinglePoint(r) => r,
30        };
31
32        if left.euclidean_distance(&p) <= right.euclidean_distance(&p) {
33            *self
34        } else {
35            *other
36        }
37    }
38}
39
40/// Implements the common pattern where a Geometry enum simply delegates its trait impl to it's inner type.
41///
42/// ```
43/// # use geo::{GeoNum, Coord, Point, Line, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, Rect, Triangle, Geometry};
44///
45/// trait Foo<T: GeoNum> {
46///     fn foo_1(&self, coord: Coord<T>)  -> bool;
47///     fn foo_2(&self) -> i32;
48/// }
49///
50/// // Assuming we have an impl for all the inner types like this:
51/// impl<T: GeoNum> Foo<T> for Point<T> {
52///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
53///     fn foo_2(&self)  -> i32 { 1 }
54/// }
55/// impl<T: GeoNum> Foo<T> for Line<T> {
56///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
57///     fn foo_2(&self)  -> i32 { 2 }
58/// }
59/// impl<T: GeoNum> Foo<T> for LineString<T> {
60///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
61///     fn foo_2(&self)  -> i32 { 3 }
62/// }
63/// impl<T: GeoNum> Foo<T> for Polygon<T> {
64///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
65///     fn foo_2(&self)  -> i32 { 4 }
66/// }
67/// impl<T: GeoNum> Foo<T> for MultiPoint<T> {
68///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
69///     fn foo_2(&self)  -> i32 { 5 }
70/// }
71/// impl<T: GeoNum> Foo<T> for MultiLineString<T> {
72///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
73///     fn foo_2(&self)  -> i32 { 6 }
74/// }
75/// impl<T: GeoNum> Foo<T> for MultiPolygon<T> {
76///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
77///     fn foo_2(&self)  -> i32 { 7 }
78/// }
79/// impl<T: GeoNum> Foo<T> for GeometryCollection<T> {
80///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
81///     fn foo_2(&self)  -> i32 { 8 }
82/// }
83/// impl<T: GeoNum> Foo<T> for Rect<T> {
84///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
85///     fn foo_2(&self)  -> i32 { 9 }
86/// }
87/// impl<T: GeoNum> Foo<T> for Triangle<T> {
88///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
89///     fn foo_2(&self)  -> i32 { 10 }
90/// }
91///
92/// // If we want the impl for Geometry to simply delegate to it's
93/// // inner case...
94/// impl<T: GeoNum> Foo<T> for Geometry<T> {
95///     // Instead of writing out this trivial enum delegation...
96///     // fn foo_1(&self, coord: Coord<T>)  -> bool {
97///     //     match self {
98///     //        Geometry::Point(g) => g.foo_1(coord),
99///     //        Geometry::LineString(g) => g.foo_1(coord),
100///     //        _ => unimplemented!("...etc for other cases")
101///     //     }
102///     // }
103///     //
104///     // fn foo_2(&self)  -> i32 {
105///     //     match self {
106///     //        Geometry::Point(g) => g.foo_2(),
107///     //        Geometry::LineString(g) => g.foo_2(),
108///     //        _ => unimplemented!("...etc for other cases")
109///     //     }
110///     // }
111///
112///     // we can equivalently write:
113///     geo::geometry_delegate_impl! {
114///         fn foo_1(&self, coord: Coord<T>) -> bool;
115///         fn foo_2(&self) -> i32;
116///     }
117/// }
118/// ```
119#[macro_export]
120macro_rules! geometry_delegate_impl {
121    ($($a:tt)*) => { $crate::__geometry_delegate_impl_helper!{ Geometry, $($a)* } }
122}
123
124#[doc(hidden)]
125#[macro_export]
126macro_rules! geometry_cow_delegate_impl {
127    ($($a:tt)*) => { $crate::__geometry_delegate_impl_helper!{ GeometryCow, $($a)* } }
128}
129
130#[doc(hidden)]
131#[macro_export]
132macro_rules! __geometry_delegate_impl_helper {
133    (
134        $enum:ident,
135        $(
136            $(#[$outer:meta])*
137            fn $func_name: ident(&$($self_life:lifetime)?self $(, $arg_name: ident: $arg_type: ty)*) -> $return: ty;
138         )+
139    ) => {
140            $(
141                $(#[$outer])*
142                fn $func_name(&$($self_life)? self, $($arg_name: $arg_type),*) -> $return {
143                    match self {
144                        $enum::Point(g) => g.$func_name($($arg_name),*).into(),
145                        $enum::Line(g) =>  g.$func_name($($arg_name),*).into(),
146                        $enum::LineString(g) => g.$func_name($($arg_name),*).into(),
147                        $enum::Polygon(g) => g.$func_name($($arg_name),*).into(),
148                        $enum::MultiPoint(g) => g.$func_name($($arg_name),*).into(),
149                        $enum::MultiLineString(g) => g.$func_name($($arg_name),*).into(),
150                        $enum::MultiPolygon(g) => g.$func_name($($arg_name),*).into(),
151                        $enum::GeometryCollection(g) => g.$func_name($($arg_name),*).into(),
152                        $enum::Rect(g) => g.$func_name($($arg_name),*).into(),
153                        $enum::Triangle(g) => g.$func_name($($arg_name),*).into(),
154                    }
155                }
156            )+
157        };
158}