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 iter(&self) -> impl Iterator<Item = &Polygon<T>> {
116 self.0.iter()
117 }
118
119 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Polygon<T>> {
120 self.0.iter_mut()
121 }
122}
123
124#[cfg(any(feature = "approx", test))]
125mod approx_integration {
126 use super::*;
127 use approx::{AbsDiffEq, RelativeEq, UlpsEq};
128
129 impl<T> RelativeEq for MultiPolygon<T>
130 where
131 T: CoordNum + RelativeEq<Epsilon = T>,
132 {
133 #[inline]
134 fn default_max_relative() -> Self::Epsilon {
135 T::default_max_relative()
136 }
137
138 #[inline]
154 fn relative_eq(
155 &self,
156 other: &Self,
157 epsilon: Self::Epsilon,
158 max_relative: Self::Epsilon,
159 ) -> bool {
160 if self.0.len() != other.0.len() {
161 return false;
162 }
163
164 let mut mp_zipper = self.iter().zip(other.iter());
165 mp_zipper.all(|(lhs, rhs)| lhs.relative_eq(rhs, epsilon, max_relative))
166 }
167 }
168
169 impl<T> AbsDiffEq for MultiPolygon<T>
170 where
171 T: CoordNum + AbsDiffEq<Epsilon = T>,
172 {
173 type Epsilon = T;
174
175 #[inline]
176 fn default_epsilon() -> Self::Epsilon {
177 T::default_epsilon()
178 }
179
180 #[inline]
196 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
197 if self.0.len() != other.0.len() {
198 return false;
199 }
200
201 let mut mp_zipper = self.into_iter().zip(other);
202 mp_zipper.all(|(lhs, rhs)| lhs.abs_diff_eq(rhs, epsilon))
203 }
204 }
205
206 impl<T> UlpsEq for MultiPolygon<T>
207 where
208 T: CoordNum + UlpsEq<Epsilon = T>,
209 {
210 fn default_max_ulps() -> u32 {
211 T::default_max_ulps()
212 }
213
214 fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
215 if self.0.len() != other.0.len() {
216 return false;
217 }
218 let mut mp_zipper = self.into_iter().zip(other);
219 mp_zipper.all(|(lhs, rhs)| lhs.ulps_eq(rhs, epsilon, max_ulps))
220 }
221 }
222}
223
224#[cfg(any(
225 feature = "rstar_0_8",
226 feature = "rstar_0_9",
227 feature = "rstar_0_10",
228 feature = "rstar_0_11",
229 feature = "rstar_0_12"
230))]
231macro_rules! impl_rstar_multi_polygon {
232 ($rstar:ident) => {
233 impl<T> $rstar::RTreeObject for MultiPolygon<T>
234 where
235 T: ::num_traits::Float + ::$rstar::RTreeNum,
236 {
237 type Envelope = ::$rstar::AABB<$crate::Point<T>>;
238 fn envelope(&self) -> Self::Envelope {
239 use ::$rstar::Envelope;
240 self.iter()
241 .map(|p| p.envelope())
242 .fold(::$rstar::AABB::new_empty(), |a, b| a.merged(&b))
243 }
244 }
245 };
246}
247#[cfg(feature = "rstar_0_8")]
248impl_rstar_multi_polygon!(rstar_0_8);
249#[cfg(feature = "rstar_0_9")]
250impl_rstar_multi_polygon!(rstar_0_9);
251#[cfg(feature = "rstar_0_10")]
252impl_rstar_multi_polygon!(rstar_0_10);
253#[cfg(feature = "rstar_0_11")]
254impl_rstar_multi_polygon!(rstar_0_11);
255#[cfg(feature = "rstar_0_12")]
256impl_rstar_multi_polygon!(rstar_0_12);
257
258#[cfg(test)]
259mod test {
260 use super::*;
261 use crate::polygon;
262
263 #[test]
264 fn test_iter() {
265 let multi = MultiPolygon::new(vec![
266 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
267 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
268 ]);
269
270 let mut first = true;
271 for p in &multi {
272 if first {
273 assert_eq!(
274 p,
275 &polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)]
276 );
277 first = false;
278 } else {
279 assert_eq!(
280 p,
281 &polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)]
282 );
283 }
284 }
285
286 first = true;
288 for p in &multi {
289 if first {
290 assert_eq!(
291 p,
292 &polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)]
293 );
294 first = false;
295 } else {
296 assert_eq!(
297 p,
298 &polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)]
299 );
300 }
301 }
302 }
303
304 #[cfg(feature = "multithreading")]
305 #[test]
306 fn test_par_iter() {
307 let multi = MultiPolygon::new(vec![
308 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
309 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
310 ]);
311 let mut multimut = MultiPolygon::new(vec![
312 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
313 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
314 ]);
315 multi.par_iter().for_each(|_p| ());
316 let _ = &multimut.par_iter_mut().for_each(|_p| ());
317 let _ = &multi.into_par_iter().for_each(|_p| ());
318 let _ = &mut multimut.par_iter_mut().for_each(|_p| ());
319 }
320 #[test]
321 fn test_iter_mut() {
322 let mut multi = MultiPolygon::new(vec![
323 polygon![(x: 0, y: 0), (x: 2, y: 0), (x: 1, y: 2), (x:0, y:0)],
324 polygon![(x: 10, y: 10), (x: 12, y: 10), (x: 11, y: 12), (x:10, y:10)],
325 ]);
326
327 for poly in &mut multi {
328 poly.exterior_mut(|exterior| {
329 for coord in exterior {
330 coord.x += 1;
331 coord.y += 1;
332 }
333 });
334 }
335
336 for poly in multi.iter_mut() {
337 poly.exterior_mut(|exterior| {
338 for coord in exterior {
339 coord.x += 1;
340 coord.y += 1;
341 }
342 });
343 }
344
345 let mut first = true;
346 for p in &multi {
347 if first {
348 assert_eq!(
349 p,
350 &polygon![(x: 2, y: 2), (x: 4, y: 2), (x: 3, y: 4), (x:2, y:2)]
351 );
352 first = false;
353 } else {
354 assert_eq!(
355 p,
356 &polygon![(x: 12, y: 12), (x: 14, y: 12), (x: 13, y: 14), (x:12, y:12)]
357 );
358 }
359 }
360 }
361}