use geometry_strategy::{WithinStrategy, WithinStrategyForKind};
use geometry_trait::{Geometry, Point};
#[inline]
#[must_use]
pub fn within<P, G>(p: &P, g: &G) -> bool
where
P: Point,
G: Geometry,
G::Kind: WithinStrategyForKind,
<G::Kind as WithinStrategyForKind>::S: WithinStrategy<P, G>,
{
<<G::Kind as WithinStrategyForKind>::S as Default>::default().within(p, g)
}
#[inline]
#[must_use]
pub fn covered_by<P, G>(p: &P, g: &G) -> bool
where
P: Point,
G: Geometry,
G::Kind: WithinStrategyForKind,
<G::Kind as WithinStrategyForKind>::S: WithinStrategy<P, G>,
{
<<G::Kind as WithinStrategyForKind>::S as Default>::default().covered_by(p, g)
}
#[cfg(test)]
mod tests {
use super::{covered_by, within};
use geometry_cs::Cartesian;
use geometry_model::{Box, Point2D, Polygon, Ring, polygon};
type P = Point2D<f64, Cartesian>;
fn pt(x: f64, y: f64) -> P {
Point2D::new(x, y)
}
fn box_polygon() -> Polygon<P> {
polygon![[(0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)]]
}
#[test]
fn box_b1_inside() {
assert!(within(&pt(1.0, 1.0), &box_polygon()));
}
#[test]
fn box_b2_outside() {
assert!(!within(&pt(3.0, 3.0), &box_polygon()));
}
#[test]
fn box_corners_excluded() {
let p = box_polygon();
for (x, y) in [(0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0)] {
assert!(!within(&pt(x, y), &p), "corner ({x},{y})");
}
}
#[test]
fn box_sides_excluded() {
let p = box_polygon();
for (x, y) in [(0.0, 1.0), (1.0, 2.0), (2.0, 1.0), (1.0, 0.0)] {
assert!(!within(&pt(x, y), &p), "side ({x},{y})");
}
}
fn triangle() -> Polygon<P> {
polygon![[(0.0, 0.0), (0.0, 4.0), (6.0, 0.0), (0.0, 0.0)]]
}
#[test]
fn triangle_t1_inside() {
assert!(within(&pt(1.0, 1.0), &triangle()));
}
#[test]
fn triangle_t2_outside() {
assert!(!within(&pt(3.0, 3.0), &triangle()));
}
fn with_hole() -> Polygon<P> {
polygon![
[(0.0, 0.0), (0.0, 3.0), (3.0, 3.0), (3.0, 0.0), (0.0, 0.0)],
[(1.0, 1.0), (2.0, 1.0), (2.0, 2.0), (1.0, 2.0), (1.0, 1.0)]
]
}
#[test]
fn hole_h1_in_outer_not_hole() {
assert!(within(&pt(0.5, 0.5), &with_hole()));
}
#[test]
fn hole_h2a_in_hole_not_within() {
assert!(!within(&pt(1.5, 1.5), &with_hole()));
}
#[test]
fn covered_by_includes_boundary() {
let p = box_polygon();
assert!(covered_by(&pt(0.0, 0.0), &p)); assert!(covered_by(&pt(0.0, 1.0), &p)); assert!(covered_by(&pt(1.0, 1.0), &p)); assert!(!covered_by(&pt(3.0, 3.0), &p)); }
#[test]
fn quickstart_polygon_3_7_2_0_is_within() {
let q: Polygon<P> = polygon![[
(2.0, 1.3),
(2.4, 1.7),
(2.8, 1.8),
(3.4, 1.2),
(3.7, 1.6),
(3.4, 2.0),
(4.1, 3.0),
(5.3, 2.6),
(5.4, 1.2),
(4.9, 0.8),
(2.9, 0.7),
(2.0, 1.3)
]];
assert!(within(&pt(3.7, 2.0), &q));
}
#[test]
fn box_geometry_within_and_covered_by() {
let b = Box::from_corners(pt(0.0, 0.0), pt(2.0, 2.0));
assert!(within(&pt(1.0, 1.0), &b));
assert!(!within(&pt(0.0, 0.0), &b));
assert!(covered_by(&pt(0.0, 0.0), &b));
assert!(!covered_by(&pt(3.0, 3.0), &b));
}
#[test]
fn ring_within_and_covered_by() {
let r: Ring<P> = Ring::from_vec(vec![
pt(0.0, 0.0),
pt(0.0, 2.0),
pt(2.0, 2.0),
pt(2.0, 0.0),
pt(0.0, 0.0),
]);
assert!(within(&pt(1.0, 1.0), &r));
assert!(!within(&pt(0.0, 0.0), &r));
assert!(covered_by(&pt(0.0, 0.0), &r));
}
}