1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use crate::{GeoFloat, Point};

/// The result of trying to find the closest spot on an object to a point.
#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Closest<F: GeoFloat> {
    /// The point actually intersects with the object.
    Intersection(Point<F>),
    /// There is exactly one place on this object which is closest to the point.
    SinglePoint(Point<F>),
    /// There are two or more (possibly infinite or undefined) possible points.
    Indeterminate,
}

impl<F: GeoFloat> Closest<F> {
    /// Compare two `Closest`s relative to `p` and return a copy of the best
    /// one.
    pub fn best_of_two(&self, other: &Self, p: Point<F>) -> Self {
        use crate::EuclideanDistance;

        let left = match *self {
            Closest::Indeterminate => return *other,
            Closest::Intersection(_) => return *self,
            Closest::SinglePoint(l) => l,
        };
        let right = match *other {
            Closest::Indeterminate => return *self,
            Closest::Intersection(_) => return *other,
            Closest::SinglePoint(r) => r,
        };

        if left.euclidean_distance(&p) <= right.euclidean_distance(&p) {
            *self
        } else {
            *other
        }
    }
}

/// Implements the common pattern where a Geometry enum simply delegates its trait impl to it's inner type.
///
/// ```
/// # use geo::{GeoNum, Coord, Point, Line, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, Rect, Triangle, Geometry};
///
/// trait Foo<T: GeoNum> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool;
///     fn foo_2(&self) -> i32;
/// }
///
/// // Assuming we have an impl for all the inner types like this:
/// impl<T: GeoNum> Foo<T> for Point<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 1 }
/// }
/// impl<T: GeoNum> Foo<T> for Line<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
///     fn foo_2(&self)  -> i32 { 2 }
/// }
/// impl<T: GeoNum> Foo<T> for LineString<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 3 }
/// }
/// impl<T: GeoNum> Foo<T> for Polygon<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
///     fn foo_2(&self)  -> i32 { 4 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiPoint<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 5 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiLineString<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
///     fn foo_2(&self)  -> i32 { 6 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiPolygon<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 7 }
/// }
/// impl<T: GeoNum> Foo<T> for GeometryCollection<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { false }
///     fn foo_2(&self)  -> i32 { 8 }
/// }
/// impl<T: GeoNum> Foo<T> for Rect<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 9 }
/// }
/// impl<T: GeoNum> Foo<T> for Triangle<T> {
///     fn foo_1(&self, coord: Coord<T>)  -> bool { true }
///     fn foo_2(&self)  -> i32 { 10 }
/// }
///
/// // If we want the impl for Geometry to simply delegate to it's
/// // inner case...
/// impl<T: GeoNum> Foo<T> for Geometry<T> {
///     // Instead of writing out this trivial enum delegation...
///     // fn foo_1(&self, coord: Coord<T>)  -> bool {
///     //     match self {
///     //        Geometry::Point(g) => g.foo_1(coord),
///     //        Geometry::LineString(g) => g.foo_1(coord),
///     //        _ => unimplemented!("...etc for other cases")
///     //     }
///     // }
///     //
///     // fn foo_2(&self)  -> i32 {
///     //     match self {
///     //        Geometry::Point(g) => g.foo_2(),
///     //        Geometry::LineString(g) => g.foo_2(),
///     //        _ => unimplemented!("...etc for other cases")
///     //     }
///     // }
///
///     // we can equivalently write:
///     geo::geometry_delegate_impl! {
///         fn foo_1(&self, coord: Coord<T>) -> bool;
///         fn foo_2(&self) -> i32;
///     }
/// }
/// ```
#[macro_export]
macro_rules! geometry_delegate_impl {
    ($($a:tt)*) => { $crate::__geometry_delegate_impl_helper!{ Geometry, $($a)* } }
}

#[doc(hidden)]
#[macro_export]
macro_rules! geometry_cow_delegate_impl {
    ($($a:tt)*) => { $crate::__geometry_delegate_impl_helper!{ GeometryCow, $($a)* } }
}

#[doc(hidden)]
#[macro_export]
macro_rules! __geometry_delegate_impl_helper {
    (
        $enum:ident,
        $(
            $(#[$outer:meta])*
            fn $func_name: ident(&$($self_life:lifetime)?self $(, $arg_name: ident: $arg_type: ty)*) -> $return: ty;
         )+
    ) => {
            $(
                $(#[$outer])*
                fn $func_name(&$($self_life)? self, $($arg_name: $arg_type),*) -> $return {
                    match self {
                        $enum::Point(g) => g.$func_name($($arg_name),*).into(),
                        $enum::Line(g) =>  g.$func_name($($arg_name),*).into(),
                        $enum::LineString(g) => g.$func_name($($arg_name),*).into(),
                        $enum::Polygon(g) => g.$func_name($($arg_name),*).into(),
                        $enum::MultiPoint(g) => g.$func_name($($arg_name),*).into(),
                        $enum::MultiLineString(g) => g.$func_name($($arg_name),*).into(),
                        $enum::MultiPolygon(g) => g.$func_name($($arg_name),*).into(),
                        $enum::GeometryCollection(g) => g.$func_name($($arg_name),*).into(),
                        $enum::Rect(g) => g.$func_name($($arg_name),*).into(),
                        $enum::Triangle(g) => g.$func_name($($arg_name),*).into(),
                    }
                }
            )+
        };
}