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 try_new(
75 lower: SeparatedCoordBufferBuilder,
76 upper: SeparatedCoordBufferBuilder,
77 validity: NullBufferBuilder,
78 data_type: BoxType,
79 ) -> GeoArrowResult<Self> {
80 if lower.len() != upper.len() {
81 return Err(GeoArrowError::InvalidGeoArrow(
82 "Lower and upper lengths must match".to_string(),
83 ));
84 }
85 Ok(Self {
86 lower,
87 upper,
88 validity,
89 data_type,
90 })
91 }
92
93 pub fn finish(mut self) -> RectArray {
95 RectArray::new(
96 self.lower.finish(),
97 self.upper.finish(),
98 self.validity.finish(),
99 self.data_type.metadata().clone(),
100 )
101 }
102
103 #[inline]
105 pub fn push_rect(&mut self, value: Option<&impl RectTrait<T = f64>>) {
106 if let Some(value) = value {
107 let min_coord = value.min();
108 let max_coord = value.max();
109
110 self.lower.push_coord(&min_coord);
111 self.upper.push_coord(&max_coord);
112 self.validity.append_non_null()
113 } else {
114 self.lower.push_constant(f64::NAN);
116 self.upper.push_constant(f64::NAN);
117 self.validity.append_null();
118 }
119 }
120
121 #[inline]
123 pub fn push_null(&mut self) {
124 self.push_rect(None::<&Rect>);
125 }
126
127 #[inline]
129 pub fn push_min_max(&mut self, min: &impl CoordTrait<T = f64>, max: &impl CoordTrait<T = f64>) {
130 self.lower.push_coord(min);
131 self.upper.push_coord(max);
132 self.validity.append_non_null()
133 }
134
135 pub fn from_rects<'a>(
137 geoms: impl ExactSizeIterator<Item = &'a (impl RectTrait<T = f64> + 'a)>,
138 typ: BoxType,
139 ) -> Self {
140 let mut mutable_array = Self::with_capacity(typ, geoms.len());
141 geoms
142 .into_iter()
143 .for_each(|rect| mutable_array.push_rect(Some(rect)));
144 mutable_array
145 }
146
147 pub fn from_nullable_rects<'a>(
149 geoms: impl ExactSizeIterator<Item = Option<&'a (impl RectTrait<T = f64> + 'a)>>,
150 typ: BoxType,
151 ) -> Self {
152 let mut mutable_array = Self::with_capacity(typ, geoms.len());
153 geoms
154 .into_iter()
155 .for_each(|maybe_rect| mutable_array.push_rect(maybe_rect));
156 mutable_array
157 }
158}