iron_shapes/
multi_polygon.rs1use crate::CoordinateType;
9
10use crate::point::Point;
11use crate::polygon::Polygon;
12
13pub use crate::traits::{BoundingBox, DoubledOrientedArea, MapPointwise, WindingNumber};
14
15use crate::edge::Edge;
16use crate::prelude::Rect;
17use crate::traits::{TryBoundingBox, TryIntoBoundingBox};
18use std::iter::FromIterator;
19
20#[derive(Default, Clone, Debug, Hash)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub struct MultiPolygon<T> {
25 pub polygons: Vec<Polygon<T>>,
27}
28
29impl<T> MultiPolygon<T> {
30 pub fn new() -> Self {
32 Self { polygons: vec![] }
33 }
34
35 pub fn from_polygons(polygons: Vec<Polygon<T>>) -> Self {
37 MultiPolygon { polygons }
38 }
39
40 pub fn len(&self) -> usize {
42 self.polygons.len()
43 }
44
45 pub fn is_empty(&self) -> bool {
47 self.polygons.is_empty()
48 }
49
50 pub fn insert(&mut self, polygon: Polygon<T>) {
52 self.polygons.push(polygon)
53 }
54}
55
56impl<T: Copy> MultiPolygon<T> {
57 pub fn all_edges_iter(&self) -> impl Iterator<Item = Edge<T>> + '_ {
59 self.polygons.iter().flat_map(|p| p.all_edges_iter())
60 }
61}
62
63impl<T> WindingNumber<T> for MultiPolygon<T>
64where
65 T: CoordinateType,
66{
67 fn winding_number(&self, point: Point<T>) -> isize {
68 self.polygons.iter().map(|p| p.winding_number(point)).sum()
69 }
70}
71
72impl<T> MapPointwise<T> for MultiPolygon<T>
73where
74 T: CoordinateType,
75{
76 fn transform<F: Fn(Point<T>) -> Point<T>>(&self, tf: F) -> Self {
77 MultiPolygon::from_polygons(self.polygons.iter().map(|p| p.transform(&tf)).collect())
78 }
79}
80
81impl<T, IP: Into<Polygon<T>>> From<IP> for MultiPolygon<T> {
82 fn from(x: IP) -> Self {
83 MultiPolygon::from_polygons(vec![x.into()])
84 }
85}
86
87impl<T> From<Vec<Polygon<T>>> for MultiPolygon<T> {
88 fn from(polygons: Vec<Polygon<T>>) -> Self {
89 MultiPolygon { polygons }
90 }
91}
92
93impl<T, IP: Into<Polygon<T>>> FromIterator<IP> for MultiPolygon<T> {
94 fn from_iter<I: IntoIterator<Item = IP>>(iter: I) -> Self {
95 MultiPolygon::from_polygons(iter.into_iter().map(|p| p.into()).collect())
96 }
97}
98
99impl<T> IntoIterator for MultiPolygon<T> {
100 type Item = Polygon<T>;
101 type IntoIter = ::std::vec::IntoIter<Polygon<T>>;
102
103 fn into_iter(self) -> Self::IntoIter {
104 self.polygons.into_iter()
105 }
106}
107
108impl<T: CoordinateType> TryBoundingBox<T> for MultiPolygon<T> {
109 fn try_bounding_box(&self) -> Option<Rect<T>> {
110 self.polygons.iter().try_into_bounding_box()
111 }
112}
113
114