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}