use geometry_strategy::{EnvelopeStrategy, EnvelopeStrategyForKind};
use geometry_trait::Geometry;
#[inline]
#[must_use]
pub fn envelope<G>(
g: &G,
) -> <<G::Kind as EnvelopeStrategyForKind>::S as EnvelopeStrategy<G>>::Output
where
G: Geometry,
G::Kind: EnvelopeStrategyForKind,
<G::Kind as EnvelopeStrategyForKind>::S: EnvelopeStrategy<G>,
{
<<G::Kind as EnvelopeStrategyForKind>::S as Default>::default().envelope(g)
}
#[cfg(test)]
mod tests {
use super::envelope;
use geometry_cs::Cartesian;
use geometry_model::{Box, Linestring, Point2D, Polygon, Segment, linestring, polygon};
use geometry_trait::IndexedAccess as _;
type P = Point2D<f64, Cartesian>;
fn assert_2d(b: &Box<P>, xmin: f64, xmax: f64, ymin: f64, ymax: f64) {
assert_eq!(b.get_indexed::<0, 0>().to_bits(), xmin.to_bits());
assert_eq!(b.get_indexed::<0, 1>().to_bits(), ymin.to_bits());
assert_eq!(b.get_indexed::<1, 0>().to_bits(), xmax.to_bits());
assert_eq!(b.get_indexed::<1, 1>().to_bits(), ymax.to_bits());
}
#[test]
fn point_envelope_collapses() {
let p = Point2D::<f64, Cartesian>::new(1.0, 1.0);
assert_2d(&envelope(&p), 1.0, 1.0, 1.0, 1.0);
}
#[test]
fn linestring_two_points() {
let ls: Linestring<P> = linestring![(1.0, 1.0), (2.0, 2.0)];
assert_2d(&envelope(&ls), 1.0, 2.0, 1.0, 2.0);
}
#[test]
fn polygon_axis_aligned_square() {
let p: Polygon<P> = polygon![[(1.0, 1.0), (1.0, 3.0), (3.0, 3.0), (3.0, 1.0), (1.0, 1.0),]];
assert_2d(&envelope(&p), 1.0, 3.0, 1.0, 3.0);
}
#[test]
fn box_envelope_is_self() {
let b = Box::from_corners(
Point2D::<f64, Cartesian>::new(1.0, 1.0),
Point2D::<f64, Cartesian>::new(3.0, 3.0),
);
assert_2d(&envelope(&b), 1.0, 3.0, 1.0, 3.0);
}
#[test]
fn ring_non_convex() {
let p: Polygon<P> = polygon![[(4.0, 1.0), (0.0, 7.0), (7.0, 9.0), (4.0, 1.0)]];
assert_2d(&envelope(&p), 0.0, 7.0, 1.0, 9.0);
}
#[test]
fn segment_envelope() {
let s = Segment::new(
Point2D::<f64, Cartesian>::new(1.0, 1.0),
Point2D::<f64, Cartesian>::new(3.0, 3.0),
);
assert_2d(&envelope(&s), 1.0, 3.0, 1.0, 3.0);
}
}