1use geometry_strategy::{EnvelopeStrategy, EnvelopeStrategyForKind};
17use geometry_trait::Geometry;
18
19#[inline]
33#[must_use]
34pub fn envelope<G>(
35 g: &G,
36) -> <<G::Kind as EnvelopeStrategyForKind>::S as EnvelopeStrategy<G>>::Output
37where
38 G: Geometry,
39 G::Kind: EnvelopeStrategyForKind,
40 <G::Kind as EnvelopeStrategyForKind>::S: EnvelopeStrategy<G>,
41{
42 <<G::Kind as EnvelopeStrategyForKind>::S as Default>::default().envelope(g)
43}
44
45#[cfg(test)]
46mod tests {
47 use super::envelope;
52 use geometry_cs::Cartesian;
53 use geometry_model::{Box, Linestring, Point2D, Polygon, Segment, linestring, polygon};
54 use geometry_trait::IndexedAccess as _;
55
56 type P = Point2D<f64, Cartesian>;
57
58 fn assert_2d(b: &Box<P>, xmin: f64, xmax: f64, ymin: f64, ymax: f64) {
59 assert_eq!(b.get_indexed::<0, 0>().to_bits(), xmin.to_bits());
60 assert_eq!(b.get_indexed::<0, 1>().to_bits(), ymin.to_bits());
61 assert_eq!(b.get_indexed::<1, 0>().to_bits(), xmax.to_bits());
62 assert_eq!(b.get_indexed::<1, 1>().to_bits(), ymax.to_bits());
63 }
64
65 #[test]
67 fn point_envelope_collapses() {
68 let p = Point2D::<f64, Cartesian>::new(1.0, 1.0);
69 assert_2d(&envelope(&p), 1.0, 1.0, 1.0, 1.0);
70 }
71
72 #[test]
74 fn linestring_two_points() {
75 let ls: Linestring<P> = linestring![(1.0, 1.0), (2.0, 2.0)];
76 assert_2d(&envelope(&ls), 1.0, 2.0, 1.0, 2.0);
77 }
78
79 #[test]
81 fn polygon_axis_aligned_square() {
82 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),]];
83 assert_2d(&envelope(&p), 1.0, 3.0, 1.0, 3.0);
84 }
85
86 #[test]
88 fn box_envelope_is_self() {
89 let b = Box::from_corners(
90 Point2D::<f64, Cartesian>::new(1.0, 1.0),
91 Point2D::<f64, Cartesian>::new(3.0, 3.0),
92 );
93 assert_2d(&envelope(&b), 1.0, 3.0, 1.0, 3.0);
94 }
95
96 #[test]
99 fn ring_non_convex() {
100 let p: Polygon<P> = polygon![[(4.0, 1.0), (0.0, 7.0), (7.0, 9.0), (4.0, 1.0)]];
101 assert_2d(&envelope(&p), 0.0, 7.0, 1.0, 9.0);
102 }
103
104 #[test]
106 fn segment_envelope() {
107 let s = Segment::new(
108 Point2D::<f64, Cartesian>::new(1.0, 1.0),
109 Point2D::<f64, Cartesian>::new(3.0, 3.0),
110 );
111 assert_2d(&envelope(&s), 1.0, 3.0, 1.0, 3.0);
112 }
113
114 #[test]
117 fn ring_envelope_direct() {
118 let r: geometry_model::Ring<P> = geometry_model::Ring::from_vec(vec![
119 Point2D::new(4.0, 1.0),
120 Point2D::new(0.0, 7.0),
121 Point2D::new(7.0, 9.0),
122 Point2D::new(4.0, 1.0),
123 ]);
124 assert_2d(&envelope(&r), 0.0, 7.0, 1.0, 9.0);
125 }
126
127 #[test]
132 fn multi_point_envelope() {
133 let mp = geometry_model::MultiPoint(vec![
134 Point2D::<f64, Cartesian>::new(-3.0, -1.0),
135 Point2D::<f64, Cartesian>::new(-1.0, -4.0),
136 ]);
137 assert_2d(&envelope(&mp), -3.0, -1.0, -4.0, -1.0);
138 let empty = geometry_model::MultiPoint::<P>(vec![]);
139 assert_2d(&envelope(&empty), 0.0, 0.0, 0.0, 0.0);
140 }
141
142 #[test]
144 fn multi_linestring_envelope_spans_members() {
145 let mls = geometry_model::MultiLinestring::<Linestring<P>>(vec![
146 linestring![(1.0, 1.0), (2.0, 2.0)],
147 linestring![(-5.0, 4.0), (0.0, 0.0)],
148 ]);
149 assert_2d(&envelope(&mls), -5.0, 2.0, 0.0, 4.0);
150 }
151
152 #[test]
154 fn multi_polygon_envelope_spans_members() {
155 let mpg = geometry_model::MultiPolygon::<Polygon<P>>(vec![
156 polygon![[(1.0, 1.0), (1.0, 3.0), (3.0, 3.0), (3.0, 1.0), (1.0, 1.0)]],
157 polygon![[(10.0, -2.0), (10.0, 0.0), (12.0, 0.0), (10.0, -2.0)]],
158 ]);
159 assert_2d(&envelope(&mpg), 1.0, 12.0, -2.0, 3.0);
160 }
161
162 #[test]
165 fn three_d_segment_envelope() {
166 use geometry_model::Point3D;
167 type P3 = Point3D<f64, Cartesian>;
168 let s = Segment::new(P3::new(1.0, 2.0, 9.0), P3::new(3.0, 0.0, -1.0));
169 let b = envelope(&s);
170 assert_eq!(b.get_indexed::<0, 2>().to_bits(), (-1.0_f64).to_bits());
171 assert_eq!(b.get_indexed::<1, 2>().to_bits(), 9.0_f64.to_bits());
172 }
173
174 #[test]
176 fn four_d_point_envelope() {
177 use geometry_model::Point;
178 use geometry_trait::PointMut as _;
179 type P4 = Point<f64, 4, Cartesian>;
180 let mut p = P4::default();
181 p.set::<3>(7.0);
182 let b = envelope(&p);
183 assert_eq!(b.get_indexed::<0, 3>().to_bits(), 7.0_f64.to_bits());
184 assert_eq!(b.get_indexed::<1, 3>().to_bits(), 7.0_f64.to_bits());
185 }
186}