Skip to main content

geometry_algorithm/
dyn_envelope.rs

1//! `envelope_dyn` — runtime-dispatched envelope for [`DynGeometry`].
2//!
3//! Mirrors `boost::geometry::envelope(g)` reached through the variant
4//! adapter (`algorithms/envelope.hpp`). Returns a
5//! `model::Box<Point<S, 2, Cs>>`.
6//!
7//! Every single/multi variant is supported (each per-kind envelope
8//! strategy resolves through the tag-keyed
9//! [`geometry_strategy::EnvelopeStrategyForKind`] picker). The
10//! `GeometryCollection` arm returns `Err(DynKindMismatch)`: computing
11//! its envelope needs a box-merge primitive v1 does not yet ship (and
12//! an empty collection has no well-defined envelope). That arm lands
13//! when the merge helper does.
14
15use geometry_coords::CoordinateScalar;
16use geometry_cs::{CartesianFamily, CoordinateSystem};
17use geometry_model::{Box, DynGeometry, DynKind, Linestring, Point, Polygon};
18use geometry_strategy::{EnvelopeStrategy, EnvelopeStrategyForKind};
19use geometry_tag::{
20    LinestringTag, MultiLinestringTag, MultiPointTag, MultiPolygonTag, PointTag, PolygonTag, SameAs,
21};
22
23use crate::dyn_error::DynKindMismatch;
24use crate::envelope::envelope;
25
26const SUPPORTED: &[&[DynKind]] = &[
27    &[DynKind::Point],
28    &[DynKind::LineString],
29    &[DynKind::Polygon],
30    &[DynKind::MultiPoint],
31    &[DynKind::MultiLineString],
32    &[DynKind::MultiPolygon],
33];
34
35/// Runtime-dispatched envelope.
36///
37/// Returns `Ok(Box)` for every single/multi kind.
38///
39/// # Errors
40///
41/// Returns `Err(DynKindMismatch)` for `GeometryCollection` (see the
42/// module docs — it needs a box-merge primitive v1 lacks).
43pub fn envelope_dyn<S, Cs>(g: &DynGeometry<S, Cs>) -> Result<Box<Point<S, 2, Cs>>, DynKindMismatch>
44where
45    S: CoordinateScalar,
46    Cs: CoordinateSystem,
47    Cs::Family: SameAs<CartesianFamily>,
48    // Each arm calls the tag-dispatched `envelope` free fn; require the
49    // picked per-kind strategy for each concrete arm type to produce a
50    // `Box<Point<S, 2, Cs>>`.
51    <PointTag as EnvelopeStrategyForKind>::S:
52        EnvelopeStrategy<Point<S, 2, Cs>, Output = Box<Point<S, 2, Cs>>>,
53    <LinestringTag as EnvelopeStrategyForKind>::S:
54        EnvelopeStrategy<Linestring<Point<S, 2, Cs>>, Output = Box<Point<S, 2, Cs>>>,
55    <PolygonTag as EnvelopeStrategyForKind>::S:
56        EnvelopeStrategy<Polygon<Point<S, 2, Cs>>, Output = Box<Point<S, 2, Cs>>>,
57    <MultiPointTag as EnvelopeStrategyForKind>::S: EnvelopeStrategy<geometry_model::MultiPoint<Point<S, 2, Cs>>, Output = Box<Point<S, 2, Cs>>>,
58    <MultiLinestringTag as EnvelopeStrategyForKind>::S: EnvelopeStrategy<
59            geometry_model::MultiLinestring<Linestring<Point<S, 2, Cs>>>,
60            Output = Box<Point<S, 2, Cs>>,
61        >,
62    <MultiPolygonTag as EnvelopeStrategyForKind>::S: EnvelopeStrategy<
63            geometry_model::MultiPolygon<Polygon<Point<S, 2, Cs>>>,
64            Output = Box<Point<S, 2, Cs>>,
65        >,
66{
67    use DynGeometry::{
68        GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon,
69        Point as PointArm, Polygon as PolygonArm,
70    };
71    match g {
72        PointArm(p) => Ok(envelope(p)),
73        LineString(ls) => Ok(envelope(ls)),
74        PolygonArm(pg) => Ok(envelope(pg)),
75        MultiPoint(mp) => Ok(envelope(mp)),
76        MultiLineString(ml) => Ok(envelope(ml)),
77        MultiPolygon(mpg) => Ok(envelope(mpg)),
78        GeometryCollection(_) => Err(DynKindMismatch {
79            got: alloc::vec![g.kind()],
80            expected: SUPPORTED,
81        }),
82    }
83}