1use crate::{CoordNum, Polygon};
2
3use alloc::vec;
4use alloc::vec::Vec;
5
6use core::iter::FromIterator;
7#[cfg(feature = "multithreading")]
8use rayon::prelude::*;
9
10#[derive(Eq, PartialEq, Clone, Hash)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32pub struct MultiPolygon<T: CoordNum = f64>(pub Vec<Polygon<T>>);
33
34impl<T: CoordNum, IP: Into<Polygon<T>>> From<IP> for MultiPolygon<T> {
35 fn from(x: IP) -> Self {
36 Self(vec![x.into()])
37 }
38}
39
40impl<T: CoordNum, IP: Into<Polygon<T>>> From<Vec<IP>> for MultiPolygon<T> {
41 fn from(x: Vec<IP>) -> Self {
42 Self(x.into_iter().map(|p| p.into()).collect())
43 }
44}
45
46impl<T: CoordNum, IP: Into<Polygon<T>>> FromIterator<IP> for MultiPolygon<T> {
47 fn from_iter<I: IntoIterator<Item = IP>>(iter: I) -> Self {
48 Self(iter.into_iter().map(|p| p.into()).collect())
49 }
50}
51
52impl<T: CoordNum> IntoIterator for MultiPolygon<T> {
53 type Item = Polygon<T>;
54 type IntoIter = ::alloc::vec::IntoIter<Polygon<T>>;
55
56 fn into_iter(self) -> Self::IntoIter {
57 self.0.into_iter()
58 }
59}
60
61impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon<T> {
62 type Item = &'a Polygon<T>;
63 type IntoIter = ::alloc::slice::Iter<'a, Polygon<T>>;
64
65 fn into_iter(self) -> Self::IntoIter {
66 (self.0).iter()
67 }
68}
69
70impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPolygon<T> {
71 type Item = &'a mut Polygon<T>;
72 type IntoIter = ::alloc::slice::IterMut<'a, Polygon<T>>;
73
74 fn into_iter(self) -> Self::IntoIter {
75 (self.0).iter_mut()
76 }
77}
78
79#[cfg(feature = "multithreading")]
80impl<T: CoordNum + Send> IntoParallelIterator for MultiPolygon<T> {
81 type Item = Polygon<T>;
82 type Iter = rayon::vec::IntoIter<Polygon<T>>;
83
84 fn into_par_iter(self) -> Self::Iter {
85 self.0.into_par_iter()
86 }
87}
88
89#[cfg(feature = "multithreading")]
90impl<'a, T: CoordNum + Sync> IntoParallelIterator for &'a MultiPolygon<T> {
91 type Item = &'a Polygon<T>;
92 type Iter = rayon::slice::Iter<'a, Polygon<T>>;
93
94 fn into_par_iter(self) -> Self::Iter {
95 self.0.par_iter()
96 }
97}
98
99#[cfg(feature = "multithreading")]
100impl<'a, T: CoordNum + Send + Sync> IntoParallelIterator for &'a mut MultiPolygon<T> {
101 type Item = &'a mut Polygon<T>;
102 type Iter = rayon::slice::IterMut<'a, Polygon<T>>;
103
104 fn into_par_iter(self) -> Self::Iter {
105 self.0.par_iter_mut()
106 }
107}
108
109impl<T: CoordNum> MultiPolygon<T> {
110 pub fn new(value: Vec<Polygon<T>>) -> Self {
112 Self(value)
113 }
114
115 pub fn empty() -> Self {
117 Self(Vec::new())
118 }
119
120 pub fn iter(&self) -> impl Iterator<Item = &Polygon<T>> {
121 self.0.iter()
122 }
123
124 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Polygon<T>> {
125 self.0.iter_mut()
126 }
127}
128
129#[cfg(any(feature = "approx", test))]
130mod approx_integration {
131 use super::*;
132 use approx::{AbsDiffEq, RelativeEq, UlpsEq};
133
134 impl<T> RelativeEq for MultiPolygon<T>
135 where
136 T: CoordNum + RelativeEq<Epsilon = T>,
137 {
138 #[inline]
139 fn default_max_relative() -> Self::Epsilon {
140 T::default_max_relative()
141 }
142
143 #[inline]
159 fn relative_eq(
160 &self,
161 other: &Self,
162 epsilon: Self::Epsilon,
163 max_relative: Self::Epsilon,
164 ) -> bool {
165 if self.0.len() != other.0.len() {
166 return false;
167 }
168
169 let mut mp_zipper = self.iter().zip(other.iter());
170 mp_zipper.all(|(lhs, rhs)| lhs.relative_eq(rhs, epsilon, max_relative))
171 }
172 }
173
174 impl<T> AbsDiffEq for MultiPolygon<T>
175 where
176 T: CoordNum + AbsDiffEq<Epsilon = T>,
177 {
178 type Epsilon = T;
179
180 #[inline]
181 fn default_epsilon() -> Self::Epsilon {
182 T::default_epsilon()
183 }
184
185 #[inline]
201 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
202 if self.0.len() != other.0.len() {
203 return false;
204 }
205
206 let mut mp_zipper = self.into_iter().zip(other);
207 mp_zipper.all(|(lhs, rhs)| lhs.abs_diff_eq(rhs, epsilon))
208 }
209 }
210
211 impl<T> UlpsEq for MultiPolygon<T>
212 where
213 T: CoordNum + UlpsEq<Epsilon = T>,
214 {
215 fn default_max_ulps() -> u32 {
216 T::default_max_ulps()
217 }
218
219 fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
220 if self.0.len() != other.0.len() {
221 return false;
222 }
223 let mut mp_zipper = self.into_iter().zip(other);
224 mp_zipper.all(|(lhs, rhs)| lhs.ulps_eq(rhs, epsilon, max_ulps))
225 }
226 }
227}
228
229#[cfg(any(
230 feature = "rstar_0_8",
231 feature = "rstar_0_9",
232 feature = "rstar_0_10",
233 feature = "rstar_0_11",
234 feature = "rstar_0_12"
235))]
236macro_rules! impl_rstar_multi_polygon {
237 ($rstar:ident) => {
238 impl<T> $rstar::RTreeObject for MultiPolygon<T>
239 where
240 T: ::num_traits::Float + ::$rstar::RTreeNum,
241 {
242 type Envelope = ::$rstar::AABB<$crate::Point<T>>;
243 fn envelope(&self) -> Self::Envelope {
244 use ::$rstar::Envelope;
245 self.iter()
246 .map(|p| p.envelope())
247 .fold(::$rstar::AABB::new_empty(), |a, b| a.merged(&b))
248 }
249 }
250 };
251}
252#[cfg(feature = "rstar_0_8")]
253impl_rstar_multi_polygon!(rstar_0_8);
254#[cfg(feature = "rstar_0_9")]
255impl_rstar_multi_polygon!(rstar_0_9);
256#[cfg(feature = "rstar_0_10")]
257impl_rstar_multi_polygon!(rstar_0_10);
258#[cfg(feature = "rstar_0_11")]
259impl_rstar_multi_polygon!(rstar_0_11);
260#[cfg(feature = "rstar_0_12")]
261impl_rstar_multi_polygon!(rstar_0_12);
262
263#[cfg(test)]
264mod test {
265 use super::*;
266 use crate::{polygon, wkt};
267
268 #[test]
269 fn test_iter() {
270 let multi = MultiPolygon::new(vec![
271 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
272 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
273 ]);
274
275 let mut first = true;
276 for p in &multi {
277 if first {
278 assert_eq!(
279 p,
280 &polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)]
281 );
282 first = false;
283 } else {
284 assert_eq!(
285 p,
286 &polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)]
287 );
288 }
289 }
290
291 first = true;
293 for p in &multi {
294 if first {
295 assert_eq!(
296 p,
297 &polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)]
298 );
299 first = false;
300 } else {
301 assert_eq!(
302 p,
303 &polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)]
304 );
305 }
306 }
307 }
308
309 #[cfg(feature = "multithreading")]
310 #[test]
311 fn test_par_iter() {
312 let multi = MultiPolygon::new(vec![
313 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
314 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
315 ]);
316 let mut multimut = MultiPolygon::new(vec![
317 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
318 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
319 ]);
320 multi.par_iter().for_each(|_p| ());
321 let _ = &multimut.par_iter_mut().for_each(|_p| ());
322 let _ = &multi.into_par_iter().for_each(|_p| ());
323 let _ = &mut multimut.par_iter_mut().for_each(|_p| ());
324 }
325 #[test]
326 fn test_iter_mut() {
327 let mut multi = MultiPolygon::new(vec![
328 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
329 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
330 ]);
331
332 for poly in &mut multi {
333 poly.exterior_mut(|exterior| {
334 for coord in exterior {
335 coord.x += 1;
336 coord.y += 1;
337 }
338 });
339 }
340
341 for poly in multi.iter_mut() {
342 poly.exterior_mut(|exterior| {
343 for coord in exterior {
344 coord.x += 1;
345 coord.y += 1;
346 }
347 });
348 }
349
350 let mut first = true;
351 for p in &multi {
352 if first {
353 assert_eq!(
354 p,
355 &polygon![(x: 2, y: 2), (x: 4, y: 2), (x: 3, y: 4), (x:2, y:2)]
356 );
357 first = false;
358 } else {
359 assert_eq!(
360 p,
361 &polygon![(x: 12, y: 12), (x: 14, y: 12), (x: 13, y: 14), (x:12, y:12)]
362 );
363 }
364 }
365 }
366
367 #[test]
368 fn empty() {
369 let empty = MultiPolygon::<f64>::empty();
370 let empty_2 = wkt! { MULTIPOLYGON EMPTY };
371 assert_eq!(empty, empty_2);
372 }
373}