geoarrow_array/capacity/
multipolygon.rs1use std::ops::{Add, AddAssign};
2
3use geo_traits::{GeometryTrait, GeometryType, LineStringTrait, MultiPolygonTrait, PolygonTrait};
4use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
5
6use crate::capacity::PolygonCapacity;
7use crate::util::GeometryTypeName;
8
9#[derive(Debug, Clone, Copy)]
13pub struct MultiPolygonCapacity {
14 pub(crate) coord_capacity: usize,
15 pub(crate) ring_capacity: usize,
16 pub(crate) polygon_capacity: usize,
17 pub(crate) geom_capacity: usize,
18}
19
20impl MultiPolygonCapacity {
21 pub fn new(
23 coord_capacity: usize,
24 ring_capacity: usize,
25 polygon_capacity: usize,
26 geom_capacity: usize,
27 ) -> Self {
28 Self {
29 coord_capacity,
30 ring_capacity,
31 polygon_capacity,
32 geom_capacity,
33 }
34 }
35
36 pub fn new_empty() -> Self {
38 Self::new(0, 0, 0, 0)
39 }
40
41 pub fn is_empty(&self) -> bool {
43 self.coord_capacity == 0
44 && self.ring_capacity == 0
45 && self.polygon_capacity == 0
46 && self.geom_capacity == 0
47 }
48
49 pub fn coord_capacity(&self) -> usize {
51 self.coord_capacity
52 }
53
54 pub fn ring_capacity(&self) -> usize {
56 self.ring_capacity
57 }
58
59 pub fn polygon_capacity(&self) -> usize {
61 self.polygon_capacity
62 }
63
64 pub fn geom_capacity(&self) -> usize {
66 self.geom_capacity
67 }
68
69 #[inline]
71 pub fn add_polygon<'a>(&mut self, polygon: Option<&'a (impl PolygonTrait + 'a)>) {
72 self.geom_capacity += 1;
73 if let Some(polygon) = polygon {
74 self.polygon_capacity += 1;
76
77 let num_interiors = polygon.num_interiors();
79 self.ring_capacity += num_interiors + 1;
80
81 if let Some(exterior) = polygon.exterior() {
83 self.coord_capacity += exterior.num_coords();
84 }
85
86 for int_ring in polygon.interiors() {
87 self.coord_capacity += int_ring.num_coords();
88 }
89 }
90 }
91
92 #[inline]
94 pub fn add_multi_polygon<'a>(
95 &mut self,
96 multi_polygon: Option<&'a (impl MultiPolygonTrait + 'a)>,
97 ) {
98 self.geom_capacity += 1;
99
100 if let Some(multi_polygon) = multi_polygon {
101 let num_polygons = multi_polygon.num_polygons();
103 self.polygon_capacity += num_polygons;
104
105 for polygon in multi_polygon.polygons() {
106 self.ring_capacity += polygon.num_interiors() + 1;
108
109 if let Some(exterior) = polygon.exterior() {
111 self.coord_capacity += exterior.num_coords();
112 }
113
114 for int_ring in polygon.interiors() {
115 self.coord_capacity += int_ring.num_coords();
116 }
117 }
118 }
119 }
120
121 #[inline]
125 pub fn add_geometry(&mut self, value: Option<&impl GeometryTrait>) -> GeoArrowResult<()> {
126 if let Some(geom) = value {
127 match geom.as_type() {
128 GeometryType::Polygon(g) => self.add_polygon(Some(g)),
129 GeometryType::MultiPolygon(g) => self.add_multi_polygon(Some(g)),
130 gt => {
131 return Err(GeoArrowError::IncorrectGeometryType(format!(
132 "Expected MultiPolygon, got {}",
133 gt.name()
134 )));
135 }
136 }
137 } else {
138 self.geom_capacity += 1;
139 };
140 Ok(())
141 }
142
143 pub fn from_multi_polygons<'a>(
145 geoms: impl Iterator<Item = Option<&'a (impl MultiPolygonTrait + 'a)>>,
146 ) -> Self {
147 let mut counter = Self::new_empty();
148 for maybe_multi_polygon in geoms.into_iter() {
149 counter.add_multi_polygon(maybe_multi_polygon);
150 }
151 counter
152 }
153
154 pub fn from_geometries<'a>(
156 geoms: impl Iterator<Item = Option<&'a (impl GeometryTrait + 'a)>>,
157 ) -> GeoArrowResult<Self> {
158 let mut counter = Self::new_empty();
159 for g in geoms.into_iter() {
160 counter.add_geometry(g)?;
161 }
162 Ok(counter)
163 }
164
165 pub fn num_bytes(&self) -> usize {
167 let offsets_byte_width = 4;
168 let num_offsets = self.geom_capacity + self.polygon_capacity + self.ring_capacity;
169 (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8)
170 }
171}
172
173impl Default for MultiPolygonCapacity {
174 fn default() -> Self {
175 Self::new_empty()
176 }
177}
178
179impl Add for MultiPolygonCapacity {
180 type Output = Self;
181
182 fn add(self, rhs: Self) -> Self::Output {
183 let coord_capacity = self.coord_capacity + rhs.coord_capacity;
184 let ring_capacity = self.ring_capacity + rhs.ring_capacity;
185 let polygon_capacity = self.polygon_capacity + rhs.polygon_capacity;
186 let geom_capacity = self.geom_capacity + rhs.geom_capacity;
187 Self::new(
188 coord_capacity,
189 ring_capacity,
190 polygon_capacity,
191 geom_capacity,
192 )
193 }
194}
195
196impl AddAssign for MultiPolygonCapacity {
197 fn add_assign(&mut self, rhs: Self) {
198 self.coord_capacity += rhs.coord_capacity;
199 self.ring_capacity += rhs.ring_capacity;
200 self.polygon_capacity += rhs.polygon_capacity;
201 self.geom_capacity += rhs.geom_capacity;
202 }
203}
204
205impl AddAssign<PolygonCapacity> for MultiPolygonCapacity {
206 fn add_assign(&mut self, rhs: PolygonCapacity) {
207 self.coord_capacity += rhs.coord_capacity();
208 self.ring_capacity += rhs.ring_capacity();
209 self.polygon_capacity += rhs.geom_capacity();
210 self.geom_capacity += rhs.geom_capacity();
211 }
212}