From 40fff8ef4ea6abb082a94c086bed8e6033fb28c2 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Sun, 21 Jul 2024 21:38:00 -0400 Subject: [PATCH] infer dimensions in capacity --- src/algorithm/geo/minimum_rotated_rect.rs | 16 ++++++- src/algorithm/native/cast.rs | 19 +++++++-- src/array/geometrycollection/array.rs | 2 +- src/array/geometrycollection/capacity.rs | 6 +-- src/array/linestring/array.rs | 10 +++-- src/array/linestring/builder.rs | 2 +- src/array/linestring/capacity.rs | 30 +++++++++---- src/array/mixed/array.rs | 2 +- src/array/mixed/capacity.rs | 40 ++++++++--------- src/array/mod.rs | 2 +- src/array/multilinestring/array.rs | 5 ++- src/array/multilinestring/builder.rs | 2 +- src/array/multilinestring/capacity.rs | 47 +++++++++++++------- src/array/multipoint/array.rs | 10 +++-- src/array/multipoint/builder.rs | 2 +- src/array/multipoint/capacity.rs | 45 ++++++++++++++------ src/array/multipolygon/array.rs | 5 ++- src/array/multipolygon/builder.rs | 1 + src/array/multipolygon/capacity.rs | 52 ++++++++++++----------- src/array/point/builder.rs | 2 +- src/array/point/capacity.rs | 36 ++++++++++++---- src/array/point/mod.rs | 2 +- src/array/polygon/array.rs | 10 +++-- src/array/polygon/builder.rs | 2 +- src/array/polygon/capacity.rs | 41 +++++++++++++----- src/io/geozero/array/linestring.rs | 6 ++- src/io/geozero/array/multilinestring.rs | 10 +++-- src/io/geozero/array/multipoint.rs | 8 ++-- src/io/geozero/array/multipolygon.rs | 12 +++--- src/io/geozero/array/polygon.rs | 8 ++-- 30 files changed, 286 insertions(+), 149 deletions(-) diff --git a/src/algorithm/geo/minimum_rotated_rect.rs b/src/algorithm/geo/minimum_rotated_rect.rs index 4b0c340df..59efef6c8 100644 --- a/src/algorithm/geo/minimum_rotated_rect.rs +++ b/src/algorithm/geo/minimum_rotated_rect.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use crate::array::polygon::PolygonCapacity; use crate::array::*; use crate::chunked_array::{ChunkedGeometryArray, ChunkedGeometryArrayTrait, ChunkedPolygonArray}; @@ -52,7 +54,12 @@ impl MinimumRotatedRect for PointArray<2> { // Each output polygon has exactly 5 coordinates let coord_capacity = ring_capacity * 5; - let capacity = PolygonCapacity::new(coord_capacity, ring_capacity, geom_capacity); + let capacity = PolygonCapacity::new( + coord_capacity, + ring_capacity, + geom_capacity, + HashSet::from_iter([2]), + ); let mut output_array = PolygonBuilder::with_capacity(capacity); @@ -84,7 +91,12 @@ macro_rules! iter_geo_impl { // Each output polygon has exactly 5 coordinates let coord_capacity = ring_capacity * 5; - let capacity = PolygonCapacity::new(coord_capacity, ring_capacity, geom_capacity); + let capacity = PolygonCapacity::new( + coord_capacity, + ring_capacity, + geom_capacity, + HashSet::from_iter([2]), + ); let mut output_array = PolygonBuilder::with_capacity(capacity); diff --git a/src/algorithm/native/cast.rs b/src/algorithm/native/cast.rs index e1d8ad0f7..f821a1a7f 100644 --- a/src/algorithm/native/cast.rs +++ b/src/algorithm/native/cast.rs @@ -5,6 +5,7 @@ //! todo: have a set of "fast cast" functions, where you first try to fast cast and fall back to //! slower copies if necessary. Can check that the coord type of the input and output is the same. +use std::collections::HashSet; use std::sync::Arc; use arrow_array::OffsetSizeTrait; @@ -77,8 +78,11 @@ impl Cast for PointArray<2> { Ok(Arc::new(builder.finish())) } MultiPoint(ct, Dimension::XY) => { - let capacity = - MultiPointCapacity::new(self.buffer_lengths(), self.buffer_lengths()); + let capacity = MultiPointCapacity::new( + self.buffer_lengths(), + self.buffer_lengths(), + HashSet::from_iter([2]), + ); let mut builder = MultiPointBuilder::::with_capacity_and_options( capacity, *ct, @@ -89,8 +93,11 @@ impl Cast for PointArray<2> { Ok(Arc::new(builder.finish())) } LargeMultiPoint(ct, Dimension::XY) => { - let capacity = - MultiPointCapacity::new(self.buffer_lengths(), self.buffer_lengths()); + let capacity = MultiPointCapacity::new( + self.buffer_lengths(), + self.buffer_lengths(), + HashSet::from_iter([2]), + ); let mut builder = MultiPointBuilder::::with_capacity_and_options( capacity, *ct, @@ -510,6 +517,7 @@ impl Cast for MultiLineStringArray { let capacity = LineStringCapacity { coord_capacity: existing_capacity.coord_capacity, geom_capacity: existing_capacity.ring_capacity, + dimensions: HashSet::from_iter([2]), }; let mut builder = LineStringBuilder::::with_capacity_and_options( capacity, @@ -530,6 +538,7 @@ impl Cast for MultiLineStringArray { let capacity = LineStringCapacity { coord_capacity: existing_capacity.coord_capacity, geom_capacity: existing_capacity.ring_capacity, + dimensions: HashSet::from_iter([2]), }; let mut builder = LineStringBuilder::::with_capacity_and_options( capacity, @@ -621,6 +630,7 @@ impl Cast for MultiPolygonArray { coord_capacity: existing_capacity.coord_capacity, ring_capacity: existing_capacity.ring_capacity, geom_capacity: existing_capacity.polygon_capacity, + dimensions: HashSet::from_iter([2]), }; let mut builder = PolygonBuilder::::with_capacity_and_options( capacity, @@ -642,6 +652,7 @@ impl Cast for MultiPolygonArray { coord_capacity: existing_capacity.coord_capacity, ring_capacity: existing_capacity.ring_capacity, geom_capacity: existing_capacity.polygon_capacity, + dimensions: HashSet::from_iter([2]), }; let mut builder = PolygonBuilder::::with_capacity_and_options( capacity, diff --git a/src/array/geometrycollection/array.rs b/src/array/geometrycollection/array.rs index d1cb40406..2c31a1be0 100644 --- a/src/array/geometrycollection/array.rs +++ b/src/array/geometrycollection/array.rs @@ -87,7 +87,7 @@ impl GeometryCollectionArray { /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/geometrycollection/capacity.rs b/src/array/geometrycollection/capacity.rs index 55998e982..869d317a0 100644 --- a/src/array/geometrycollection/capacity.rs +++ b/src/array/geometrycollection/capacity.rs @@ -13,7 +13,7 @@ use crate::geo_traits::{ /// [`GeometryCollectionArray`][crate::array::GeometryCollectionArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct GeometryCollectionCapacity { pub(crate) mixed_capacity: MixedCapacity, pub(crate) geom_capacity: usize, @@ -141,10 +141,10 @@ impl GeometryCollectionCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity; - (offsets_byte_width * num_offsets) + self.mixed_capacity.num_bytes::() + (offsets_byte_width * num_offsets) + self.mixed_capacity.num_bytes::(dim) } } diff --git a/src/array/linestring/array.rs b/src/array/linestring/array.rs index 4a171343e..2ebe236e3 100644 --- a/src/array/linestring/array.rs +++ b/src/array/linestring/array.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use crate::algorithm::native::eq::offset_buffer_eq; @@ -133,13 +133,17 @@ impl LineStringArray { /// The lengths of each buffer contained in this array. pub fn buffer_lengths(&self) -> LineStringCapacity { - LineStringCapacity::new(self.geom_offsets.last().to_usize().unwrap(), self.len()) + LineStringCapacity::new( + self.geom_offsets.last().to_usize().unwrap(), + self.len(), + HashSet::from_iter([D]), + ) } /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/linestring/builder.rs b/src/array/linestring/builder.rs index 3db14d3ff..6cf9c4642 100644 --- a/src/array/linestring/builder.rs +++ b/src/array/linestring/builder.rs @@ -309,7 +309,7 @@ impl GeometryArrayBuilder for LineStringBuil coord_type: CoordType, metadata: Arc, ) -> Self { - let capacity = LineStringCapacity::new(0, geom_capacity); + let capacity = LineStringCapacity::new(0, geom_capacity, Default::default()); Self::with_capacity_and_options(capacity, coord_type, metadata) } diff --git a/src/array/linestring/capacity.rs b/src/array/linestring/capacity.rs index 26f1fd845..38bb4e708 100644 --- a/src/array/linestring/capacity.rs +++ b/src/array/linestring/capacity.rs @@ -1,4 +1,5 @@ -use std::ops::Add; +use std::collections::HashSet; +use std::ops::{Add, AddAssign}; use arrow_array::OffsetSizeTrait; @@ -8,24 +9,26 @@ use crate::geo_traits::{GeometryTrait, GeometryType, LineStringTrait}; /// A counter for the buffer sizes of a [`LineStringArray`][crate::array::LineStringArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct LineStringCapacity { pub(crate) coord_capacity: usize, pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl LineStringCapacity { /// Create a new capacity with known sizes. - pub fn new(coord_capacity: usize, geom_capacity: usize) -> Self { + pub fn new(coord_capacity: usize, geom_capacity: usize, dimensions: HashSet) -> Self { Self { coord_capacity, geom_capacity, + dimensions, } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0, 0) + Self::new(0, 0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -45,6 +48,7 @@ impl LineStringCapacity { #[inline] fn add_valid_line_string(&mut self, line_string: &impl LineStringTrait) { self.coord_capacity += line_string.num_coords(); + self.dimensions.insert(line_string.dim()); } #[inline] @@ -81,10 +85,10 @@ impl LineStringCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity; - (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8) + (offsets_byte_width * num_offsets) + (self.coord_capacity * dim * 8) } } @@ -98,8 +102,16 @@ impl Add for LineStringCapacity { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - let coord_capacity = self.coord_capacity + rhs.coord_capacity; - let geom_capacity = self.geom_capacity + rhs.geom_capacity; - Self::new(coord_capacity, geom_capacity) + let mut new = self.clone(); + new += rhs; + new + } +} + +impl AddAssign for LineStringCapacity { + fn add_assign(&mut self, rhs: Self) { + self.coord_capacity += rhs.coord_capacity(); + self.geom_capacity += rhs.geom_capacity(); + self.dimensions.extend(rhs.dimensions); } } diff --git a/src/array/mixed/array.rs b/src/array/mixed/array.rs index 5e94d3011..4daa53106 100644 --- a/src/array/mixed/array.rs +++ b/src/array/mixed/array.rs @@ -265,7 +265,7 @@ impl MixedGeometryArray { /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { - self.buffer_lengths().num_bytes::() + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/mixed/capacity.rs b/src/array/mixed/capacity.rs index 712e93acc..e22c62d32 100644 --- a/src/array/mixed/capacity.rs +++ b/src/array/mixed/capacity.rs @@ -13,7 +13,7 @@ use crate::geo_traits::*; /// A counter for the buffer sizes of a [`MixedGeometryArray`][crate::array::MixedGeometryArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Default, Debug, Clone, Copy)] +#[derive(Default, Debug, Clone)] pub struct MixedCapacity { /// Simple: just the total number of points, nulls included pub(crate) point: usize, @@ -77,28 +77,28 @@ impl MixedCapacity { total } - pub fn point_capacity(&self) -> usize { - self.point + pub fn point_capacity(&self) -> &usize { + &self.point } - pub fn line_string_capacity(&self) -> LineStringCapacity { - self.line_string + pub fn line_string_capacity(&self) -> &LineStringCapacity { + &self.line_string } - pub fn polygon_capacity(&self) -> PolygonCapacity { - self.polygon + pub fn polygon_capacity(&self) -> &PolygonCapacity { + &self.polygon } - pub fn multi_point_capacity(&self) -> MultiPointCapacity { - self.multi_point + pub fn multi_point_capacity(&self) -> &MultiPointCapacity { + &self.multi_point } - pub fn multi_line_string_capacity(&self) -> MultiLineStringCapacity { - self.multi_line_string + pub fn multi_line_string_capacity(&self) -> &MultiLineStringCapacity { + &self.multi_line_string } - pub fn multi_polygon_capacity(&self) -> MultiPolygonCapacity { - self.multi_polygon + pub fn multi_polygon_capacity(&self) -> &MultiPolygonCapacity { + &self.multi_polygon } pub fn point_compatible(&self) -> bool { @@ -221,13 +221,13 @@ impl MixedCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { - let mut count = self.point * 2 * 8; - count += self.line_string.num_bytes::(); - count += self.polygon.num_bytes::(); - count += self.multi_point.num_bytes::(); - count += self.multi_line_string.num_bytes::(); - count += self.multi_polygon.num_bytes::(); + pub fn num_bytes(&self, dim: usize) -> usize { + let mut count = self.point * dim * 8; + count += self.line_string.num_bytes::(dim); + count += self.polygon.num_bytes::(dim); + count += self.multi_point.num_bytes::(dim); + count += self.multi_line_string.num_bytes::(dim); + count += self.multi_polygon.num_bytes::(dim); count } } diff --git a/src/array/mod.rs b/src/array/mod.rs index 134045519..baf9672dd 100644 --- a/src/array/mod.rs +++ b/src/array/mod.rs @@ -14,7 +14,7 @@ pub use mixed::{MixedCapacity, MixedGeometryArray, MixedGeometryBuilder}; pub use multilinestring::{MultiLineStringArray, MultiLineStringBuilder, MultiLineStringCapacity}; pub use multipoint::{MultiPointArray, MultiPointBuilder, MultiPointCapacity}; pub use multipolygon::{MultiPolygonArray, MultiPolygonBuilder, MultiPolygonCapacity}; -pub use point::{PointArray, PointBuilder}; +pub use point::{PointArray, PointBuilder, PointCapacity}; pub use polygon::{PolygonArray, PolygonBuilder, PolygonCapacity}; pub use rect::{RectArray, RectBuilder}; diff --git a/src/array/multilinestring/array.rs b/src/array/multilinestring/array.rs index 2b8ef79a3..642294f61 100644 --- a/src/array/multilinestring/array.rs +++ b/src/array/multilinestring/array.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use crate::algorithm::native::eq::offset_buffer_eq; @@ -170,13 +170,14 @@ impl MultiLineStringArray { self.ring_offsets.last().to_usize().unwrap(), self.geom_offsets.last().to_usize().unwrap(), self.len(), + HashSet::from_iter([D]), ) } /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/multilinestring/builder.rs b/src/array/multilinestring/builder.rs index 0d6ff4811..c52653ecb 100644 --- a/src/array/multilinestring/builder.rs +++ b/src/array/multilinestring/builder.rs @@ -395,7 +395,7 @@ impl GeometryArrayBuilder for MultiLineStrin coord_type: CoordType, metadata: Arc, ) -> Self { - let capacity = MultiLineStringCapacity::new(0, 0, geom_capacity); + let capacity = MultiLineStringCapacity::new(0, 0, geom_capacity, Default::default()); Self::with_capacity_and_options(capacity, coord_type, metadata) } diff --git a/src/array/multilinestring/capacity.rs b/src/array/multilinestring/capacity.rs index 95f39d5fd..5aacbb1e2 100644 --- a/src/array/multilinestring/capacity.rs +++ b/src/array/multilinestring/capacity.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::ops::{Add, AddAssign}; use arrow_array::OffsetSizeTrait; @@ -9,26 +10,33 @@ use crate::geo_traits::{LineStringTrait, MultiLineStringTrait}; /// [`MultiLineStringArray`][crate::array::MultiLineStringArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct MultiLineStringCapacity { pub(crate) coord_capacity: usize, pub(crate) ring_capacity: usize, pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl MultiLineStringCapacity { /// Create a new capacity with known sizes. - pub fn new(coord_capacity: usize, ring_capacity: usize, geom_capacity: usize) -> Self { + pub fn new( + coord_capacity: usize, + ring_capacity: usize, + geom_capacity: usize, + dimensions: HashSet, + ) -> Self { Self { coord_capacity, ring_capacity, geom_capacity, + dimensions, } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0, 0, 0) + Self::new(0, 0, 0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -55,6 +63,8 @@ impl MultiLineStringCapacity { // A single line string self.ring_capacity += 1; self.coord_capacity += line_string.num_coords(); + + self.dimensions.insert(line_string.dim()); } } @@ -69,13 +79,9 @@ impl MultiLineStringCapacity { for line_string in multi_line_string.lines() { self.coord_capacity += line_string.num_coords(); } - } - } - pub fn add_line_string_capacity(&mut self, line_string_capacity: LineStringCapacity) { - self.coord_capacity += line_string_capacity.coord_capacity(); - self.ring_capacity += line_string_capacity.geom_capacity(); - self.geom_capacity += line_string_capacity.geom_capacity(); + self.dimensions.insert(multi_line_string.dim()); + } } pub fn from_multi_line_strings<'a>( @@ -89,10 +95,10 @@ impl MultiLineStringCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity + self.ring_capacity; - (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8) + (offsets_byte_width * num_offsets) + (self.coord_capacity * dim * 8) } } @@ -106,10 +112,19 @@ impl Add for MultiLineStringCapacity { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - let coord_capacity = self.coord_capacity + rhs.coord_capacity; - let ring_capacity = self.ring_capacity + rhs.ring_capacity; - let geom_capacity = self.geom_capacity + rhs.geom_capacity; - Self::new(coord_capacity, ring_capacity, geom_capacity) + let mut new = self.clone(); + new += rhs; + new + } +} + +impl Add for MultiLineStringCapacity { + type Output = Self; + + fn add(self, rhs: LineStringCapacity) -> Self::Output { + let mut new = self.clone(); + new += rhs; + new } } @@ -118,6 +133,7 @@ impl AddAssign for MultiLineStringCapacity { self.coord_capacity += rhs.coord_capacity; self.ring_capacity += rhs.ring_capacity; self.geom_capacity += rhs.geom_capacity; + self.dimensions.extend(rhs.dimensions); } } @@ -126,5 +142,6 @@ impl AddAssign for MultiLineStringCapacity { self.coord_capacity += rhs.coord_capacity(); self.ring_capacity += rhs.geom_capacity(); self.geom_capacity += rhs.geom_capacity(); + self.dimensions.extend(rhs.dimensions); } } diff --git a/src/array/multipoint/array.rs b/src/array/multipoint/array.rs index 40a9981bb..71becd49e 100644 --- a/src/array/multipoint/array.rs +++ b/src/array/multipoint/array.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use super::MultiPointBuilder; @@ -133,13 +133,17 @@ impl MultiPointArray { /// The lengths of each buffer contained in this array. pub fn buffer_lengths(&self) -> MultiPointCapacity { - MultiPointCapacity::new(self.geom_offsets.last().to_usize().unwrap(), self.len()) + MultiPointCapacity::new( + self.geom_offsets.last().to_usize().unwrap(), + self.len(), + HashSet::from_iter([D]), + ) } /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/multipoint/builder.rs b/src/array/multipoint/builder.rs index 1bca408a9..78740bd8e 100644 --- a/src/array/multipoint/builder.rs +++ b/src/array/multipoint/builder.rs @@ -342,7 +342,7 @@ impl GeometryArrayBuilder for MultiPointBuil coord_type: CoordType, metadata: Arc, ) -> Self { - let capacity = MultiPointCapacity::new(0, geom_capacity); + let capacity = MultiPointCapacity::new(0, geom_capacity, Default::default()); Self::with_capacity_and_options(capacity, coord_type, metadata) } diff --git a/src/array/multipoint/capacity.rs b/src/array/multipoint/capacity.rs index b43418020..27d0d55ae 100644 --- a/src/array/multipoint/capacity.rs +++ b/src/array/multipoint/capacity.rs @@ -1,31 +1,35 @@ -use std::ops::Add; +use std::collections::HashSet; +use std::ops::{Add, AddAssign}; use arrow_array::OffsetSizeTrait; +use crate::array::PointCapacity; use crate::error::{GeoArrowError, Result}; use crate::geo_traits::{GeometryTrait, GeometryType, MultiPointTrait, PointTrait}; /// A counter for the buffer sizes of a [`MultiPointArray`][crate::array::MultiPointArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct MultiPointCapacity { pub(crate) coord_capacity: usize, pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl MultiPointCapacity { /// Create a new capacity with known sizes. - pub fn new(coord_capacity: usize, geom_capacity: usize) -> Self { + pub fn new(coord_capacity: usize, geom_capacity: usize, dimensions: HashSet) -> Self { Self { coord_capacity, geom_capacity, + dimensions, } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0, 0) + Self::new(0, 0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -42,8 +46,9 @@ impl MultiPointCapacity { } #[inline] - fn add_valid_point(&mut self, _point: &impl PointTrait) { + fn add_valid_point(&mut self, point: &impl PointTrait) { self.coord_capacity += 1; + self.dimensions.insert(point.dim()); } #[inline] @@ -58,6 +63,7 @@ impl MultiPointCapacity { #[inline] fn add_valid_multi_point(&mut self, multi_point: &impl MultiPointTrait) { self.coord_capacity += multi_point.num_points(); + self.dimensions.insert(multi_point.dim()); } #[inline] @@ -74,11 +80,6 @@ impl MultiPointCapacity { Ok(()) } - pub fn add_point_capacity(&mut self, point_capacity: usize) { - self.coord_capacity += point_capacity; - self.geom_capacity += point_capacity; - } - pub fn coord_capacity(&self) -> usize { self.coord_capacity } @@ -100,10 +101,10 @@ impl MultiPointCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity; - (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8) + (offsets_byte_width * num_offsets) + (self.coord_capacity * dim * 8) } } @@ -119,6 +120,24 @@ impl Add for MultiPointCapacity { fn add(self, rhs: Self) -> Self::Output { let coord_capacity = self.coord_capacity + rhs.coord_capacity; let geom_capacity = self.geom_capacity + rhs.geom_capacity; - Self::new(coord_capacity, geom_capacity) + let mut dimensions = self.dimensions.clone(); + dimensions.extend(rhs.dimensions); + Self::new(coord_capacity, geom_capacity, dimensions) + } +} + +impl AddAssign for MultiPointCapacity { + fn add_assign(&mut self, rhs: Self) { + self.coord_capacity += rhs.coord_capacity; + self.geom_capacity += rhs.geom_capacity; + self.dimensions.extend(rhs.dimensions); + } +} + +impl AddAssign for MultiPointCapacity { + fn add_assign(&mut self, rhs: PointCapacity) { + self.coord_capacity += rhs.geom_capacity; + self.geom_capacity += rhs.geom_capacity; + self.dimensions.extend(rhs.dimensions); } } diff --git a/src/array/multipolygon/array.rs b/src/array/multipolygon/array.rs index 926356a49..0b76aa453 100644 --- a/src/array/multipolygon/array.rs +++ b/src/array/multipolygon/array.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use crate::algorithm::native::eq::offset_buffer_eq; @@ -207,13 +207,14 @@ impl MultiPolygonArray { self.polygon_offsets.last().to_usize().unwrap(), self.geom_offsets.last().to_usize().unwrap(), self.len(), + HashSet::from_iter([D]), ) } /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } diff --git a/src/array/multipolygon/builder.rs b/src/array/multipolygon/builder.rs index a88972bb1..e623cc1ac 100644 --- a/src/array/multipolygon/builder.rs +++ b/src/array/multipolygon/builder.rs @@ -466,6 +466,7 @@ impl GeometryArrayBuilder for MultiPolygonBu Default::default(), Default::default(), geom_capacity, + Default::default(), ); Self::with_capacity_and_options(capacity, coord_type, metadata) } diff --git a/src/array/multipolygon/capacity.rs b/src/array/multipolygon/capacity.rs index a3ba26fc2..c26377b9d 100644 --- a/src/array/multipolygon/capacity.rs +++ b/src/array/multipolygon/capacity.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::ops::{Add, AddAssign}; use arrow_array::OffsetSizeTrait; @@ -8,12 +9,13 @@ use crate::geo_traits::{LineStringTrait, MultiPolygonTrait, PolygonTrait}; /// A counter for the buffer sizes of a [`MultiPolygonArray`][crate::array::MultiPolygonArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct MultiPolygonCapacity { pub(crate) coord_capacity: usize, pub(crate) ring_capacity: usize, pub(crate) polygon_capacity: usize, pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl MultiPolygonCapacity { @@ -23,18 +25,20 @@ impl MultiPolygonCapacity { ring_capacity: usize, polygon_capacity: usize, geom_capacity: usize, + dimensions: HashSet, ) -> Self { Self { coord_capacity, ring_capacity, polygon_capacity, geom_capacity, + dimensions, } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0, 0, 0, 0) + Self::new(0, 0, 0, 0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -80,6 +84,8 @@ impl MultiPolygonCapacity { for int_ring in polygon.interiors() { self.coord_capacity += int_ring.num_coords(); } + + self.dimensions.insert(polygon.dim()); } } @@ -108,17 +114,9 @@ impl MultiPolygonCapacity { self.coord_capacity += int_ring.num_coords(); } } - } - } - pub fn add_polygon_capacity(&mut self, capacity: PolygonCapacity) { - // NOTE: I think this will overallocate if there are null values? - // Because it assumes that every geometry has exactly one polygon, which won't be true if - // there are null values? - self.coord_capacity += capacity.coord_capacity(); - self.ring_capacity += capacity.ring_capacity(); - self.polygon_capacity += capacity.geom_capacity(); - self.geom_capacity += capacity.geom_capacity(); + self.dimensions.insert(multi_polygon.dim()); + } } pub fn from_multi_polygons<'a>( @@ -132,10 +130,10 @@ impl MultiPolygonCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity + self.polygon_capacity + self.ring_capacity; - (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8) + (offsets_byte_width * num_offsets) + (self.coord_capacity * dim * 8) } } @@ -149,16 +147,19 @@ impl Add for MultiPolygonCapacity { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - let coord_capacity = self.coord_capacity + rhs.coord_capacity; - let ring_capacity = self.ring_capacity + rhs.ring_capacity; - let polygon_capacity = self.polygon_capacity + rhs.polygon_capacity; - let geom_capacity = self.geom_capacity + rhs.geom_capacity; - Self::new( - coord_capacity, - ring_capacity, - polygon_capacity, - geom_capacity, - ) + let mut new = self.clone(); + new += rhs; + new + } +} + +impl Add for MultiPolygonCapacity { + type Output = Self; + + fn add(self, rhs: PolygonCapacity) -> Self::Output { + let mut new = self.clone(); + new += rhs; + new } } @@ -172,6 +173,9 @@ impl AddAssign for MultiPolygonCapacity { } impl AddAssign for MultiPolygonCapacity { + // NOTE: I think this will overallocate if there are null values? + // Because it assumes that every geometry has exactly one polygon, which won't be true if + // there are null values? fn add_assign(&mut self, rhs: PolygonCapacity) { self.coord_capacity += rhs.coord_capacity(); self.ring_capacity += rhs.ring_capacity(); diff --git a/src/array/point/builder.rs b/src/array/point/builder.rs index 8ce260b39..f4318bd88 100644 --- a/src/array/point/builder.rs +++ b/src/array/point/builder.rs @@ -31,7 +31,7 @@ impl PointBuilder { } pub fn new_with_options(coord_type: CoordType, metadata: Arc) -> Self { - Self::with_capacity_and_options(0, coord_type, metadata) + Self::with_capacity_and_options(Default::default(), coord_type, metadata) } /// Creates a new [`PointBuilder`] with a capacity. diff --git a/src/array/point/capacity.rs b/src/array/point/capacity.rs index 97652f112..f1ed2b1fe 100644 --- a/src/array/point/capacity.rs +++ b/src/array/point/capacity.rs @@ -2,25 +2,30 @@ use crate::error::{GeoArrowError, Result}; use crate::geo_traits::{GeometryTrait, GeometryType, PointTrait}; -use std::ops::Add; +use std::collections::HashSet; +use std::ops::{Add, AddAssign}; /// A counter for the buffer sizes of a [`PointArray`][crate::array::PointArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Default)] pub struct PointCapacity { pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl PointCapacity { /// Create a new capacity with known size. - pub fn new(geom_capacity: usize) -> Self { - Self { geom_capacity } + pub fn new(geom_capacity: usize, dimensions: HashSet) -> Self { + Self { + geom_capacity, + dimensions, + } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0) + Self::new(0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -29,8 +34,11 @@ impl PointCapacity { } #[inline] - pub fn add_point(&mut self, _point: Option<&impl PointTrait>) { + pub fn add_point(&mut self, point: Option<&impl PointTrait>) { self.geom_capacity += 1; + if let Some(g) = point { + self.dimensions.insert(g.dim()); + } } #[inline] @@ -40,6 +48,7 @@ impl PointCapacity { GeometryType::Point(p) => self.add_point(Some(p)), _ => return Err(GeoArrowError::General("incorrect type".to_string())), } + self.dimensions.insert(g.dim()); } else { self.geom_capacity += 1; }; @@ -47,8 +56,8 @@ impl PointCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { - self.geom_capacity * 2 * 8 + pub fn num_bytes(&self, dim: usize) -> usize { + self.geom_capacity * dim * 8 } } @@ -56,6 +65,15 @@ impl Add for PointCapacity { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - Self::new(self.geom_capacity + rhs.geom_capacity) + let mut new = self.clone(); + new += rhs; + new + } +} + +impl AddAssign for PointCapacity { + fn add_assign(&mut self, rhs: Self) { + self.geom_capacity += rhs.geom_capacity; + self.dimensions.extend(rhs.dimensions); } } diff --git a/src/array/point/mod.rs b/src/array/point/mod.rs index 2dcce1e85..1d31b970d 100644 --- a/src/array/point/mod.rs +++ b/src/array/point/mod.rs @@ -2,7 +2,7 @@ pub use array::PointArray; pub use builder::PointBuilder; -// pub use capacity::PointCapacity; +pub use capacity::PointCapacity; mod array; pub(crate) mod builder; diff --git a/src/array/polygon/array.rs b/src/array/polygon/array.rs index ece2aa6fd..779cfb6d1 100644 --- a/src/array/polygon/array.rs +++ b/src/array/polygon/array.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use crate::algorithm::native::eq::offset_buffer_eq; @@ -171,13 +171,14 @@ impl PolygonArray { self.ring_offsets.last().to_usize().unwrap(), self.geom_offsets.last().to_usize().unwrap(), self.len(), + Default::default(), ) } /// The number of bytes occupied by this array. pub fn num_bytes(&self) -> usize { let validity_len = self.validity().map(|v| v.buffer().len()).unwrap_or(0); - validity_len + self.buffer_lengths().num_bytes::() + validity_len + self.buffer_lengths().num_bytes::(D) } } @@ -501,7 +502,10 @@ impl From for PolygonArray { // Don't reserve capacity for null entries let coord_capacity = (value.len() - value.null_count()) * 5; - let capacity = PolygonCapacity::new(coord_capacity, ring_capacity, geom_capacity); + // TODO: update to D generic when RectArray is genericized + let dimensions = HashSet::from_iter([2]); + let capacity = + PolygonCapacity::new(coord_capacity, ring_capacity, geom_capacity, dimensions); let mut output_array = PolygonBuilder::with_capacity(capacity); value.iter_geo().for_each(|maybe_g| { diff --git a/src/array/polygon/builder.rs b/src/array/polygon/builder.rs index e036d8550..a5767439e 100644 --- a/src/array/polygon/builder.rs +++ b/src/array/polygon/builder.rs @@ -412,7 +412,7 @@ impl GeometryArrayBuilder for PolygonBuilder coord_type: CoordType, metadata: Arc, ) -> Self { - let capacity = PolygonCapacity::new(0, 0, geom_capacity); + let capacity = PolygonCapacity::new(0, 0, geom_capacity, Default::default()); Self::with_capacity_and_options(capacity, coord_type, metadata) } diff --git a/src/array/polygon/capacity.rs b/src/array/polygon/capacity.rs index e7113f1bf..dd2e56220 100644 --- a/src/array/polygon/capacity.rs +++ b/src/array/polygon/capacity.rs @@ -1,4 +1,5 @@ -use std::ops::Add; +use std::collections::HashSet; +use std::ops::{Add, AddAssign}; use arrow_array::OffsetSizeTrait; @@ -7,26 +8,33 @@ use crate::geo_traits::{LineStringTrait, PolygonTrait, RectTrait}; /// A counter for the buffer sizes of a [`PolygonArray`][crate::array::PolygonArray]. /// /// This can be used to reduce allocations by allocating once for exactly the array size you need. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct PolygonCapacity { pub(crate) coord_capacity: usize, pub(crate) ring_capacity: usize, pub(crate) geom_capacity: usize, + pub(crate) dimensions: HashSet, } impl PolygonCapacity { /// Create a new capacity with known sizes. - pub fn new(coord_capacity: usize, ring_capacity: usize, geom_capacity: usize) -> Self { + pub fn new( + coord_capacity: usize, + ring_capacity: usize, + geom_capacity: usize, + dimensions: HashSet, + ) -> Self { Self { coord_capacity, ring_capacity, geom_capacity, + dimensions, } } /// Create a new empty capacity. pub fn new_empty() -> Self { - Self::new(0, 0, 0) + Self::new(0, 0, 0, HashSet::new()) } /// Return `true` if the capacity is empty. @@ -62,17 +70,20 @@ impl PolygonCapacity { for int_ring in polygon.interiors() { self.coord_capacity += int_ring.num_coords(); } + + self.dimensions.insert(polygon.dim()); } } #[inline] pub fn add_rect<'a>(&mut self, rect: Option<&'a (impl RectTrait + 'a)>) { self.geom_capacity += 1; - if let Some(_rect) = rect { + if let Some(r) = rect { // A rect is a simple polygon with only one ring self.ring_capacity += 1; // A rect is a closed polygon with 5 coordinates self.coord_capacity += 5; + self.dimensions.insert(r.dim()); } } @@ -95,10 +106,10 @@ impl PolygonCapacity { } /// The number of bytes an array with this capacity would occupy. - pub fn num_bytes(&self) -> usize { + pub fn num_bytes(&self, dim: usize) -> usize { let offsets_byte_width = if O::IS_LARGE { 8 } else { 4 }; let num_offsets = self.geom_capacity + self.ring_capacity; - (offsets_byte_width * num_offsets) + (self.coord_capacity * 2 * 8) + (offsets_byte_width * num_offsets) + (self.coord_capacity * dim * 8) } } @@ -112,9 +123,17 @@ impl Add for PolygonCapacity { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - let coord_capacity = self.coord_capacity + rhs.coord_capacity; - let ring_capacity = self.ring_capacity + rhs.ring_capacity; - let geom_capacity = self.geom_capacity + rhs.geom_capacity; - Self::new(coord_capacity, ring_capacity, geom_capacity) + let mut new = self.clone(); + new += rhs; + new + } +} + +impl AddAssign for PolygonCapacity { + fn add_assign(&mut self, rhs: Self) { + self.coord_capacity += rhs.coord_capacity(); + self.ring_capacity += rhs.ring_capacity(); + self.geom_capacity += rhs.geom_capacity(); + self.dimensions.extend(rhs.dimensions); } } diff --git a/src/io/geozero/array/linestring.rs b/src/io/geozero/array/linestring.rs index 8c694f269..51d32e553 100644 --- a/src/io/geozero/array/linestring.rs +++ b/src/io/geozero/array/linestring.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use arrow_array::OffsetSizeTrait; use geozero::{GeomProcessor, GeozeroGeometry}; @@ -48,7 +50,7 @@ impl ToLineStringArray for T { #[allow(unused_variables)] impl GeomProcessor for LineStringBuilder { fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { - let capacity = LineStringCapacity::new(0, size); + let capacity = LineStringCapacity::new(0, size, HashSet::from_iter([2])); self.reserve(capacity); Ok(()) } @@ -72,7 +74,7 @@ impl GeomProcessor for LineStringBuilder { size: usize, idx: usize, ) -> geozero::error::Result<()> { - let capacity = LineStringCapacity::new(size, 0); + let capacity = LineStringCapacity::new(size, 0, HashSet::from_iter([2])); self.reserve(capacity); self.try_push_length(size).unwrap(); Ok(()) diff --git a/src/io/geozero/array/multilinestring.rs b/src/io/geozero/array/multilinestring.rs index 748f943e2..2b70aff1a 100644 --- a/src/io/geozero/array/multilinestring.rs +++ b/src/io/geozero/array/multilinestring.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use arrow_array::OffsetSizeTrait; use geozero::{GeomProcessor, GeozeroGeometry}; @@ -49,7 +51,7 @@ impl ToMultiLineStringArray for T { impl GeomProcessor for MultiLineStringBuilder { fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { // reserve `size` geometries - let capacity = MultiLineStringCapacity::new(0, 0, size); + let capacity = MultiLineStringCapacity::new(0, 0, size, HashSet::from_iter([2])); self.reserve(capacity); Ok(()) } @@ -70,7 +72,7 @@ impl GeomProcessor for MultiLineStringBuilder { // Here, size is the number of LineStrings in the MultiLineString fn multilinestring_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { // reserve `size` line strings - let capacity = MultiLineStringCapacity::new(0, size, 0); + let capacity = MultiLineStringCapacity::new(0, size, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -90,7 +92,7 @@ impl GeomProcessor for MultiLineStringBuilder { // So if tagged, we need to update the geometry offsets array. if tagged { // reserve 1 line strings - let capacity = MultiLineStringCapacity::new(0, 1, 0); + let capacity = MultiLineStringCapacity::new(0, 1, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -100,7 +102,7 @@ impl GeomProcessor for MultiLineStringBuilder { } // reserve `size` coordinates - let capacity = MultiLineStringCapacity::new(size, 0, 0); + let capacity = MultiLineStringCapacity::new(size, 0, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: diff --git a/src/io/geozero/array/multipoint.rs b/src/io/geozero/array/multipoint.rs index 1b148ce2b..51d51f960 100644 --- a/src/io/geozero/array/multipoint.rs +++ b/src/io/geozero/array/multipoint.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use crate::array::multipoint::MultiPointCapacity; use crate::array::{MultiPointArray, MultiPointBuilder}; use crate::io::geozero::scalar::process_multi_point; @@ -47,7 +49,7 @@ impl ToMultiPointArray for T { #[allow(unused_variables)] impl GeomProcessor for MultiPointBuilder { fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { - let capacity = MultiPointCapacity::new(0, size); + let capacity = MultiPointCapacity::new(0, size, HashSet::from_iter([2])); self.reserve(capacity); Ok(()) } @@ -61,7 +63,7 @@ impl GeomProcessor for MultiPointBuilder { } fn point_begin(&mut self, idx: usize) -> geozero::error::Result<()> { - let capacity = MultiPointCapacity::new(1, 0); + let capacity = MultiPointCapacity::new(1, 0, HashSet::from_iter([2])); self.reserve(capacity); self.try_push_length(1).unwrap(); Ok(()) @@ -72,7 +74,7 @@ impl GeomProcessor for MultiPointBuilder { } fn multipoint_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { - let capacity = MultiPointCapacity::new(size, 0); + let capacity = MultiPointCapacity::new(size, 0, HashSet::from_iter([2])); self.reserve(capacity); self.try_push_length(size).unwrap(); Ok(()) diff --git a/src/io/geozero/array/multipolygon.rs b/src/io/geozero/array/multipolygon.rs index 3f8182a3c..bcac1ad80 100644 --- a/src/io/geozero/array/multipolygon.rs +++ b/src/io/geozero/array/multipolygon.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use arrow_array::OffsetSizeTrait; use geozero::{GeomProcessor, GeozeroGeometry}; @@ -49,7 +51,7 @@ impl ToMultiPolygonArray for T { impl GeomProcessor for MultiPolygonBuilder { fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { // reserve `size` geometries - let capacity = MultiPolygonCapacity::new(0, 0, 0, size); + let capacity = MultiPolygonCapacity::new(0, 0, 0, size, HashSet::from_iter([2])); self.reserve(capacity); Ok(()) } @@ -69,7 +71,7 @@ impl GeomProcessor for MultiPolygonBuilder { fn multipolygon_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { // reserve `size` polygons - let capacity = MultiPolygonCapacity::new(0, 0, size, 0); + let capacity = MultiPolygonCapacity::new(0, 0, size, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -88,7 +90,7 @@ impl GeomProcessor for MultiPolygonBuilder { // > An untagged Polygon is part of a MultiPolygon if tagged { // reserve 1 polygon - let capacity = MultiPolygonCapacity::new(0, 0, 1, 0); + let capacity = MultiPolygonCapacity::new(0, 0, 1, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -98,7 +100,7 @@ impl GeomProcessor for MultiPolygonBuilder { } // reserve `size` rings - let capacity = MultiPolygonCapacity::new(0, size, 0, 0); + let capacity = MultiPolygonCapacity::new(0, size, 0, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -117,7 +119,7 @@ impl GeomProcessor for MultiPolygonBuilder { assert!(!tagged); // reserve `size` coordinates - let capacity = MultiPolygonCapacity::new(size, 0, 0, 0); + let capacity = MultiPolygonCapacity::new(size, 0, 0, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: diff --git a/src/io/geozero/array/polygon.rs b/src/io/geozero/array/polygon.rs index 1a921b8d5..7181f022f 100644 --- a/src/io/geozero/array/polygon.rs +++ b/src/io/geozero/array/polygon.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use crate::array::polygon::PolygonCapacity; use crate::array::{PolygonArray, PolygonBuilder}; use crate::io::geozero::scalar::process_polygon; @@ -48,7 +50,7 @@ impl ToPolygonArray for T { impl GeomProcessor for PolygonBuilder { fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> { // reserve `size` geometries - let capacity = PolygonCapacity::new(0, 0, size); + let capacity = PolygonCapacity::new(0, 0, size, HashSet::from_iter([2])); self.reserve(capacity); Ok(()) } @@ -74,7 +76,7 @@ impl GeomProcessor for PolygonBuilder { idx: usize, ) -> geozero::error::Result<()> { // reserve `size` rings - let capacity = PolygonCapacity::new(0, size, 0); + let capacity = PolygonCapacity::new(0, size, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: @@ -91,7 +93,7 @@ impl GeomProcessor for PolygonBuilder { idx: usize, ) -> geozero::error::Result<()> { // reserve `size` coordinates - let capacity = PolygonCapacity::new(size, 0, 0); + let capacity = PolygonCapacity::new(size, 0, 0, HashSet::from_iter([2])); self.reserve(capacity); // # Safety: