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::algorithm::euclidean_distance::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, Coordinate, Point, Line, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, Rect, Triangle, Geometry};
///
/// trait Foo<T: GeoNum> {
/// fn foo_1(&self, coord: Coordinate<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: Coordinate<T>) -> bool { true }
/// fn foo_2(&self) -> i32 { 1 }
/// }
/// impl<T: GeoNum> Foo<T> for Line<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { false }
/// fn foo_2(&self) -> i32 { 2 }
/// }
/// impl<T: GeoNum> Foo<T> for LineString<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { true }
/// fn foo_2(&self) -> i32 { 3 }
/// }
/// impl<T: GeoNum> Foo<T> for Polygon<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { false }
/// fn foo_2(&self) -> i32 { 4 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiPoint<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { true }
/// fn foo_2(&self) -> i32 { 5 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiLineString<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { false }
/// fn foo_2(&self) -> i32 { 6 }
/// }
/// impl<T: GeoNum> Foo<T> for MultiPolygon<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { true }
/// fn foo_2(&self) -> i32 { 7 }
/// }
/// impl<T: GeoNum> Foo<T> for GeometryCollection<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { false }
/// fn foo_2(&self) -> i32 { 8 }
/// }
/// impl<T: GeoNum> Foo<T> for Rect<T> {
/// fn foo_1(&self, coord: Coordinate<T>) -> bool { true }
/// fn foo_2(&self) -> i32 { 9 }
/// }
/// impl<T: GeoNum> Foo<T> for Triangle<T> {
/// fn foo_1(&self, coord: Coordinate<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: Coordinate<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: Coordinate<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(),
}
}
)+
};
}