use crate::{GeoFloat, Point};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Closest<F: GeoFloat> {
Intersection(Point<F>),
SinglePoint(Point<F>),
Indeterminate,
}
impl<F: GeoFloat> Closest<F> {
pub fn best_of_two(&self, other: &Self, p: Point<F>) -> Self {
use crate::{Distance, Euclidean};
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 Euclidean.distance(left, p) <= Euclidean.distance(right, p) {
*self
} else {
*other
}
}
}
#[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(),
}
}
)+
};
}