geo_types/geometry/
geometry_collection.rs1use crate::{CoordNum, Geometry};
2
3use alloc::vec;
4use alloc::vec::Vec;
5use core::iter::FromIterator;
6use core::ops::{Index, IndexMut};
7
8#[derive(Eq, PartialEq, Clone, Hash)]
73#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74pub struct GeometryCollection<T: CoordNum = f64>(pub Vec<Geometry<T>>);
75
76impl<T: CoordNum> Default for GeometryCollection<T> {
79 fn default() -> Self {
80 Self(Vec::new())
81 }
82}
83
84impl<T: CoordNum> GeometryCollection<T> {
85 #[deprecated(
87 note = "Will be replaced with a parametrized version in upcoming version. Use GeometryCollection::empty() instead"
88 )]
89 pub fn new() -> Self {
90 GeometryCollection::default()
91 }
92
93 pub fn new_from(value: Vec<Geometry<T>>) -> Self {
97 Self(value)
98 }
99
100 pub fn empty() -> Self {
102 Self(Vec::new())
103 }
104
105 pub fn len(&self) -> usize {
107 self.0.len()
108 }
109
110 pub fn is_empty(&self) -> bool {
112 self.0.is_empty()
113 }
114}
115
116impl<T: CoordNum, IG: Into<Geometry<T>>> From<IG> for GeometryCollection<T> {
120 fn from(x: IG) -> Self {
121 Self(vec![x.into()])
122 }
123}
124
125impl<T: CoordNum, IG: Into<Geometry<T>>> From<Vec<IG>> for GeometryCollection<T> {
126 fn from(geoms: Vec<IG>) -> Self {
127 let geoms: Vec<Geometry<_>> = geoms.into_iter().map(Into::into).collect();
128 Self(geoms)
129 }
130}
131
132impl<T: CoordNum, IG: Into<Geometry<T>>> FromIterator<IG> for GeometryCollection<T> {
134 fn from_iter<I: IntoIterator<Item = IG>>(iter: I) -> Self {
135 Self(iter.into_iter().map(|g| g.into()).collect())
136 }
137}
138
139impl<T: CoordNum> Index<usize> for GeometryCollection<T> {
140 type Output = Geometry<T>;
141
142 fn index(&self, index: usize) -> &Geometry<T> {
143 self.0.index(index)
144 }
145}
146
147impl<T: CoordNum> IndexMut<usize> for GeometryCollection<T> {
148 fn index_mut(&mut self, index: usize) -> &mut Geometry<T> {
149 self.0.index_mut(index)
150 }
151}
152
153#[derive(Debug)]
155pub struct IntoIteratorHelper<T: CoordNum> {
156 iter: ::alloc::vec::IntoIter<Geometry<T>>,
157}
158
159impl<T: CoordNum> IntoIterator for GeometryCollection<T> {
162 type Item = Geometry<T>;
163 type IntoIter = IntoIteratorHelper<T>;
164
165 fn into_iter(self) -> Self::IntoIter {
167 IntoIteratorHelper {
168 iter: self.0.into_iter(),
169 }
170 }
171}
172
173impl<T: CoordNum> Iterator for IntoIteratorHelper<T> {
175 type Item = Geometry<T>;
176
177 fn next(&mut self) -> Option<Self::Item> {
179 self.iter.next()
180 }
181}
182
183#[derive(Debug)]
185pub struct IterHelper<'a, T: CoordNum> {
186 iter: ::core::slice::Iter<'a, Geometry<T>>,
187}
188
189impl<'a, T: CoordNum> IntoIterator for &'a GeometryCollection<T> {
192 type Item = &'a Geometry<T>;
193 type IntoIter = IterHelper<'a, T>;
194
195 fn into_iter(self) -> Self::IntoIter {
197 IterHelper {
198 iter: self.0.iter(),
199 }
200 }
201}
202
203impl<'a, T: CoordNum> Iterator for IterHelper<'a, T> {
205 type Item = &'a Geometry<T>;
206
207 fn next(&mut self) -> Option<Self::Item> {
209 self.iter.next()
210 }
211}
212
213#[derive(Debug)]
215pub struct IterMutHelper<'a, T: CoordNum> {
216 iter: ::core::slice::IterMut<'a, Geometry<T>>,
217}
218
219impl<'a, T: CoordNum> IntoIterator for &'a mut GeometryCollection<T> {
222 type Item = &'a mut Geometry<T>;
223 type IntoIter = IterMutHelper<'a, T>;
224
225 fn into_iter(self) -> Self::IntoIter {
227 IterMutHelper {
228 iter: self.0.iter_mut(),
229 }
230 }
231}
232
233impl<'a, T: CoordNum> Iterator for IterMutHelper<'a, T> {
235 type Item = &'a mut Geometry<T>;
236
237 fn next(&mut self) -> Option<Self::Item> {
239 self.iter.next()
240 }
241}
242
243impl<'a, T: CoordNum> GeometryCollection<T> {
244 pub fn iter(&'a self) -> IterHelper<'a, T> {
245 self.into_iter()
246 }
247
248 pub fn iter_mut(&'a mut self) -> IterMutHelper<'a, T> {
249 self.into_iter()
250 }
251}
252
253#[cfg(any(feature = "approx", test))]
254mod approx_integration {
255 use super::*;
256 use approx::{AbsDiffEq, RelativeEq, UlpsEq};
257
258 impl<T> RelativeEq for GeometryCollection<T>
259 where
260 T: CoordNum + RelativeEq<Epsilon = T>,
261 {
262 #[inline]
263 fn default_max_relative() -> Self::Epsilon {
264 T::default_max_relative()
265 }
266
267 #[inline]
281 fn relative_eq(
282 &self,
283 other: &Self,
284 epsilon: Self::Epsilon,
285 max_relative: Self::Epsilon,
286 ) -> bool {
287 if self.0.len() != other.0.len() {
288 return false;
289 }
290
291 self.iter()
292 .zip(other.iter())
293 .all(|(lhs, rhs)| lhs.relative_eq(rhs, epsilon, max_relative))
294 }
295 }
296
297 impl<T> AbsDiffEq for GeometryCollection<T>
298 where
299 T: CoordNum + AbsDiffEq<Epsilon = T>,
300 {
301 type Epsilon = T;
302
303 #[inline]
304 fn default_epsilon() -> Self::Epsilon {
305 T::default_epsilon()
306 }
307
308 #[inline]
322 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
323 if self.0.len() != other.0.len() {
324 return false;
325 }
326
327 self.into_iter()
328 .zip(other)
329 .all(|(lhs, rhs)| lhs.abs_diff_eq(rhs, epsilon))
330 }
331 }
332
333 impl<T> UlpsEq for GeometryCollection<T>
334 where
335 T: CoordNum + UlpsEq<Epsilon = T>,
336 {
337 fn default_max_ulps() -> u32 {
338 T::default_max_ulps()
339 }
340
341 fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
342 if self.0.len() != other.0.len() {
343 return false;
344 }
345 self.into_iter()
346 .zip(other)
347 .all(|(lhs, rhs)| lhs.ulps_eq(rhs, epsilon, max_ulps))
348 }
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use alloc::vec;
355
356 use crate::{wkt, GeometryCollection, Point};
357
358 #[test]
359 fn from_vec() {
360 let gc = GeometryCollection::from(vec![Point::new(1i32, 2)]);
361 let p = Point::try_from(gc[0].clone()).unwrap();
362 assert_eq!(p.y(), 2);
363 }
364
365 #[test]
366 fn empty() {
367 let empty = GeometryCollection::<f64>::empty();
368 let empty_2 = wkt! { GEOMETRYCOLLECTION EMPTY };
369 assert_eq!(empty, empty_2);
370 }
371}