geoarrow_array/capacity/
polygon.rs1use std::ops::Add;
2
3use geo_traits::{GeometryTrait, GeometryType, LineStringTrait, PolygonTrait, RectTrait};
4use geoarrow_schema::Dimension;
5use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
6
7use crate::util::GeometryTypeName;
8
9#[derive(Debug, Clone, Copy)]
13pub struct PolygonCapacity {
14 pub(crate) coord_capacity: usize,
15 pub(crate) ring_capacity: usize,
16 pub(crate) geom_capacity: usize,
17}
18
19impl PolygonCapacity {
20 pub fn new(coord_capacity: usize, ring_capacity: usize, geom_capacity: usize) -> Self {
22 Self {
23 coord_capacity,
24 ring_capacity,
25 geom_capacity,
26 }
27 }
28
29 pub fn new_empty() -> Self {
31 Self::new(0, 0, 0)
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.coord_capacity == 0 && self.ring_capacity == 0 && self.geom_capacity == 0
37 }
38
39 pub fn coord_capacity(&self) -> usize {
41 self.coord_capacity
42 }
43
44 pub fn ring_capacity(&self) -> usize {
46 self.ring_capacity
47 }
48
49 pub fn geom_capacity(&self) -> usize {
51 self.geom_capacity
52 }
53
54 #[inline]
56 pub fn add_polygon<'a>(&mut self, polygon: Option<&'a (impl PolygonTrait + 'a)>) {
57 self.geom_capacity += 1;
58 if let Some(polygon) = polygon {
59 let num_interiors = polygon.num_interiors();
61 self.ring_capacity += num_interiors + 1;
62
63 if let Some(exterior) = polygon.exterior() {
65 self.coord_capacity += exterior.num_coords();
66 }
67
68 for int_ring in polygon.interiors() {
69 self.coord_capacity += int_ring.num_coords();
70 }
71 }
72 }
73
74 #[inline]
76 pub fn add_rect<'a>(&mut self, rect: Option<&'a (impl RectTrait + 'a)>) {
77 self.geom_capacity += 1;
78 if rect.is_some() {
79 self.ring_capacity += 1;
81 self.coord_capacity += 5;
83 }
84 }
85
86 #[inline]
90 pub fn add_geometry(&mut self, value: Option<&impl GeometryTrait>) -> GeoArrowResult<()> {
91 if let Some(geom) = value {
92 match geom.as_type() {
93 GeometryType::Polygon(g) => self.add_polygon(Some(g)),
94 GeometryType::Rect(g) => self.add_rect(Some(g)),
95 gt => {
96 return Err(GeoArrowError::IncorrectGeometryType(format!(
97 "Expected polygon, got {}",
98 gt.name()
99 )));
100 }
101 }
102 } else {
103 self.geom_capacity += 1;
104 };
105 Ok(())
106 }
107
108 pub fn from_polygons<'a>(
110 geoms: impl Iterator<Item = Option<&'a (impl PolygonTrait + 'a)>>,
111 ) -> Self {
112 let mut counter = Self::new_empty();
113 for maybe_polygon in geoms.into_iter() {
114 counter.add_polygon(maybe_polygon);
115 }
116 counter
117 }
118
119 pub fn from_rects<'a>(geoms: impl Iterator<Item = Option<&'a (impl RectTrait + 'a)>>) -> Self {
121 let mut counter = Self::new_empty();
122 for maybe_rect in geoms.into_iter() {
123 counter.add_rect(maybe_rect);
124 }
125 counter
126 }
127
128 pub fn from_geometries<'a>(
130 geoms: impl Iterator<Item = Option<&'a (impl GeometryTrait + 'a)>>,
131 ) -> GeoArrowResult<Self> {
132 let mut counter = Self::new_empty();
133 for g in geoms.into_iter() {
134 counter.add_geometry(g)?;
135 }
136 Ok(counter)
137 }
138
139 pub fn num_bytes(&self, dim: Dimension) -> usize {
141 let offsets_byte_width = 4;
142 let num_offsets = self.geom_capacity + self.ring_capacity;
143 (offsets_byte_width * num_offsets) + (self.coord_capacity * dim.size() * 8)
144 }
145}
146
147impl Default for PolygonCapacity {
148 fn default() -> Self {
149 Self::new_empty()
150 }
151}
152
153impl Add for PolygonCapacity {
154 type Output = Self;
155
156 fn add(self, rhs: Self) -> Self::Output {
157 let coord_capacity = self.coord_capacity + rhs.coord_capacity;
158 let ring_capacity = self.ring_capacity + rhs.ring_capacity;
159 let geom_capacity = self.geom_capacity + rhs.geom_capacity;
160 Self::new(coord_capacity, ring_capacity, geom_capacity)
161 }
162}