geoarrow_array/builder/
rect.rs1use arrow_buffer::NullBufferBuilder;
2use geo_traits::{CoordTrait, RectTrait};
3use geoarrow_schema::BoxType;
4use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
5
6use crate::array::RectArray;
7use crate::builder::SeparatedCoordBufferBuilder;
8use crate::scalar::Rect;
9
10#[derive(Debug)]
14pub struct RectBuilder {
15 pub(crate) data_type: BoxType,
16 pub(crate) lower: SeparatedCoordBufferBuilder,
17 pub(crate) upper: SeparatedCoordBufferBuilder,
18 pub(crate) validity: NullBufferBuilder,
19}
20
21impl RectBuilder {
22 pub fn new(typ: BoxType) -> Self {
24 Self::with_capacity(typ, Default::default())
25 }
26
27 pub fn with_capacity(typ: BoxType, capacity: usize) -> Self {
29 Self {
30 lower: SeparatedCoordBufferBuilder::with_capacity(capacity, typ.dimension()),
31 upper: SeparatedCoordBufferBuilder::with_capacity(capacity, typ.dimension()),
32 validity: NullBufferBuilder::new(capacity),
33 data_type: typ,
34 }
35 }
36
37 pub fn reserve(&mut self, additional: usize) {
43 self.lower.reserve(additional);
44 self.upper.reserve(additional);
45 }
46
47 pub fn reserve_exact(&mut self, additional: usize) {
59 self.lower.reserve_exact(additional);
60 self.upper.reserve_exact(additional);
61 }
62
63 pub fn shrink_to_fit(&mut self) {
65 self.lower.shrink_to_fit();
66 self.upper.shrink_to_fit();
67 }
69
70 pub fn try_new(
82 lower: SeparatedCoordBufferBuilder,
83 upper: SeparatedCoordBufferBuilder,
84 validity: NullBufferBuilder,
85 data_type: BoxType,
86 ) -> GeoArrowResult<Self> {
87 if lower.len() != upper.len() {
88 return Err(GeoArrowError::InvalidGeoArrow(
89 "Lower and upper lengths must match".to_string(),
90 ));
91 }
92 Ok(Self {
93 lower,
94 upper,
95 validity,
96 data_type,
97 })
98 }
99
100 pub fn finish(mut self) -> RectArray {
102 RectArray::new(
103 self.lower.finish(),
104 self.upper.finish(),
105 self.validity.finish(),
106 self.data_type.metadata().clone(),
107 )
108 }
109
110 #[inline]
112 pub fn push_rect(&mut self, value: Option<&impl RectTrait<T = f64>>) {
113 if let Some(value) = value {
114 let min_coord = value.min();
115 let max_coord = value.max();
116
117 self.lower.push_coord(&min_coord);
118 self.upper.push_coord(&max_coord);
119 self.validity.append_non_null()
120 } else {
121 self.lower.push_constant(f64::NAN);
123 self.upper.push_constant(f64::NAN);
124 self.validity.append_null();
125 }
126 }
127
128 #[inline]
130 pub fn push_null(&mut self) {
131 self.push_rect(None::<&Rect>);
132 }
133
134 #[inline]
136 pub fn push_min_max(&mut self, min: &impl CoordTrait<T = f64>, max: &impl CoordTrait<T = f64>) {
137 self.lower.push_coord(min);
138 self.upper.push_coord(max);
139 self.validity.append_non_null()
140 }
141
142 pub fn from_rects<'a>(
144 geoms: impl ExactSizeIterator<Item = &'a (impl RectTrait<T = f64> + 'a)>,
145 typ: BoxType,
146 ) -> Self {
147 let mut mutable_array = Self::with_capacity(typ, geoms.len());
148 geoms
149 .into_iter()
150 .for_each(|rect| mutable_array.push_rect(Some(rect)));
151 mutable_array
152 }
153
154 pub fn from_nullable_rects<'a>(
156 geoms: impl ExactSizeIterator<Item = Option<&'a (impl RectTrait<T = f64> + 'a)>>,
157 typ: BoxType,
158 ) -> Self {
159 let mut mutable_array = Self::with_capacity(typ, geoms.len());
160 geoms
161 .into_iter()
162 .for_each(|maybe_rect| mutable_array.push_rect(maybe_rect));
163 mutable_array
164 }
165}