diff --git a/rust/geoarrow/src/array/coord/interleaved/array.rs b/rust/geoarrow/src/array/coord/interleaved/array.rs index 02cec0f9..e4eb0483 100644 --- a/rust/geoarrow/src/array/coord/interleaved/array.rs +++ b/rust/geoarrow/src/array/coord/interleaved/array.rs @@ -116,15 +116,17 @@ impl InterleavedCoordBuffer { self.len() == 0 } - pub fn value(&self, index: usize) -> InterleavedCoord<'_> { + pub fn value(&self, index: usize) -> InterleavedCoord { assert!(index <= self.len()); self.value_unchecked(index) } - pub fn value_unchecked(&self, index: usize) -> InterleavedCoord<'_> { + pub fn value_unchecked(&self, index: usize) -> InterleavedCoord { InterleavedCoord { - coords: &self.coords, - i: index, + coords: self + .coords + .clone() + .slice(index * self.dim.size(), self.dim.size()), dim: self.dim, } } diff --git a/rust/geoarrow/src/array/coord/separated/array.rs b/rust/geoarrow/src/array/coord/separated/array.rs index ea3220f3..052697a9 100644 --- a/rust/geoarrow/src/array/coord/separated/array.rs +++ b/rust/geoarrow/src/array/coord/separated/array.rs @@ -167,15 +167,14 @@ impl SeparatedCoordBuffer { self.len() == 0 } - pub fn value(&self, index: usize) -> SeparatedCoord<'_> { + pub fn value(&self, index: usize) -> SeparatedCoord { assert!(index <= self.len()); self.value_unchecked(index) } - pub fn value_unchecked(&self, index: usize) -> SeparatedCoord<'_> { + pub fn value_unchecked(&self, index: usize) -> SeparatedCoord { SeparatedCoord { - buffers: &self.buffers, - i: index, + buffers: self.buffers.clone().map(|buffer| buffer.slice(index, 1)), dim: self.dim, } } diff --git a/rust/geoarrow/src/array/linestring/array.rs b/rust/geoarrow/src/array/linestring/array.rs index a08f73c1..1032dc4d 100644 --- a/rust/geoarrow/src/array/linestring/array.rs +++ b/rust/geoarrow/src/array/linestring/array.rs @@ -183,6 +183,10 @@ impl LineStringArray { self.metadata, ) } + + fn value(&self, index: usize) -> LineString { + LineString::new(self.slice(index, 1)) + } } impl ArrayBase for LineStringArray { @@ -284,7 +288,7 @@ impl GeometryArraySelfMethods for LineStringArray { impl NativeGeometryAccessor for LineStringArray { unsafe fn value_as_geometry_unchecked(&self, index: usize) -> crate::scalar::Geometry { - Geometry::LineString(LineString::new(&self.coords, &self.geom_offsets, index)) + Geometry::LineString(self.value(index)) } } @@ -294,17 +298,17 @@ impl<'a> crate::trait_::NativeGEOSGeometryAccessor<'a> for LineStringArray { &'a self, index: usize, ) -> std::result::Result { - let geom = LineString::new(&self.coords, &self.geom_offsets, index); + let geom = self.value(index); (&geom).try_into() } } impl<'a> ArrayAccessor<'a> for LineStringArray { - type Item = LineString<'a>; + type Item = LineString; type ItemGeo = geo::LineString; unsafe fn value_unchecked(&'a self, index: usize) -> Self::Item { - LineString::new(&self.coords, &self.geom_offsets, index) + self.value(index) } } diff --git a/rust/geoarrow/src/array/point/array.rs b/rust/geoarrow/src/array/point/array.rs index 4fa11225..8f37256d 100644 --- a/rust/geoarrow/src/array/point/array.rs +++ b/rust/geoarrow/src/array/point/array.rs @@ -216,7 +216,7 @@ impl GeometryArraySelfMethods for PointArray { impl NativeGeometryAccessor for PointArray { unsafe fn value_as_geometry_unchecked(&self, index: usize) -> crate::scalar::Geometry { - Geometry::Point(Point::new(&self.coords, index)) + Geometry::Point(Point::new(self.slice(index, 1))) } } @@ -226,17 +226,17 @@ impl<'a> crate::trait_::NativeGEOSGeometryAccessor<'a> for PointArray { &'a self, index: usize, ) -> std::result::Result { - let geom = Point::new(&self.coords, index); + let geom = Point::new(self.slice(index, 1)); (&geom).try_into() } } impl<'a> ArrayAccessor<'a> for PointArray { - type Item = Point<'a>; + type Item = Point; type ItemGeo = geo::Point; unsafe fn value_unchecked(&'a self, index: usize) -> Self::Item { - Point::new(&self.coords, index) + Point::new(self.slice(index, 1)) } } diff --git a/rust/geoarrow/src/array/polygon/array.rs b/rust/geoarrow/src/array/polygon/array.rs index a254750f..fa6cae60 100644 --- a/rust/geoarrow/src/array/polygon/array.rs +++ b/rust/geoarrow/src/array/polygon/array.rs @@ -201,6 +201,10 @@ impl PolygonArray { self.metadata, ) } + + fn value(&self, index: usize) -> Polygon { + Polygon::new(self.slice(index, 1)) + } } impl ArrayBase for PolygonArray { @@ -300,12 +304,7 @@ impl GeometryArraySelfMethods for PolygonArray { impl NativeGeometryAccessor for PolygonArray { unsafe fn value_as_geometry_unchecked(&self, index: usize) -> crate::scalar::Geometry { - Geometry::Polygon(Polygon::new( - &self.coords, - &self.geom_offsets, - &self.ring_offsets, - index, - )) + Geometry::Polygon(self.value(index)) } } @@ -315,7 +314,7 @@ impl<'a> crate::trait_::NativeGEOSGeometryAccessor<'a> for PolygonArray { &'a self, index: usize, ) -> std::result::Result { - let geom = Polygon::new(&self.coords, &self.geom_offsets, &self.ring_offsets, index); + let geom = self.value(index); (&geom).try_into() } } @@ -325,7 +324,7 @@ impl<'a> ArrayAccessor<'a> for PolygonArray { type ItemGeo = geo::Polygon; unsafe fn value_unchecked(&'a self, index: usize) -> Self::Item { - Polygon::new(&self.coords, &self.geom_offsets, &self.ring_offsets, index) + self.value(index) } } diff --git a/rust/geoarrow/src/scalar/coord/combined/scalar.rs b/rust/geoarrow/src/scalar/coord/combined/scalar.rs index 44753837..1887331f 100644 --- a/rust/geoarrow/src/scalar/coord/combined/scalar.rs +++ b/rust/geoarrow/src/scalar/coord/combined/scalar.rs @@ -6,12 +6,12 @@ use geo_traits::to_geo::ToGeoCoord; use geo_traits::CoordTrait; #[derive(Debug, Clone)] -pub enum Coord<'a> { - Separated(SeparatedCoord<'a>), - Interleaved(InterleavedCoord<'a>), +pub enum Coord { + Separated(SeparatedCoord), + Interleaved(InterleavedCoord), } -impl Coord<'_> { +impl Coord { /// Return `true` if all values in the coordinate are f64::NAN pub(crate) fn is_nan(&self) -> bool { match self { @@ -21,7 +21,7 @@ impl Coord<'_> { } } -impl NativeScalar for Coord<'_> { +impl NativeScalar for Coord { type ScalarGeo = geo::Coord; fn to_geo(&self) -> Self::ScalarGeo { @@ -39,25 +39,25 @@ impl NativeScalar for Coord<'_> { } } -impl From> for geo::Coord { +impl From for geo::Coord { fn from(value: Coord) -> Self { (&value).into() } } -impl From<&Coord<'_>> for geo::Coord { +impl From<&Coord> for geo::Coord { fn from(value: &Coord) -> Self { value.to_coord() } } -impl From> for geo::Point { +impl From for geo::Point { fn from(value: Coord) -> Self { (&value).into() } } -impl From<&Coord<'_>> for geo::Point { +impl From<&Coord> for geo::Point { fn from(value: &Coord) -> Self { match value { Coord::Separated(c) => c.into(), @@ -66,7 +66,7 @@ impl From<&Coord<'_>> for geo::Point { } } -impl RTreeObject for Coord<'_> { +impl RTreeObject for Coord { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -77,25 +77,25 @@ impl RTreeObject for Coord<'_> { } } -impl PartialEq for Coord<'_> { +impl PartialEq for Coord { fn eq(&self, other: &Self) -> bool { self.x_y() == other.x_y() } } -impl PartialEq> for Coord<'_> { - fn eq(&self, other: &InterleavedCoord<'_>) -> bool { +impl PartialEq for Coord { + fn eq(&self, other: &InterleavedCoord) -> bool { self.x_y() == other.x_y() } } -impl PartialEq> for Coord<'_> { - fn eq(&self, other: &SeparatedCoord<'_>) -> bool { +impl PartialEq for Coord { + fn eq(&self, other: &SeparatedCoord) -> bool { self.x_y() == other.x_y() } } -impl CoordTrait for Coord<'_> { +impl CoordTrait for Coord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { @@ -127,7 +127,7 @@ impl CoordTrait for Coord<'_> { } } -impl CoordTrait for &Coord<'_> { +impl CoordTrait for &Coord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { diff --git a/rust/geoarrow/src/scalar/coord/interleaved/scalar.rs b/rust/geoarrow/src/scalar/coord/interleaved/scalar.rs index 9c8cb372..ef6f8931 100644 --- a/rust/geoarrow/src/scalar/coord/interleaved/scalar.rs +++ b/rust/geoarrow/src/scalar/coord/interleaved/scalar.rs @@ -9,20 +9,19 @@ use geo_traits::to_geo::ToGeoCoord; use geo_traits::CoordTrait; #[derive(Debug, Clone)] -pub struct InterleavedCoord<'a> { - pub(crate) coords: &'a ScalarBuffer, - pub(crate) i: usize, +pub struct InterleavedCoord { + pub(crate) coords: ScalarBuffer, pub(crate) dim: Dimension, } -impl InterleavedCoord<'_> { +impl InterleavedCoord { /// Return `true` if all values in the coordinate are f64::NAN pub(crate) fn is_nan(&self) -> bool { (0..self.dim.size()).all(|coord_dim| self.nth_or_panic(coord_dim).is_nan()) } } -impl NativeScalar for InterleavedCoord<'_> { +impl NativeScalar for InterleavedCoord { type ScalarGeo = geo::Coord; fn to_geo(&self) -> Self::ScalarGeo { @@ -40,32 +39,32 @@ impl NativeScalar for InterleavedCoord<'_> { } } -impl From> for geo::Coord { +impl From for geo::Coord { fn from(value: InterleavedCoord) -> Self { (&value).into() } } -impl From<&InterleavedCoord<'_>> for geo::Coord { +impl From<&InterleavedCoord> for geo::Coord { fn from(value: &InterleavedCoord) -> Self { value.to_coord() } } -impl From> for geo::Point { - fn from(value: InterleavedCoord<'_>) -> Self { +impl From for geo::Point { + fn from(value: InterleavedCoord) -> Self { (&value).into() } } -impl From<&InterleavedCoord<'_>> for geo::Point { - fn from(value: &InterleavedCoord<'_>) -> Self { +impl From<&InterleavedCoord> for geo::Point { + fn from(value: &InterleavedCoord) -> Self { let coord: geo::Coord = value.into(); coord.into() } } -impl RTreeObject for InterleavedCoord<'_> { +impl RTreeObject for InterleavedCoord { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -73,19 +72,19 @@ impl RTreeObject for InterleavedCoord<'_> { } } -impl PartialEq for InterleavedCoord<'_> { +impl PartialEq for InterleavedCoord { fn eq(&self, other: &Self) -> bool { coord_eq(self, other) } } -impl PartialEq> for InterleavedCoord<'_> { - fn eq(&self, other: &SeparatedCoord<'_>) -> bool { +impl PartialEq for InterleavedCoord { + fn eq(&self, other: &SeparatedCoord) -> bool { coord_eq(self, other) } } -impl CoordTrait for InterleavedCoord<'_> { +impl CoordTrait for InterleavedCoord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { @@ -94,19 +93,19 @@ impl CoordTrait for InterleavedCoord<'_> { fn nth_or_panic(&self, n: usize) -> Self::T { debug_assert!(n < self.dim.size()); - *self.coords.get(self.i * self.dim.size() + n).unwrap() + *self.coords.get(n).unwrap() } fn x(&self) -> Self::T { - *self.coords.get(self.i * self.dim.size()).unwrap() + *self.coords.get(0).unwrap() } fn y(&self) -> Self::T { - *self.coords.get(self.i * self.dim.size() + 1).unwrap() + *self.coords.get(1).unwrap() } } -impl CoordTrait for &InterleavedCoord<'_> { +impl CoordTrait for &InterleavedCoord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { @@ -115,15 +114,15 @@ impl CoordTrait for &InterleavedCoord<'_> { fn nth_or_panic(&self, n: usize) -> Self::T { debug_assert!(n < self.dim.size()); - *self.coords.get(self.i * self.dim.size() + n).unwrap() + *self.coords.get(n).unwrap() } fn x(&self) -> Self::T { - *self.coords.get(self.i * self.dim.size()).unwrap() + *self.coords.get(0).unwrap() } fn y(&self) -> Self::T { - *self.coords.get(self.i * self.dim.size() + 1).unwrap() + *self.coords.get(1).unwrap() } } diff --git a/rust/geoarrow/src/scalar/coord/separated/scalar.rs b/rust/geoarrow/src/scalar/coord/separated/scalar.rs index 0a71b5aa..92ca21a5 100644 --- a/rust/geoarrow/src/scalar/coord/separated/scalar.rs +++ b/rust/geoarrow/src/scalar/coord/separated/scalar.rs @@ -8,20 +8,19 @@ use geo_traits::CoordTrait; use rstar::{RTreeObject, AABB}; #[derive(Debug, Clone)] -pub struct SeparatedCoord<'a> { - pub(crate) buffers: &'a [ScalarBuffer; 4], - pub(crate) i: usize, +pub struct SeparatedCoord { + pub(crate) buffers: [ScalarBuffer; 4], pub(crate) dim: Dimension, } -impl SeparatedCoord<'_> { +impl SeparatedCoord { /// Return `true` if all values in the coordinate are f64::NAN pub(crate) fn is_nan(&self) -> bool { (0..self.dim.size()).all(|coord_dim| self.nth_or_panic(coord_dim).is_nan()) } } -impl NativeScalar for SeparatedCoord<'_> { +impl NativeScalar for SeparatedCoord { type ScalarGeo = geo::Coord; fn to_geo(&self) -> Self::ScalarGeo { @@ -39,31 +38,31 @@ impl NativeScalar for SeparatedCoord<'_> { } } -impl From> for geo::Coord { +impl From for geo::Coord { fn from(value: SeparatedCoord) -> Self { (&value).into() } } -impl From<&SeparatedCoord<'_>> for geo::Coord { +impl From<&SeparatedCoord> for geo::Coord { fn from(value: &SeparatedCoord) -> Self { value.to_coord() } } -impl From> for geo::Point { - fn from(value: SeparatedCoord<'_>) -> Self { +impl From for geo::Point { + fn from(value: SeparatedCoord) -> Self { (&value).into() } } -impl From<&SeparatedCoord<'_>> for geo::Point { - fn from(value: &SeparatedCoord<'_>) -> Self { +impl From<&SeparatedCoord> for geo::Point { + fn from(value: &SeparatedCoord) -> Self { let coord: geo::Coord = value.into(); coord.into() } } -impl RTreeObject for SeparatedCoord<'_> { +impl RTreeObject for SeparatedCoord { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -71,19 +70,19 @@ impl RTreeObject for SeparatedCoord<'_> { } } -impl PartialEq for SeparatedCoord<'_> { +impl PartialEq for SeparatedCoord { fn eq(&self, other: &SeparatedCoord) -> bool { coord_eq(self, other) } } -impl PartialEq> for SeparatedCoord<'_> { +impl PartialEq for SeparatedCoord { fn eq(&self, other: &InterleavedCoord) -> bool { coord_eq(self, other) } } -impl CoordTrait for SeparatedCoord<'_> { +impl CoordTrait for SeparatedCoord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { @@ -91,19 +90,19 @@ impl CoordTrait for SeparatedCoord<'_> { } fn nth_or_panic(&self, n: usize) -> Self::T { - self.buffers[n][self.i] + self.buffers[n][0] } fn x(&self) -> Self::T { - self.buffers[0][self.i] + self.buffers[0][0] } fn y(&self) -> Self::T { - self.buffers[1][self.i] + self.buffers[1][0] } } -impl CoordTrait for &SeparatedCoord<'_> { +impl CoordTrait for &SeparatedCoord { type T = f64; fn dim(&self) -> geo_traits::Dimensions { @@ -111,15 +110,15 @@ impl CoordTrait for &SeparatedCoord<'_> { } fn nth_or_panic(&self, n: usize) -> Self::T { - self.buffers[n][self.i] + self.buffers[n][0] } fn x(&self) -> Self::T { - self.buffers[0][self.i] + self.buffers[0][0] } fn y(&self) -> Self::T { - self.buffers[1][self.i] + self.buffers[1][0] } } diff --git a/rust/geoarrow/src/scalar/linestring/scalar.rs b/rust/geoarrow/src/scalar/linestring.rs similarity index 58% rename from rust/geoarrow/src/scalar/linestring/scalar.rs rename to rust/geoarrow/src/scalar/linestring.rs index b27508ea..f2b061d8 100644 --- a/rust/geoarrow/src/scalar/linestring/scalar.rs +++ b/rust/geoarrow/src/scalar/linestring.rs @@ -1,52 +1,40 @@ use crate::algorithm::native::bounding_rect::bounding_rect_linestring; use crate::algorithm::native::eq::line_string_eq; use crate::array::util::OffsetBufferUtils; -use crate::array::CoordBuffer; +use crate::array::LineStringArray; use crate::scalar::Coord; use crate::trait_::NativeScalar; -use arrow_buffer::OffsetBuffer; +use crate::{ArrayBase, NativeArray}; use geo_traits::to_geo::ToGeoLineString; use geo_traits::LineStringTrait; use rstar::{RTreeObject, AABB}; /// An Arrow equivalent of a LineString +/// +/// This is stored as a [LineStringArray] with length 1. That element may not be null. #[derive(Debug, Clone)] -pub struct LineString<'a> { - pub(crate) coords: &'a CoordBuffer, - - /// Offsets into the coordinate array where each geometry starts - pub(crate) geom_offsets: &'a OffsetBuffer, - - pub(crate) geom_index: usize, - +pub struct LineString { + array: LineStringArray, start_offset: usize, } -impl<'a> LineString<'a> { - pub fn new( - coords: &'a CoordBuffer, - geom_offsets: &'a OffsetBuffer, - geom_index: usize, - ) -> Self { - let (start_offset, _) = geom_offsets.start_end(geom_index); +impl LineString { + pub fn new(array: LineStringArray) -> Self { + assert_eq!(array.len(), 1); + assert!(!array.is_null(0)); + let (start_offset, _) = array.geom_offsets.start_end(0); Self { - coords, - geom_offsets, - geom_index, + array, start_offset, } } - pub fn into_owned_inner(self) -> (CoordBuffer, OffsetBuffer, usize) { - ( - self.coords.clone(), - self.geom_offsets.clone(), - self.geom_index, - ) + pub fn into_inner(self) -> LineStringArray { + self.array } } -impl NativeScalar for LineString<'_> { +impl NativeScalar for LineString { type ScalarGeo = geo::LineString; fn to_geo(&self) -> Self::ScalarGeo { @@ -63,67 +51,67 @@ impl NativeScalar for LineString<'_> { } } -impl<'a> LineStringTrait for LineString<'a> { +impl<'a> LineStringTrait for LineString { type T = f64; type CoordType<'b> - = Coord<'a> + = Coord where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() + self.0.dimension().into() } fn num_coords(&self) -> usize { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.0.geom_offsets.start_end(0); end - start } unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> { - self.coords.value(self.start_offset + i) + self.array.coords.value(self.start_offset + i) } } -impl<'a> LineStringTrait for &'a LineString<'a> { +impl<'a> LineStringTrait for &'a LineString { type T = f64; type CoordType<'b> - = Coord<'a> + = Coord where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() + self.0.dimension().into() } fn num_coords(&self) -> usize { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.0.geom_offsets.start_end(0); end - start } unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> { - self.coords.value(self.start_offset + i) + self.array.coords.value(self.start_offset + i) } } -impl From> for geo::LineString { - fn from(value: LineString<'_>) -> Self { +impl From for geo::LineString { + fn from(value: LineString) -> Self { (&value).into() } } -impl From<&LineString<'_>> for geo::LineString { - fn from(value: &LineString<'_>) -> Self { +impl From<&LineString> for geo::LineString { + fn from(value: &LineString) -> Self { value.to_line_string() } } -impl From> for geo::Geometry { - fn from(value: LineString<'_>) -> Self { +impl From for geo::Geometry { + fn from(value: LineString) -> Self { geo::Geometry::LineString(value.into()) } } -impl RTreeObject for LineString<'_> { +impl RTreeObject for LineString { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -132,7 +120,7 @@ impl RTreeObject for LineString<'_> { } } -impl> PartialEq for LineString<'_> { +impl> PartialEq for LineString { fn eq(&self, other: &G) -> bool { line_string_eq(self, other) } diff --git a/rust/geoarrow/src/scalar/linestring/mod.rs b/rust/geoarrow/src/scalar/linestring/mod.rs deleted file mode 100644 index 79fa8084..00000000 --- a/rust/geoarrow/src/scalar/linestring/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod owned; -mod scalar; - -pub use owned::OwnedLineString; -pub use scalar::LineString; diff --git a/rust/geoarrow/src/scalar/linestring/owned.rs b/rust/geoarrow/src/scalar/linestring/owned.rs deleted file mode 100644 index 199be52b..00000000 --- a/rust/geoarrow/src/scalar/linestring/owned.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::algorithm::native::eq::line_string_eq; -use crate::array::{CoordBuffer, LineStringArray}; -use crate::scalar::{Coord, LineString}; -use arrow_buffer::OffsetBuffer; -use geo_traits::LineStringTrait; - -#[derive(Clone, Debug)] -pub struct OwnedLineString { - coords: CoordBuffer, - - /// Offsets into the coordinate array where each geometry starts - geom_offsets: OffsetBuffer, - - geom_index: usize, -} - -impl OwnedLineString { - pub fn new(coords: CoordBuffer, geom_offsets: OffsetBuffer, geom_index: usize) -> Self { - Self { - coords, - geom_offsets, - geom_index, - } - } -} - -impl<'a> From<&'a OwnedLineString> for LineString<'a> { - fn from(value: &'a OwnedLineString) -> Self { - Self::new(&value.coords, &value.geom_offsets, value.geom_index) - } -} - -impl From for geo::LineString { - fn from(value: OwnedLineString) -> Self { - let geom = LineString::from(&value); - geom.into() - } -} - -impl<'a> From> for OwnedLineString { - fn from(value: LineString<'a>) -> Self { - let (coords, geom_offsets, geom_index) = value.into_owned_inner(); - Self::new(coords, geom_offsets, geom_index) - } -} - -impl From for LineStringArray { - fn from(value: OwnedLineString) -> Self { - Self::new(value.coords, value.geom_offsets, None, Default::default()) - } -} - -impl LineStringTrait for OwnedLineString { - type T = f64; - type CoordType<'b> - = Coord<'b> - where - Self: 'b; - - fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() - } - - fn num_coords(&self) -> usize { - LineString::from(self).num_coords() - } - - unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> { - LineString::from(self).coord_unchecked(i) - } -} - -impl> PartialEq for OwnedLineString { - fn eq(&self, other: &G) -> bool { - line_string_eq(self, other) - } -} diff --git a/rust/geoarrow/src/scalar/mod.rs b/rust/geoarrow/src/scalar/mod.rs index 34d5c37f..9975b64a 100644 --- a/rust/geoarrow/src/scalar/mod.rs +++ b/rust/geoarrow/src/scalar/mod.rs @@ -1,17 +1,17 @@ -//! GeoArrow scalars, which are references onto a full GeoArrow array at a specific index. +//! GeoArrow scalars, which are slices of a full GeoArrow array at a specific index. #![allow(missing_docs)] // FIXME -pub use binary::{OwnedWKB, WKB}; +pub use binary::WKB; pub use coord::{Coord, InterleavedCoord, SeparatedCoord}; -pub use geometry::{Geometry, OwnedGeometry}; -pub use geometrycollection::{GeometryCollection, OwnedGeometryCollection}; -pub use linestring::{LineString, OwnedLineString}; -pub use multilinestring::{MultiLineString, OwnedMultiLineString}; -pub use multipoint::{MultiPoint, OwnedMultiPoint}; -pub use multipolygon::{MultiPolygon, OwnedMultiPolygon}; -pub use point::{OwnedPoint, Point}; -pub use polygon::{OwnedPolygon, Polygon}; +pub use geometry::Geometry; +pub use geometrycollection::GeometryCollection; +pub use linestring::LineString; +pub use multilinestring::MultiLineString; +pub use multipoint::MultiPoint; +pub use multipolygon::MultiPolygon; +pub use point::Point; +pub use polygon::Polygon; pub use rect::{OwnedRect, Rect}; pub use scalar::GeometryScalar; diff --git a/rust/geoarrow/src/scalar/point/scalar.rs b/rust/geoarrow/src/scalar/point.rs similarity index 69% rename from rust/geoarrow/src/scalar/point/scalar.rs rename to rust/geoarrow/src/scalar/point.rs index 2fe4cd7c..30bae12f 100644 --- a/rust/geoarrow/src/scalar/point/scalar.rs +++ b/rust/geoarrow/src/scalar/point.rs @@ -1,30 +1,32 @@ use crate::algorithm::native::bounding_rect::bounding_rect_point; use crate::algorithm::native::eq::point_eq; -use crate::array::CoordBuffer; +use crate::array::PointArray; use crate::scalar::Coord; -use crate::trait_::NativeScalar; +use crate::trait_::{ArrayAccessor, NativeScalar}; +use crate::{ArrayBase, NativeArray}; use geo_traits::to_geo::ToGeoPoint; use geo_traits::PointTrait; use rstar::{RTreeObject, AABB}; /// An Arrow equivalent of a Point +/// +/// This is stored as a [PointArray] with length 1. That element may not be null. #[derive(Debug, Clone)] -pub struct Point<'a> { - coords: &'a CoordBuffer, - geom_index: usize, -} +pub struct Point(PointArray); -impl<'a> Point<'a> { - pub fn new(coords: &'a CoordBuffer, geom_index: usize) -> Self { - Point { coords, geom_index } +impl Point { + pub fn new(arr: PointArray) -> Self { + assert_eq!(arr.len(), 1); + assert!(!arr.is_null(0)); + Self(arr) } - pub fn into_owned_inner(self) -> (CoordBuffer, usize) { - (self.coords.clone(), self.geom_index) + pub fn into_inner(self) -> PointArray { + self.0 } } -impl NativeScalar for Point<'_> { +impl NativeScalar for Point { type ScalarGeo = geo::Point; fn to_geo(&self) -> Self::ScalarGeo { @@ -41,19 +43,19 @@ impl NativeScalar for Point<'_> { } } -impl<'a> PointTrait for Point<'a> { +impl PointTrait for Point { type T = f64; type CoordType<'b> - = Coord<'a> + = Coord where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() + self.0.dimension().into() } fn coord(&self) -> Option> { - let coord = self.coords.value(self.geom_index); + let coord = self.0.value(0); if coord.is_nan() { None } else { @@ -62,19 +64,19 @@ impl<'a> PointTrait for Point<'a> { } } -impl<'a> PointTrait for &Point<'a> { +impl<'a> PointTrait for &Point { type T = f64; type CoordType<'b> - = Coord<'a> + = Coord where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() + self.0.dimension().into() } fn coord(&self) -> Option> { - let coord = self.coords.value(self.geom_index); + let coord = self.0.value(0); if coord.is_nan() { None } else { @@ -83,25 +85,25 @@ impl<'a> PointTrait for &Point<'a> { } } -impl From> for geo::Point { - fn from(value: Point<'_>) -> Self { +impl From for geo::Point { + fn from(value: Point) -> Self { (&value).into() } } -impl From<&Point<'_>> for geo::Point { - fn from(value: &Point<'_>) -> Self { +impl From<&Point> for geo::Point { + fn from(value: &Point) -> Self { value.to_point() } } -impl From> for geo::Geometry { - fn from(value: Point<'_>) -> Self { +impl From for geo::Geometry { + fn from(value: Point) -> Self { geo::Geometry::Point(value.into()) } } -impl RTreeObject for Point<'_> { +impl RTreeObject for Point { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -110,7 +112,7 @@ impl RTreeObject for Point<'_> { } } -impl> PartialEq for Point<'_> { +impl> PartialEq for Point { fn eq(&self, other: &G) -> bool { point_eq(self, other) } diff --git a/rust/geoarrow/src/scalar/point/mod.rs b/rust/geoarrow/src/scalar/point/mod.rs deleted file mode 100644 index a37095e7..00000000 --- a/rust/geoarrow/src/scalar/point/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod owned; -mod scalar; - -pub use owned::OwnedPoint; -pub use scalar::Point; diff --git a/rust/geoarrow/src/scalar/point/owned.rs b/rust/geoarrow/src/scalar/point/owned.rs deleted file mode 100644 index f3041ea9..00000000 --- a/rust/geoarrow/src/scalar/point/owned.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::algorithm::native::eq::point_eq; -use crate::array::{CoordBuffer, PointArray}; -use crate::scalar::{Coord, Point}; -use geo_traits::to_geo::ToGeoPoint; -use geo_traits::PointTrait; - -#[derive(Clone, Debug)] -pub struct OwnedPoint { - coords: CoordBuffer, - geom_index: usize, -} - -impl OwnedPoint { - pub fn new(coords: CoordBuffer, geom_index: usize) -> Self { - Self { coords, geom_index } - } - - pub fn coord(&self) -> Coord { - self.coords.value(self.geom_index) - } -} - -impl<'a> From<&'a OwnedPoint> for Point<'a> { - fn from(value: &'a OwnedPoint) -> Self { - Self::new(&value.coords, value.geom_index) - } -} - -impl<'a> From> for OwnedPoint { - fn from(value: Point<'a>) -> Self { - let (coords, geom_index) = value.into_owned_inner(); - Self::new(coords, geom_index) - } -} - -impl From for PointArray { - fn from(value: OwnedPoint) -> Self { - Self::new(value.coords, None, Default::default()) - } -} - -impl PointTrait for OwnedPoint { - type T = f64; - type CoordType<'a> = Coord<'a>; - - fn dim(&self) -> geo_traits::Dimensions { - self.coords.dim().into() - } - - fn coord(&self) -> Option> { - let coord = self.coords.value(self.geom_index); - if coord.is_nan() { - None - } else { - Some(coord) - } - } -} - -impl From for geo::Point { - fn from(value: OwnedPoint) -> Self { - (&value).into() - } -} - -impl From<&OwnedPoint> for geo::Point { - fn from(value: &OwnedPoint) -> Self { - value.to_point() - } -} - -impl PartialEq for OwnedPoint { - fn eq(&self, other: &Self) -> bool { - point_eq(self, other) - } -} diff --git a/rust/geoarrow/src/scalar/polygon/scalar.rs b/rust/geoarrow/src/scalar/polygon.rs similarity index 51% rename from rust/geoarrow/src/scalar/polygon/scalar.rs rename to rust/geoarrow/src/scalar/polygon.rs index ec47f02b..43a93066 100644 --- a/rust/geoarrow/src/scalar/polygon/scalar.rs +++ b/rust/geoarrow/src/scalar/polygon.rs @@ -1,59 +1,55 @@ use crate::algorithm::native::bounding_rect::bounding_rect_polygon; use crate::algorithm::native::eq::polygon_eq; use crate::array::util::OffsetBufferUtils; -use crate::array::CoordBuffer; +use crate::array::{LineStringArray, PolygonArray}; use crate::datatypes::Dimension; use crate::scalar::LineString; -use crate::trait_::NativeScalar; -use arrow_buffer::OffsetBuffer; +use crate::trait_::{ArrayAccessor, NativeScalar}; +use crate::ArrayBase; use geo_traits::to_geo::ToGeoPolygon; use geo_traits::PolygonTrait; use rstar::{RTreeObject, AABB}; /// An Arrow equivalent of a Polygon +/// +/// This is stored as a [PolygonArray] with length 1. That element may not be null. #[derive(Debug, Clone)] -pub struct Polygon<'a> { - pub(crate) coords: &'a CoordBuffer, +pub struct Polygon { + array: PolygonArray, + start_offset: usize, +} - /// Offsets into the ring array where each geometry starts - pub(crate) geom_offsets: &'a OffsetBuffer, +// <'a> { +// pub(crate) coords: &'a CoordBuffer, - /// Offsets into the coordinate array where each ring starts - pub(crate) ring_offsets: &'a OffsetBuffer, +// /// Offsets into the ring array where each geometry starts +// pub(crate) geom_offsets: &'a OffsetBuffer, - pub(crate) geom_index: usize, +// /// Offsets into the coordinate array where each ring starts +// pub(crate) ring_offsets: &'a OffsetBuffer, - start_offset: usize, -} +// pub(crate) geom_index: usize, + +// start_offset: usize, +// } -impl<'a> Polygon<'a> { - pub fn new( - coords: &'a CoordBuffer, - geom_offsets: &'a OffsetBuffer, - ring_offsets: &'a OffsetBuffer, - geom_index: usize, - ) -> Self { - let (start_offset, _) = geom_offsets.start_end(geom_index); +impl Polygon { + pub fn new(array: PolygonArray) -> Self { + assert_eq!(array.len(), 1); + assert!(!array.is_null(0)); + let (start_offset, _) = array.geom_offsets.start_end(0); Self { - coords, - geom_offsets, - ring_offsets, - geom_index, + array, start_offset, } } - pub fn into_owned_inner(self) -> (CoordBuffer, OffsetBuffer, OffsetBuffer, usize) { - ( - self.coords.clone(), - self.geom_offsets.clone(), - self.ring_offsets.clone(), - self.geom_index, - ) + pub fn into_inner(self) -> PolygonArray { + self.array } } -impl NativeScalar for Polygon<'_> { +impl NativeScalar for Polygon { type ScalarGeo = geo::Polygon; fn to_geo(&self) -> Self::ScalarGeo { @@ -70,91 +66,115 @@ impl NativeScalar for Polygon<'_> { } } -impl<'a> PolygonTrait for Polygon<'a> { +impl<'a> PolygonTrait for Polygon { type T = f64; type RingType<'b> - = LineString<'a> + = LineString where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - match self.coords.dim() { + match self.array.coords.dim() { Dimension::XY => geo_traits::Dimensions::Xy, Dimension::XYZ => geo_traits::Dimensions::Xyz, } } fn exterior(&self) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.array.geom_offsets.start_end(0); if start == end { None } else { - Some(LineString::new(self.coords, self.ring_offsets, start)) + let arr = LineStringArray::new( + self.array.coords.clone(), + self.array.ring_offsets.clone(), + None, + Default::default(), + ); + Some(arr.value(start)) } } fn num_interiors(&self) -> usize { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.array.geom_offsets.start_end(0); end - start - 1 } unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> { - LineString::new(self.coords, self.ring_offsets, self.start_offset + 1 + i) + let arr = LineStringArray::new( + self.array.coords.clone(), + self.array.ring_offsets.clone(), + None, + Default::default(), + ); + arr.value(self.start_offset + 1 + i) } } -impl<'a> PolygonTrait for &'a Polygon<'a> { +impl<'a> PolygonTrait for &'a Polygon { type T = f64; type RingType<'b> - = LineString<'a> + = LineString where Self: 'b; fn dim(&self) -> geo_traits::Dimensions { - match self.coords.dim() { + match self.array.coords.dim() { Dimension::XY => geo_traits::Dimensions::Xy, Dimension::XYZ => geo_traits::Dimensions::Xyz, } } fn exterior(&self) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.array.geom_offsets.start_end(0); if start == end { None } else { - Some(LineString::new(self.coords, self.ring_offsets, start)) + let arr = LineStringArray::new( + self.array.coords.clone(), + self.array.ring_offsets.clone(), + None, + Default::default(), + ); + Some(arr.value(start)) } } fn num_interiors(&self) -> usize { - let (start, end) = self.geom_offsets.start_end(self.geom_index); + let (start, end) = self.array.geom_offsets.start_end(0); end - start - 1 } unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> { - LineString::new(self.coords, self.ring_offsets, self.start_offset + 1 + i) + let arr = LineStringArray::new( + self.array.coords.clone(), + self.array.ring_offsets.clone(), + None, + Default::default(), + ); + arr.value(self.start_offset + 1 + i) } } -impl From> for geo::Polygon { - fn from(value: Polygon<'_>) -> Self { +impl From for geo::Polygon { + fn from(value: Polygon) -> Self { (&value).into() } } -impl From<&Polygon<'_>> for geo::Polygon { - fn from(value: &Polygon<'_>) -> Self { +impl From<&Polygon> for geo::Polygon { + fn from(value: &Polygon) -> Self { value.to_polygon() } } -impl From> for geo::Geometry { - fn from(value: Polygon<'_>) -> Self { +impl From for geo::Geometry { + fn from(value: Polygon) -> Self { geo::Geometry::Polygon(value.into()) } } -impl RTreeObject for Polygon<'_> { +impl RTreeObject for Polygon { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { @@ -163,7 +183,7 @@ impl RTreeObject for Polygon<'_> { } } -impl> PartialEq for Polygon<'_> { +impl> PartialEq for Polygon { fn eq(&self, other: &G) -> bool { polygon_eq(self, other) } diff --git a/rust/geoarrow/src/scalar/polygon/mod.rs b/rust/geoarrow/src/scalar/polygon/mod.rs deleted file mode 100644 index 1ce32ec5..00000000 --- a/rust/geoarrow/src/scalar/polygon/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod owned; -mod scalar; - -pub use owned::OwnedPolygon; -pub use scalar::Polygon; diff --git a/rust/geoarrow/src/scalar/polygon/owned.rs b/rust/geoarrow/src/scalar/polygon/owned.rs deleted file mode 100644 index 36c5eaef..00000000 --- a/rust/geoarrow/src/scalar/polygon/owned.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::algorithm::native::eq::polygon_eq; -use crate::array::{CoordBuffer, PolygonArray}; -use crate::datatypes::Dimension; -use crate::scalar::{LineString, Polygon}; -use arrow_buffer::OffsetBuffer; -use geo_traits::PolygonTrait; - -#[derive(Clone, Debug)] -pub struct OwnedPolygon { - coords: CoordBuffer, - - /// Offsets into the coordinate array where each geometry starts - geom_offsets: OffsetBuffer, - - ring_offsets: OffsetBuffer, - - geom_index: usize, -} - -impl OwnedPolygon { - pub fn new( - coords: CoordBuffer, - geom_offsets: OffsetBuffer, - ring_offsets: OffsetBuffer, - geom_index: usize, - ) -> Self { - Self { - coords, - geom_offsets, - ring_offsets, - geom_index, - } - } -} - -impl<'a> From<&'a OwnedPolygon> for Polygon<'a> { - fn from(value: &'a OwnedPolygon) -> Self { - Self::new( - &value.coords, - &value.geom_offsets, - &value.ring_offsets, - value.geom_index, - ) - } -} - -impl From for geo::Polygon { - fn from(value: OwnedPolygon) -> Self { - let geom = Polygon::from(&value); - geom.into() - } -} - -impl<'a> From> for OwnedPolygon { - fn from(value: Polygon<'a>) -> Self { - let (coords, geom_offsets, ring_offsets, geom_index) = value.into_owned_inner(); - Self::new(coords, geom_offsets, ring_offsets, geom_index) - } -} - -impl From for PolygonArray { - fn from(value: OwnedPolygon) -> Self { - Self::new( - value.coords, - value.geom_offsets, - value.ring_offsets, - None, - Default::default(), - ) - } -} - -impl PolygonTrait for OwnedPolygon { - type T = f64; - type RingType<'b> - = LineString<'b> - where - Self: 'b; - - fn dim(&self) -> geo_traits::Dimensions { - match self.coords.dim() { - Dimension::XY => geo_traits::Dimensions::Xy, - Dimension::XYZ => geo_traits::Dimensions::Xyz, - } - } - - fn exterior(&self) -> Option> { - Polygon::from(self).exterior() - } - - fn num_interiors(&self) -> usize { - Polygon::from(self).num_interiors() - } - - unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> { - Polygon::from(self).interior_unchecked(i) - } -} - -impl> PartialEq for OwnedPolygon { - fn eq(&self, other: &G) -> bool { - polygon_eq(self, other) - } -}