#![allow(
clippy::float_cmp,
reason = "Reference values are exact integer-valued literals."
)]
use geometry_algorithm::{area_dyn, distance_dyn, envelope_dyn, length_dyn, within_dyn};
use geometry_cs::Cartesian;
use geometry_model::{DynGeometry, DynKind, Point2D};
use geometry_model::{linestring, polygon};
type S = f64;
type Pt = Point2D<S, Cartesian>;
#[test]
fn distance_dyn_point_point_matches_static() {
let a = DynGeometry::<S, Cartesian>::Point(Pt::new(0.0, 0.0));
let b = DynGeometry::<S, Cartesian>::Point(Pt::new(3.0, 4.0));
assert_eq!(distance_dyn(&a, &b).unwrap(), 5.0);
}
#[test]
fn distance_dyn_point_linestring_is_min_over_segments() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(0.0, 5.0));
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![(0.0, 0.0), (10.0, 0.0)]);
assert_eq!(distance_dyn(&p, &ls).unwrap(), 5.0);
assert_eq!(distance_dyn(&ls, &p).unwrap(), 5.0);
}
#[test]
fn distance_dyn_point_linestring_keeps_earlier_closer_segment() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(0.0, 1.0));
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![
(0.0, 0.0),
(10.0, 0.0),
(10.0, -50.0),
(20.0, -50.0)
]);
assert_eq!(distance_dyn(&p, &ls).unwrap(), 1.0);
}
#[test]
fn distance_dyn_point_to_single_vertex_linestring() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(3.0, 4.0));
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![(0.0, 0.0)]);
assert_eq!(distance_dyn(&p, &ls).unwrap(), 5.0);
}
#[test]
fn distance_dyn_point_to_empty_linestring_is_zero() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(3.0, 4.0));
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![]);
assert_eq!(distance_dyn(&p, &ls).unwrap(), 0.0);
}
#[test]
fn distance_dyn_unsupported_pair_returns_mismatch() {
let a = DynGeometry::<S, Cartesian>::Polygon(polygon![[
(0.0, 0.0),
(1.0, 0.0),
(1.0, 1.0),
(0.0, 0.0)
]]);
let b = DynGeometry::<S, Cartesian>::Polygon(polygon![[
(2.0, 2.0),
(3.0, 2.0),
(3.0, 3.0),
(2.0, 2.0)
]]);
let err = distance_dyn(&a, &b).unwrap_err();
assert_eq!(err.got, vec![DynKind::Polygon, DynKind::Polygon]);
assert!(!err.expected.is_empty());
}
#[test]
fn length_dyn_linestring_matches_static() {
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![(0.0, 0.0), (3.0, 4.0)]);
assert_eq!(length_dyn(&ls), 5.0);
}
#[test]
fn length_dyn_point_is_zero() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(1.0, 2.0));
assert_eq!(length_dyn(&p), 0.0);
}
#[test]
fn length_dyn_multi_linestring_sums_members() {
let mls = DynGeometry::<S, Cartesian>::MultiLineString(geometry_model::MultiLinestring(vec![
linestring![(0.0, 0.0), (3.0, 4.0)], linestring![(0.0, 0.0), (0.0, 2.0)], ]));
assert_eq!(length_dyn(&mls), 7.0);
}
#[test]
fn length_dyn_collection_sums_members() {
let inner = DynGeometry::<S, Cartesian>::GeometryCollection(vec![
DynGeometry::LineString(linestring![(0.0, 0.0), (3.0, 4.0)]), ]);
let gc = DynGeometry::<S, Cartesian>::GeometryCollection(vec![
DynGeometry::Point(Pt::new(9.0, 9.0)), DynGeometry::LineString(linestring![(0.0, 0.0), (0.0, 2.0)]), inner, ]);
assert_eq!(length_dyn(&gc), 7.0);
assert_eq!(
length_dyn(&DynGeometry::<S, Cartesian>::GeometryCollection(vec![])),
0.0
);
}
#[test]
fn area_dyn_polygon_matches_static() {
let pg = DynGeometry::<S, Cartesian>::Polygon(polygon![[
(0.0, 0.0),
(0.0, 1.0),
(1.0, 1.0),
(1.0, 0.0),
(0.0, 0.0)
]]);
assert_eq!(area_dyn(&pg), 1.0);
}
#[test]
fn area_dyn_linestring_is_zero() {
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![(0.0, 0.0), (3.0, 4.0)]);
assert_eq!(area_dyn(&ls), 0.0);
}
#[test]
fn area_dyn_collection_sums_members() {
let unit_square = || {
DynGeometry::<S, Cartesian>::Polygon(polygon![[
(0.0, 0.0),
(0.0, 1.0),
(1.0, 1.0),
(1.0, 0.0),
(0.0, 0.0)
]])
};
let inner = DynGeometry::<S, Cartesian>::GeometryCollection(vec![unit_square()]); let gc = DynGeometry::<S, Cartesian>::GeometryCollection(vec![
unit_square(), DynGeometry::LineString(linestring![(0.0, 0.0), (3.0, 4.0)]), inner, ]);
assert_eq!(area_dyn(&gc), 2.0);
assert_eq!(
area_dyn(&DynGeometry::<S, Cartesian>::GeometryCollection(vec![])),
0.0
);
}
#[test]
fn dyn_measures_over_deeply_nested_collection_do_not_overflow() {
let mut g = DynGeometry::<S, Cartesian>::Polygon(polygon![[
(0.0, 0.0),
(0.0, 1.0),
(1.0, 1.0),
(1.0, 0.0),
(0.0, 0.0)
]]);
for _ in 0..200_000 {
g = DynGeometry::GeometryCollection(vec![g]);
}
assert_eq!(area_dyn(&g), 1.0);
assert_eq!(length_dyn(&g), 0.0);
core::mem::forget(g);
}
#[test]
fn envelope_dyn_linestring_matches_static() {
use geometry_trait::IndexedAccess as _;
let ls = DynGeometry::<S, Cartesian>::LineString(linestring![(1.0, 2.0), (3.0, 0.0)]);
let b = envelope_dyn(&ls).unwrap();
assert_eq!(b.get_indexed::<0, 0>(), 1.0);
assert_eq!(b.get_indexed::<0, 1>(), 0.0);
assert_eq!(b.get_indexed::<1, 0>(), 3.0);
assert_eq!(b.get_indexed::<1, 1>(), 2.0);
}
#[test]
fn envelope_dyn_collection_returns_mismatch() {
let gc = DynGeometry::<S, Cartesian>::GeometryCollection(vec![]);
let err = envelope_dyn(&gc).unwrap_err();
assert_eq!(err.got, vec![DynKind::GeometryCollection]);
assert!(!err.expected.is_empty());
}
#[test]
fn within_dyn_point_in_polygon_matches_static() {
let p = DynGeometry::<S, Cartesian>::Point(Pt::new(0.5, 0.5));
let pg = DynGeometry::<S, Cartesian>::Polygon(polygon![[
(0.0, 0.0),
(0.0, 1.0),
(1.0, 1.0),
(1.0, 0.0),
(0.0, 0.0)
]]);
assert!(within_dyn(&p, &pg).unwrap());
let outside = DynGeometry::<S, Cartesian>::Point(Pt::new(5.0, 5.0));
assert!(!within_dyn(&outside, &pg).unwrap());
}
#[test]
fn within_dyn_unsupported_pair_returns_mismatch() {
let a = DynGeometry::<S, Cartesian>::Point(Pt::new(0.0, 0.0));
let b = DynGeometry::<S, Cartesian>::Point(Pt::new(1.0, 1.0));
let err = within_dyn(&a, &b).unwrap_err();
assert_eq!(err.got, vec![DynKind::Point, DynKind::Point]);
assert!(!err.expected.is_empty());
}