use geometry_strategy::{WithinStrategy, WithinStrategyForKind};
use geometry_trait::{Geometry, Point};
use crate::{covered_by, within};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CoordinatePosition {
Inside,
OnBoundary,
Outside,
}
#[inline]
#[must_use]
pub fn coordinate_position<P, G>(point: &P, geometry: &G) -> CoordinatePosition
where
P: Point,
G: Geometry,
G::Kind: WithinStrategyForKind,
<G::Kind as WithinStrategyForKind>::S: WithinStrategy<P, G>,
{
if within(point, geometry) {
CoordinatePosition::Inside
} else if covered_by(point, geometry) {
CoordinatePosition::OnBoundary
} else {
CoordinatePosition::Outside
}
}
#[cfg(test)]
mod tests {
use super::{CoordinatePosition, coordinate_position};
use geometry_cs::Cartesian;
use geometry_model::{Point2D, Polygon, polygon};
type P = Point2D<f64, Cartesian>;
fn square_with_hole() -> Polygon<P> {
polygon![
[(0.0, 0.0), (0.0, 5.0), (5.0, 5.0), (5.0, 0.0), (0.0, 0.0)],
[(2.0, 2.0), (3.0, 2.0), (3.0, 3.0), (2.0, 3.0), (2.0, 2.0)]
]
}
#[test]
fn distinguishes_interior_boundary_and_exterior() {
let polygon = square_with_hole();
assert_eq!(
coordinate_position(&P::new(1.0, 1.0), &polygon),
CoordinatePosition::Inside
);
assert_eq!(
coordinate_position(&P::new(0.0, 1.0), &polygon),
CoordinatePosition::OnBoundary
);
assert_eq!(
coordinate_position(&P::new(2.5, 2.5), &polygon),
CoordinatePosition::Outside
);
}
}