geometry_algorithm/
coordinate_position.rs1use geometry_strategy::{WithinStrategy, WithinStrategyForKind};
8use geometry_trait::{Geometry, Point};
9
10use crate::{covered_by, within};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum CoordinatePosition {
19 Inside,
21 OnBoundary,
23 Outside,
25}
26
27#[inline]
32#[must_use]
33pub fn coordinate_position<P, G>(point: &P, geometry: &G) -> CoordinatePosition
34where
35 P: Point,
36 G: Geometry,
37 G::Kind: WithinStrategyForKind,
38 <G::Kind as WithinStrategyForKind>::S: WithinStrategy<P, G>,
39{
40 if within(point, geometry) {
41 CoordinatePosition::Inside
42 } else if covered_by(point, geometry) {
43 CoordinatePosition::OnBoundary
44 } else {
45 CoordinatePosition::Outside
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::{CoordinatePosition, coordinate_position};
52 use geometry_cs::Cartesian;
53 use geometry_model::{Point2D, Polygon, polygon};
54
55 type P = Point2D<f64, Cartesian>;
56
57 fn square_with_hole() -> Polygon<P> {
58 polygon![
59 [(0.0, 0.0), (0.0, 5.0), (5.0, 5.0), (5.0, 0.0), (0.0, 0.0)],
60 [(2.0, 2.0), (3.0, 2.0), (3.0, 3.0), (2.0, 3.0), (2.0, 2.0)]
61 ]
62 }
63
64 #[test]
65 fn distinguishes_interior_boundary_and_exterior() {
66 let polygon = square_with_hole();
67 assert_eq!(
68 coordinate_position(&P::new(1.0, 1.0), &polygon),
69 CoordinatePosition::Inside
70 );
71 assert_eq!(
72 coordinate_position(&P::new(0.0, 1.0), &polygon),
73 CoordinatePosition::OnBoundary
74 );
75 assert_eq!(
76 coordinate_position(&P::new(2.5, 2.5), &polygon),
77 CoordinatePosition::Outside
78 );
79 }
80}