use std::ops::Add;
use geo_traits::*;
use geoarrow_schema::Dimension;
use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
use wkt::WktNum;
use crate::builder::geo_trait_wrappers::{LineWrapper, RectWrapper, TriangleWrapper};
use crate::capacity::{
LineStringCapacity, MultiLineStringCapacity, MultiPointCapacity, MultiPolygonCapacity,
PolygonCapacity,
};
#[derive(Default, Debug, Clone, Copy)]
pub struct MixedCapacity {
pub(crate) point: usize,
pub(crate) line_string: LineStringCapacity,
pub(crate) polygon: PolygonCapacity,
pub(crate) multi_point: MultiPointCapacity,
pub(crate) multi_line_string: MultiLineStringCapacity,
pub(crate) multi_polygon: MultiPolygonCapacity,
}
impl MixedCapacity {
pub(crate) fn new(
point: usize,
line_string: LineStringCapacity,
polygon: PolygonCapacity,
multi_point: MultiPointCapacity,
multi_line_string: MultiLineStringCapacity,
multi_polygon: MultiPolygonCapacity,
) -> Self {
Self {
point,
line_string,
polygon,
multi_point,
multi_line_string,
multi_polygon,
}
}
pub(crate) fn new_empty() -> Self {
Self {
point: 0,
line_string: LineStringCapacity::new_empty(),
polygon: PolygonCapacity::new_empty(),
multi_point: MultiPointCapacity::new_empty(),
multi_line_string: MultiLineStringCapacity::new_empty(),
multi_polygon: MultiPolygonCapacity::new_empty(),
}
}
pub(crate) fn is_empty(&self) -> bool {
self.point == 0
&& self.line_string.is_empty()
&& self.polygon.is_empty()
&& self.multi_point.is_empty()
&& self.multi_line_string.is_empty()
&& self.multi_polygon.is_empty()
}
pub(crate) fn total_num_geoms(&self) -> usize {
let mut total = 0;
total += self.point;
total += self.line_string.geom_capacity();
total += self.polygon.geom_capacity();
total += self.multi_point.geom_capacity();
total += self.multi_line_string.geom_capacity();
total += self.multi_polygon.geom_capacity();
total
}
#[inline]
pub(crate) fn add_point(&mut self) {
self.point += 1;
}
#[inline]
pub(crate) fn add_line_string(&mut self, line_string: &impl LineStringTrait) {
self.line_string.add_line_string(Some(line_string));
}
#[inline]
pub(crate) fn add_polygon(&mut self, polygon: &impl PolygonTrait) {
self.polygon.add_polygon(Some(polygon));
}
#[inline]
pub(crate) fn add_multi_point(&mut self, multi_point: &impl MultiPointTrait) {
self.multi_point.add_multi_point(Some(multi_point));
}
#[inline]
pub(crate) fn add_multi_line_string(&mut self, multi_line_string: &impl MultiLineStringTrait) {
self.multi_line_string
.add_multi_line_string(Some(multi_line_string));
}
#[inline]
pub(crate) fn add_multi_polygon(&mut self, multi_polygon: &impl MultiPolygonTrait) {
self.multi_polygon.add_multi_polygon(Some(multi_polygon));
}
#[inline]
pub(crate) fn add_geometry<T: WktNum>(
&mut self,
geom: &impl GeometryTrait<T = T>,
) -> GeoArrowResult<()> {
match geom.as_type() {
geo_traits::GeometryType::Point(_) => self.add_point(),
geo_traits::GeometryType::LineString(g) => self.add_line_string(g),
geo_traits::GeometryType::Polygon(g) => self.add_polygon(g),
geo_traits::GeometryType::MultiPoint(p) => self.add_multi_point(p),
geo_traits::GeometryType::MultiLineString(p) => self.add_multi_line_string(p),
geo_traits::GeometryType::MultiPolygon(p) => self.add_multi_polygon(p),
geo_traits::GeometryType::GeometryCollection(_) => {
return Err(GeoArrowError::InvalidGeoArrow(
"nested geometry collections not supported in GeoArrow".to_string(),
));
}
geo_traits::GeometryType::Rect(r) => self.add_polygon(&RectWrapper::try_new(r)?),
geo_traits::GeometryType::Triangle(tri) => self.add_polygon(&TriangleWrapper(tri)),
geo_traits::GeometryType::Line(l) => self.add_line_string(&LineWrapper(l)),
};
Ok(())
}
pub(crate) fn num_bytes(&self, dim: Dimension) -> usize {
let mut count = self.point * dim.size() * 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
}
}
impl Add for MixedCapacity {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let point = self.point + rhs.point;
let line_string = self.line_string + rhs.line_string;
let polygon = self.polygon + rhs.polygon;
let multi_point = self.multi_point + rhs.multi_point;
let multi_line_string = self.multi_line_string + rhs.multi_line_string;
let multi_polygon = self.multi_polygon + rhs.multi_polygon;
Self::new(
point,
line_string,
polygon,
multi_point,
multi_line_string,
multi_polygon,
)
}
}