diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fb1fd12a..4ff3ceee7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: name: Lint and Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 759077322..d76715ff9 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -15,7 +15,7 @@ jobs: working-directory: python/core steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: "recursive" @@ -49,7 +49,7 @@ jobs: # name: Lint Python code # runs-on: ubuntu-latest # steps: - # - uses: actions/checkout@v3 + # - uses: actions/checkout@v4 # - name: Set up Python 3.8 # uses: actions/setup-python@v2 @@ -73,7 +73,7 @@ jobs: working-directory: python/core steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: "recursive" diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 0c13250fc..7cb7c4bb2 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -15,7 +15,7 @@ jobs: working-directory: js steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable @@ -48,7 +48,7 @@ jobs: working-directory: js steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable diff --git a/python/.github/workflows/CI.yml b/python/.github/workflows/CI.yml deleted file mode 100644 index 8c6a5eaf5..000000000 --- a/python/.github/workflows/CI.yml +++ /dev/null @@ -1,120 +0,0 @@ -# This file is autogenerated by maturin v1.2.0 -# To update, run -# -# maturin generate-ci github -# -name: CI - -on: - push: - branches: - - main - - master - tags: - - '*' - pull_request: - workflow_dispatch: - -permissions: - contents: read - -jobs: - linux: - runs-on: ubuntu-latest - strategy: - matrix: - target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist --find-interpreter - sccache: 'true' - manylinux: auto - - name: Upload wheels - uses: actions/upload-artifact@v3 - with: - name: wheels - path: dist - - windows: - runs-on: windows-latest - strategy: - matrix: - target: [x64, x86] - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - architecture: ${{ matrix.target }} - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist --find-interpreter - sccache: 'true' - - name: Upload wheels - uses: actions/upload-artifact@v3 - with: - name: wheels - path: dist - - macos: - runs-on: macos-latest - strategy: - matrix: - target: [x86_64, aarch64] - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist --find-interpreter - sccache: 'true' - - name: Upload wheels - uses: actions/upload-artifact@v3 - with: - name: wheels - path: dist - - sdist: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Build sdist - uses: PyO3/maturin-action@v1 - with: - command: sdist - args: --out dist - - name: Upload sdist - uses: actions/upload-artifact@v3 - with: - name: wheels - path: dist - - release: - name: Release - runs-on: ubuntu-latest - if: "startsWith(github.ref, 'refs/tags/')" - needs: [linux, windows, macos, sdist] - steps: - - uses: actions/download-artifact@v3 - with: - name: wheels - - name: Publish to PyPI - uses: PyO3/maturin-action@v1 - env: - MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} - with: - command: upload - args: --skip-existing * diff --git a/src/array/geometrycollection/array.rs b/src/array/geometrycollection/array.rs index ed7b0b255..877f2ab89 100644 --- a/src/array/geometrycollection/array.rs +++ b/src/array/geometrycollection/array.rs @@ -208,11 +208,7 @@ impl<'a, O: OffsetSizeTrait> GeometryArrayAccessor<'a> for GeometryCollectionArr type ItemGeo = geo::GeometryCollection; unsafe fn value_unchecked(&'a self, index: usize) -> Self::Item { - GeometryCollection { - array: &self.array, - geom_offsets: &self.geom_offsets, - geom_index: index, - } + GeometryCollection::new(&self.array, &self.geom_offsets, index) } } diff --git a/src/geo_traits/geometry_collection.rs b/src/geo_traits/geometry_collection.rs index 1c724c8fc..0a9a0c3f3 100644 --- a/src/geo_traits/geometry_collection.rs +++ b/src/geo_traits/geometry_collection.rs @@ -1,25 +1,37 @@ +use super::iterator::GeometryCollectionIterator; use super::GeometryTrait; use geo::{CoordNum, Geometry, GeometryCollection}; -use std::slice::Iter; -pub trait GeometryCollectionTrait { +pub trait GeometryCollectionTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + GeometryTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; /// An iterator over the geometries in this GeometryCollection - fn geometries(&self) -> Self::Iter<'_>; + fn geometries(&self) -> GeometryCollectionIterator<'_, Self::T, Self::ItemType<'_>, Self> { + GeometryCollectionIterator::new(self, 0, self.num_geometries()) + } /// The number of geometries in this GeometryCollection fn num_geometries(&self) -> usize; /// Access to a specified geometry in this GeometryCollection /// Will return None if the provided index is out of bounds - fn geometry(&self, i: usize) -> Option>; + fn geometry(&self, i: usize) -> Option> { + if i >= self.num_geometries() { + None + } else { + unsafe { Some(self.geometry_unchecked(i)) } + } + } + + /// Access to a specified geometry in this GeometryCollection + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn geometry_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl GeometryCollectionTrait for GeometryCollection { @@ -27,19 +39,13 @@ impl GeometryCollectionTrait for GeometryCollection { type ItemType<'a> = &'a Geometry where Self: 'a; - type Iter<'a> = Iter<'a, Geometry> - where T: 'a; - - fn geometries(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_geometries(&self) -> usize { self.0.len() } - fn geometry(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn geometry_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } @@ -47,18 +53,12 @@ impl<'a, T: CoordNum> GeometryCollectionTrait for &'a GeometryCollection { type T = T; type ItemType<'b> = &'a Geometry where Self: 'b; - type Iter<'b> = Iter<'a, Geometry> where - Self: 'b; - - fn geometries(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_geometries(&self) -> usize { self.0.len() } - fn geometry(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn geometry_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } diff --git a/src/geo_traits/iterator.rs b/src/geo_traits/iterator.rs new file mode 100644 index 000000000..e75778eb6 --- /dev/null +++ b/src/geo_traits/iterator.rs @@ -0,0 +1,112 @@ +use super::{ + CoordTrait, GeometryCollectionTrait, GeometryTrait, LineStringTrait, MultiLineStringTrait, + MultiPointTrait, MultiPolygonTrait, PointTrait, PolygonTrait, +}; +use geo::CoordNum; + +macro_rules! impl_iterator { + ($struct_name:ident, $self_trait:ident, $item_trait:ident, $access_method:ident) => { + pub struct $struct_name< + 'a, + T: CoordNum, + ItemType: 'a + $item_trait, + G: $self_trait = ItemType>, + > { + geom: &'a G, + index: usize, + end: usize, + } + + impl< + 'a, + T: CoordNum, + ItemType: 'a + $item_trait, + G: $self_trait = ItemType>, + > $struct_name<'a, T, ItemType, G> + { + pub fn new(geom: &'a G, index: usize, end: usize) -> Self { + Self { geom, index, end } + } + } + + impl< + 'a, + T: CoordNum, + ItemType: 'a + $item_trait, + G: $self_trait = ItemType>, + > Iterator for $struct_name<'a, T, ItemType, G> + { + type Item = ItemType; + + #[inline] + fn next(&mut self) -> Option { + if self.index == self.end { + return None; + } + let old = self.index; + self.index += 1; + unsafe { Some(self.geom.$access_method(old)) } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.end - self.index, Some(self.end - self.index)) + } + } + + impl< + 'a, + T: CoordNum, + ItemType: 'a + $item_trait, + G: $self_trait = ItemType>, + > DoubleEndedIterator for $struct_name<'a, T, ItemType, G> + { + #[inline] + fn next_back(&mut self) -> Option { + if self.index == self.end { + None + } else { + self.end -= 1; + unsafe { Some(self.geom.$access_method(self.end)) } + } + } + } + }; +} + +impl_iterator!( + LineStringIterator, + LineStringTrait, + CoordTrait, + coord_unchecked +); +impl_iterator!( + PolygonInteriorIterator, + PolygonTrait, + LineStringTrait, + interior_unchecked +); +impl_iterator!( + MultiPointIterator, + MultiPointTrait, + PointTrait, + point_unchecked +); +impl_iterator!( + MultiLineStringIterator, + MultiLineStringTrait, + LineStringTrait, + line_unchecked +); +impl_iterator!( + MultiPolygonIterator, + MultiPolygonTrait, + PolygonTrait, + polygon_unchecked +); +impl_iterator!( + GeometryCollectionIterator, + GeometryCollectionTrait, + GeometryTrait, + geometry_unchecked +); diff --git a/src/geo_traits/line_string.rs b/src/geo_traits/line_string.rs index 6ea897a6a..85eb97c5c 100644 --- a/src/geo_traits/line_string.rs +++ b/src/geo_traits/line_string.rs @@ -1,59 +1,62 @@ +use super::iterator::LineStringIterator; use super::CoordTrait; use geo::{Coord, CoordNum, LineString}; -use std::slice::Iter; -pub trait LineStringTrait { +pub trait LineStringTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + CoordTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; /// An iterator over the coords in this LineString - fn coords(&self) -> Self::Iter<'_>; + fn coords(&self) -> LineStringIterator<'_, Self::T, Self::ItemType<'_>, Self> { + LineStringIterator::new(self, 0, self.num_coords()) + } /// The number of coords in this LineString fn num_coords(&self) -> usize; /// Access to a specified point in this LineString /// Will return None if the provided index is out of bounds - fn coord(&self, i: usize) -> Option>; + #[inline] + fn coord(&self, i: usize) -> Option> { + if i >= self.num_coords() { + None + } else { + unsafe { Some(self.coord_unchecked(i)) } + } + } + + /// Access to a specified point in this LineString + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl LineStringTrait for LineString { type T = T; type ItemType<'a> = &'a Coord where Self: 'a; - type Iter<'a> = Iter<'a, Coord> where T: 'a; - - fn coords(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_coords(&self) -> usize { self.0.len() } - fn coord(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } impl<'a, T: CoordNum> LineStringTrait for &'a LineString { type T = T; type ItemType<'b> = &'a Coord where Self: 'b; - type Iter<'b> = Iter<'a, Coord> where Self: 'b; - - fn coords(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_coords(&self) -> usize { self.0.len() } - fn coord(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } diff --git a/src/geo_traits/mod.rs b/src/geo_traits/mod.rs index d5ab31c68..5580ad1b1 100644 --- a/src/geo_traits/mod.rs +++ b/src/geo_traits/mod.rs @@ -19,6 +19,7 @@ pub use rect::RectTrait; mod coord; mod geometry; mod geometry_collection; +mod iterator; mod line_string; mod multi_line_string; mod multi_point; diff --git a/src/geo_traits/multi_line_string.rs b/src/geo_traits/multi_line_string.rs index f6e6c249d..cdedad3b4 100644 --- a/src/geo_traits/multi_line_string.rs +++ b/src/geo_traits/multi_line_string.rs @@ -1,59 +1,61 @@ +use super::iterator::MultiLineStringIterator; use super::line_string::LineStringTrait; use geo::{CoordNum, LineString, MultiLineString}; -use std::slice::Iter; -pub trait MultiLineStringTrait { +pub trait MultiLineStringTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + LineStringTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; /// An iterator over the LineStrings in this MultiLineString - fn lines(&self) -> Self::Iter<'_>; + fn lines(&self) -> MultiLineStringIterator<'_, Self::T, Self::ItemType<'_>, Self> { + MultiLineStringIterator::new(self, 0, self.num_lines()) + } /// The number of lines in this MultiLineString fn num_lines(&self) -> usize; /// Access to a specified line in this MultiLineString /// Will return None if the provided index is out of bounds - fn line(&self, i: usize) -> Option>; + fn line(&self, i: usize) -> Option> { + if i >= self.num_lines() { + None + } else { + unsafe { Some(self.line_unchecked(i)) } + } + } + + /// Access to a specified line in this MultiLineString + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl MultiLineStringTrait for MultiLineString { type T = T; type ItemType<'a> = &'a LineString where Self: 'a; - type Iter<'a> = Iter<'a, LineString> where T: 'a; - - fn lines(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_lines(&self) -> usize { self.0.len() } - fn line(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } impl<'a, T: CoordNum> MultiLineStringTrait for &'a MultiLineString { type T = T; type ItemType<'b> = &'a LineString where Self: 'b; - type Iter<'b> = Iter<'a, LineString> where Self: 'b; - - fn lines(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_lines(&self) -> usize { self.0.len() } - fn line(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } diff --git a/src/geo_traits/multi_point.rs b/src/geo_traits/multi_point.rs index 7b0ce568d..2d974fa98 100644 --- a/src/geo_traits/multi_point.rs +++ b/src/geo_traits/multi_point.rs @@ -1,59 +1,78 @@ +use super::iterator::MultiPointIterator; use super::point::PointTrait; use geo::{CoordNum, MultiPoint, Point}; -use std::slice::Iter; -pub trait MultiPointTrait { +pub trait MultiPointTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + PointTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; /// An iterator over the points in this MultiPoint - fn points(&self) -> Self::Iter<'_>; + fn points(&self) -> MultiPointIterator<'_, Self::T, Self::ItemType<'_>, Self> { + MultiPointIterator::new(self, 0, self.num_points()) + } /// The number of points in this MultiPoint fn num_points(&self) -> usize; /// Access to a specified point in this MultiPoint /// Will return None if the provided index is out of bounds - fn point(&self, i: usize) -> Option>; + fn point(&self, i: usize) -> Option> { + if i >= self.num_points() { + None + } else { + unsafe { Some(self.point_unchecked(i)) } + } + } + + /// Access to a specified point in this MultiPoint + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl MultiPointTrait for MultiPoint { type T = T; type ItemType<'a> = &'a Point where Self: 'a; - type Iter<'a> = Iter<'a, Point> where T: 'a; - - fn points(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_points(&self) -> usize { self.0.len() } - fn point(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } impl<'a, T: CoordNum> MultiPointTrait for &'a MultiPoint { type T = T; type ItemType<'b> = &'a Point where Self: 'b; - type Iter<'b> = Iter<'a, Point> where Self: 'b; - - fn points(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_points(&self) -> usize { self.0.len() } - fn point(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn tmp() { + let mp = MultiPoint::new(vec![ + Point::new(0.0, 1.0), + Point::new(2.0, 3.0), + Point::new(4.0, 5.0), + ]); + MultiPointTrait::points(&mp).for_each(|p| { + dbg!(p); + }); } } diff --git a/src/geo_traits/multi_polygon.rs b/src/geo_traits/multi_polygon.rs index cd94b2b7f..02579f9b8 100644 --- a/src/geo_traits/multi_polygon.rs +++ b/src/geo_traits/multi_polygon.rs @@ -1,59 +1,61 @@ +use super::iterator::MultiPolygonIterator; use super::polygon::PolygonTrait; use geo::{CoordNum, MultiPolygon, Polygon}; -use std::slice::Iter; -pub trait MultiPolygonTrait { +pub trait MultiPolygonTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + PolygonTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; /// An iterator over the Polygons in this MultiPolygon - fn polygons(&self) -> Self::Iter<'_>; + fn polygons(&self) -> MultiPolygonIterator<'_, Self::T, Self::ItemType<'_>, Self> { + MultiPolygonIterator::new(self, 0, self.num_polygons()) + } /// The number of polygons in this MultiPolygon fn num_polygons(&self) -> usize; /// Access to a specified polygon in this MultiPolygon /// Will return None if the provided index is out of bounds - fn polygon(&self, i: usize) -> Option>; + fn polygon(&self, i: usize) -> Option> { + if i >= self.num_polygons() { + None + } else { + unsafe { Some(self.polygon_unchecked(i)) } + } + } + + /// Access to a specified polygon in this MultiPolygon + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl MultiPolygonTrait for MultiPolygon { type T = T; type ItemType<'a> = &'a Polygon where Self: 'a; - type Iter<'a> = Iter<'a, Polygon> where T: 'a; - - fn polygons(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_polygons(&self) -> usize { self.0.len() } - fn polygon(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } impl<'a, T: CoordNum> MultiPolygonTrait for &'a MultiPolygon { type T = T; type ItemType<'b> = &'a Polygon where Self: 'b; - type Iter<'b> = Iter<'a, Polygon> where Self: 'b; - - fn polygons(&self) -> Self::Iter<'_> { - self.0.iter() - } fn num_polygons(&self) -> usize { self.0.len() } - fn polygon(&self, i: usize) -> Option> { - self.0.get(i) + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.0.get_unchecked(i) } } diff --git a/src/geo_traits/point.rs b/src/geo_traits/point.rs index dc3f89d9c..8680bfe98 100644 --- a/src/geo_traits/point.rs +++ b/src/geo_traits/point.rs @@ -3,13 +3,13 @@ use geo::{Coord, CoordNum, Point}; pub trait PointTrait { type T: CoordNum; - /// x component of this coord + /// x component of this point. fn x(&self) -> Self::T; - /// y component of this coord + /// y component of this point. fn y(&self) -> Self::T; - /// Returns a tuple that contains the x/horizontal & y/vertical component of the coord. + /// Returns a tuple that contains the x/horizontal & y/vertical component of the point. fn x_y(&self) -> (Self::T, Self::T) { (self.x(), self.y()) } diff --git a/src/geo_traits/polygon.rs b/src/geo_traits/polygon.rs index bac4b60ec..2fdb972c9 100644 --- a/src/geo_traits/polygon.rs +++ b/src/geo_traits/polygon.rs @@ -1,13 +1,10 @@ +use super::iterator::PolygonInteriorIterator; use super::line_string::LineStringTrait; use geo::{CoordNum, LineString, Polygon}; -use std::slice::Iter; -pub trait PolygonTrait { +pub trait PolygonTrait: Sized { type T: CoordNum; type ItemType<'a>: 'a + LineStringTrait - where - Self: 'a; - type Iter<'a>: ExactSizeIterator> where Self: 'a; @@ -15,36 +12,46 @@ pub trait PolygonTrait { fn exterior(&self) -> Option>; /// An iterator of the interior rings of this Polygon - fn interiors(&self) -> Self::Iter<'_>; + fn interiors(&self) -> PolygonInteriorIterator<'_, Self::T, Self::ItemType<'_>, Self> { + PolygonInteriorIterator::new(self, 0, self.num_interiors()) + } /// The number of interior rings in this Polygon fn num_interiors(&self) -> usize; /// Access to a specified interior ring in this Polygon /// Will return None if the provided index is out of bounds - fn interior(&self, i: usize) -> Option>; + fn interior(&self, i: usize) -> Option> { + if i >= self.num_interiors() { + None + } else { + unsafe { Some(self.interior_unchecked(i)) } + } + } + + /// Access to a specified interior ring in this Polygon + /// + /// # Safety + /// + /// Accessing an index out of bounds is UB. + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_>; } impl PolygonTrait for Polygon { type T = T; type ItemType<'a> = &'a LineString where Self: 'a; - type Iter<'a> = Iter<'a, LineString> where T: 'a; fn exterior(&self) -> Option> { // geo-types doesn't really have a way to describe an empty polygon Some(Polygon::exterior(self)) } - fn interiors(&self) -> Self::Iter<'_> { - Polygon::interiors(self).iter() - } - fn num_interiors(&self) -> usize { Polygon::interiors(self).len() } - fn interior(&self, i: usize) -> Option> { - Polygon::interiors(self).get(i) + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + unsafe { Polygon::interiors(self).get_unchecked(i) } } } @@ -52,22 +59,17 @@ impl<'a, T: CoordNum> PolygonTrait for &'a Polygon { type T = T; type ItemType<'b> = &'a LineString where Self: 'b; - type Iter<'b> = Iter<'a, LineString> where - Self: 'b; fn exterior(&self) -> Option> { + // geo-types doesn't really have a way to describe an empty polygon Some(Polygon::exterior(self)) } - fn interiors(&self) -> Self::Iter<'_> { - Polygon::interiors(self).iter() - } - fn num_interiors(&self) -> usize { Polygon::interiors(self).len() } - fn interior(&self, i: usize) -> Option> { - Polygon::interiors(self).get(i) + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + unsafe { Polygon::interiors(self).get_unchecked(i) } } } diff --git a/src/io/geos/scalar/linearring.rs b/src/io/geos/scalar/linearring.rs index 8a1986753..ae0f1632f 100644 --- a/src/io/geos/scalar/linearring.rs +++ b/src/io/geos/scalar/linearring.rs @@ -2,8 +2,6 @@ use crate::error::{GeoArrowError, Result}; use crate::geo_traits::LineStringTrait; use crate::io::geos::scalar::coord::GEOSConstCoord; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; pub struct GEOSConstLinearRing<'a, 'b>(pub(crate) geos::ConstGeometry<'a, 'b>); @@ -22,46 +20,21 @@ impl<'a, 'b> GEOSConstLinearRing<'a, 'b> { )) } } - - pub fn num_coords(&self) -> usize { - self.0.get_num_coordinates().unwrap() - } } impl<'a, 'b> LineStringTrait for GEOSConstLinearRing<'a, 'b> { type T = f64; type ItemType<'c> = GEOSConstCoord<'a> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_coords(&self) -> usize { self.0.get_num_coordinates().unwrap() } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { let seq = self.0.get_coord_seq().unwrap(); - Some(GEOSConstCoord { + GEOSConstCoord { coords: seq, geom_index: i, - }) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() - } -} - -// This is a big HACK to try and get the PolygonTrait to successfully implement on -// GEOSPolygon. We never use this because we never use the trait iterators. -impl<'a, 'b> Clone for GEOSConstLinearRing<'a, 'b> { - fn clone(&self) -> Self { - todo!() - } - - fn clone_from(&mut self, _source: &Self) { - todo!() + } } } diff --git a/src/io/geos/scalar/linestring.rs b/src/io/geos/scalar/linestring.rs index b6e878c39..bb7280ff2 100644 --- a/src/io/geos/scalar/linestring.rs +++ b/src/io/geos/scalar/linestring.rs @@ -6,8 +6,6 @@ use crate::scalar::LineString; use crate::trait_::GeometryArraySelfMethods; use arrow_array::OffsetSizeTrait; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; impl<'b, O: OffsetSizeTrait> TryFrom> for geos::Geometry<'b> { type Error = GeoArrowError; @@ -64,46 +62,28 @@ impl<'a> GEOSLineString<'a> { impl<'a> LineStringTrait for GEOSLineString<'a> { type T = f64; type ItemType<'b> = GEOSPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_coords(&self) -> usize { self.0.get_num_points().unwrap() } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_point_n(i).unwrap(); - Some(GEOSPoint::new_unchecked(point)) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + GEOSPoint::new_unchecked(point) } } impl<'a> LineStringTrait for &'a GEOSLineString<'a> { type T = f64; type ItemType<'b> = GEOSPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_coords(&self) -> usize { self.0.get_num_points().unwrap() } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_point_n(i).unwrap(); - Some(GEOSPoint::new_unchecked(point)) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + GEOSPoint::new_unchecked(point) } } @@ -126,74 +106,30 @@ impl<'a, 'b> GEOSConstLineString<'a, 'b> { } } -// This is a big HACK to try and get the PolygonTrait to successfully implement on GEOSPolygon. We -// never use this because we never use the trait iterators. -impl<'a, 'b> Clone for GEOSConstLineString<'a, 'b> { - fn clone(&self) -> Self { - todo!() - } - - fn clone_from(&mut self, _source: &Self) { - todo!() - } -} - -// TODO: uncomment - -// error[E0477]: the type `io::geos::scalar::linestring::GEOSConstLineString<'a, 'b>` does not fulfill the required lifetime -// --> src/io/geos/scalar/linestring.rs:147:25 -// | -// 147 | fn coords(&self) -> Self::Iter<'_> { -// | ^^^^^^^^^^^^^^ -// | -// note: type must outlive the lifetime `'a` as defined here as required by this binding -// --> src/io/geos/scalar/linestring.rs:129:6 -// | -// 129 | impl<'a, 'b> LineStringTrait for GEOSConstLineString<'a, 'b> { -// | ^^ - impl<'a, 'b> LineStringTrait for GEOSConstLineString<'a, 'b> { type T = f64; type ItemType<'c> = GEOSPoint<'a> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_coords(&self) -> usize { self.0.get_num_points().unwrap() } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_point_n(i).unwrap(); - Some(GEOSPoint::new_unchecked(point)) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + GEOSPoint::new_unchecked(point) } } impl<'a, 'b> LineStringTrait for &'a GEOSConstLineString<'a, 'b> { type T = f64; type ItemType<'c> = GEOSPoint<'a> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_coords(&self) -> usize { self.0.get_num_points().unwrap() } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_point_n(i).unwrap(); - Some(GEOSPoint::new_unchecked(point)) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + GEOSPoint::new_unchecked(point) } } diff --git a/src/io/geos/scalar/mod.rs b/src/io/geos/scalar/mod.rs index 6727d82f6..9234f0526 100644 --- a/src/io/geos/scalar/mod.rs +++ b/src/io/geos/scalar/mod.rs @@ -1,14 +1,14 @@ -pub mod binary; -pub mod coord; -pub mod geometry; -pub mod geometrycollection; -pub mod linearring; -pub mod linestring; -pub mod multilinestring; -pub mod multipoint; -pub mod multipolygon; -pub mod point; -pub mod polygon; +mod binary; +mod coord; +mod geometry; +mod geometrycollection; +mod linearring; +mod linestring; +mod multilinestring; +mod multipoint; +mod multipolygon; +mod point; +mod polygon; pub use linearring::GEOSConstLinearRing; pub use linestring::{GEOSConstLineString, GEOSLineString}; diff --git a/src/io/geos/scalar/multilinestring.rs b/src/io/geos/scalar/multilinestring.rs index 8c659b57c..73881937c 100644 --- a/src/io/geos/scalar/multilinestring.rs +++ b/src/io/geos/scalar/multilinestring.rs @@ -4,8 +4,6 @@ use crate::io::geos::scalar::GEOSConstLineString; use crate::scalar::MultiLineString; use arrow_array::OffsetSizeTrait; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; impl<'b, O: OffsetSizeTrait> TryFrom> for geos::Geometry<'b> { type Error = GeoArrowError; @@ -30,7 +28,7 @@ impl<'a, 'b, O: OffsetSizeTrait> TryFrom<&'a MultiLineString<'_, O>> for geos::G Ok(geos::Geometry::create_multiline_string(geos_geoms)?) } } - +/// A GEOS geometry known to be a MultiLineString #[derive(Clone)] pub struct GEOSMultiLineString<'a>(pub(crate) geos::Geometry<'a>); @@ -69,23 +67,12 @@ impl<'a> GEOSMultiLineString<'a> { impl<'a> MultiLineStringTrait for GEOSMultiLineString<'a> { type T = f64; type ItemType<'c> = GEOSConstLineString<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_lines(&self) -> usize { self.0.get_num_geometries().unwrap() } - fn line(&self, i: usize) -> Option> { - if i > self.num_lines() { - return None; - } - - Some(GEOSConstLineString::new_unchecked( - self.0.get_geometry_n(i).unwrap(), - )) - } - - fn lines(&self) -> Self::Iter<'_> { - todo!() + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + GEOSConstLineString::new_unchecked(self.0.get_geometry_n(i).unwrap()) } } diff --git a/src/io/geos/scalar/multipoint.rs b/src/io/geos/scalar/multipoint.rs index 19f05c432..c2e968b23 100644 --- a/src/io/geos/scalar/multipoint.rs +++ b/src/io/geos/scalar/multipoint.rs @@ -4,8 +4,6 @@ use crate::io::geos::scalar::GEOSConstPoint; use crate::scalar::MultiPoint; use arrow_array::OffsetSizeTrait; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; impl<'b, O: OffsetSizeTrait> TryFrom> for geos::Geometry<'b> { type Error = GeoArrowError; @@ -58,46 +56,28 @@ impl<'a> GEOSMultiPoint<'a> { impl<'a> MultiPointTrait for GEOSMultiPoint<'a> { type T = f64; type ItemType<'c> = GEOSConstPoint<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_points(&self) -> usize { self.0.get_num_geometries().unwrap() } - fn point(&self, i: usize) -> Option> { - if i > (self.num_points()) { - return None; - } - + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_geometry_n(i).unwrap(); - Some(GEOSConstPoint::new_unchecked(point)) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + GEOSConstPoint::new_unchecked(point) } } impl<'a> MultiPointTrait for &GEOSMultiPoint<'a> { type T = f64; type ItemType<'c> = GEOSConstPoint<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_points(&self) -> usize { self.0.get_num_geometries().unwrap() } - fn point(&self, i: usize) -> Option> { - if i > (self.num_points()) { - return None; - } - + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { let point = self.0.get_geometry_n(i).unwrap(); - Some(GEOSConstPoint::new_unchecked(point)) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + GEOSConstPoint::new_unchecked(point) } } @@ -108,7 +88,6 @@ impl<'a> MultiPointTrait for &GEOSMultiPoint<'a> { // impl<'a> MultiPointTrait for GEOSMultiPoint<'a> { // type T = f64; // type ItemType = GEOSConstPoint<'a, 'a>; -// type Iter = Cloned>; // fn num_points(&self) -> usize { // self.0.get_num_geometries().unwrap() @@ -122,16 +101,11 @@ impl<'a> MultiPointTrait for &GEOSMultiPoint<'a> { // let point = self.0.get_geometry_n(i).unwrap(); // Some(GEOSConstPoint::new_unchecked(&point)) // } - -// fn points(&'a self) -> Self::Iter { -// todo!() -// } // } // impl<'a> MultiPointTrait for &GEOSMultiPoint<'a> { // type T = f64; // type ItemType = GEOSConstPoint<'a, 'a>; -// type Iter = Cloned>; // fn num_points(&self) -> usize { // self.0.get_num_geometries().unwrap() @@ -145,8 +119,4 @@ impl<'a> MultiPointTrait for &GEOSMultiPoint<'a> { // let point = self.0.get_geometry_n(i).unwrap(); // Some(GEOSConstPoint::new_unchecked(&point)) // } - -// fn points(&'a self) -> Self::Iter { -// todo!() -// } // } diff --git a/src/io/geos/scalar/multipolygon.rs b/src/io/geos/scalar/multipolygon.rs index 0606b17ca..2f379ce57 100644 --- a/src/io/geos/scalar/multipolygon.rs +++ b/src/io/geos/scalar/multipolygon.rs @@ -4,8 +4,6 @@ use crate::io::geos::scalar::GEOSConstPolygon; use crate::scalar::MultiPolygon; use arrow_array::OffsetSizeTrait; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; impl<'b, O: OffsetSizeTrait> TryFrom> for geos::Geometry<'b> { type Error = GeoArrowError; @@ -54,23 +52,12 @@ impl<'a> GEOSMultiPolygon<'a> { impl<'a> MultiPolygonTrait for GEOSMultiPolygon<'a> { type T = f64; type ItemType<'c> = GEOSConstPolygon<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_polygons(&self) -> usize { self.0.get_num_geometries().unwrap() } - fn polygon(&self, i: usize) -> Option> { - if i > self.num_polygons() { - return None; - } - - Some(GEOSConstPolygon::new_unchecked( - self.0.get_geometry_n(i).unwrap(), - )) - } - - fn polygons(&self) -> Self::Iter<'_> { - todo!() + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + GEOSConstPolygon::new_unchecked(self.0.get_geometry_n(i).unwrap()) } } diff --git a/src/io/geos/scalar/polygon.rs b/src/io/geos/scalar/polygon.rs index c3d8830a9..5ee36d47f 100644 --- a/src/io/geos/scalar/polygon.rs +++ b/src/io/geos/scalar/polygon.rs @@ -4,8 +4,6 @@ use crate::io::geos::scalar::GEOSConstLinearRing; use crate::scalar::Polygon; use arrow_array::OffsetSizeTrait; use geos::{Geom, GeometryTypes}; -use std::iter::Cloned; -use std::slice::Iter; impl<'b, O: OffsetSizeTrait> TryFrom> for geos::Geometry<'b> { type Error = GeoArrowError; @@ -88,7 +86,6 @@ impl<'a> GEOSPolygon<'a> { impl<'a> PolygonTrait for GEOSPolygon<'a> { type T = f64; type ItemType<'c> = GEOSConstLinearRing<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_interiors(&self) -> usize { self.0.get_num_interior_rings().unwrap() @@ -104,18 +101,10 @@ impl<'a> PolygonTrait for GEOSPolygon<'a> { )) } - fn interior(&self, i: usize) -> Option> { - if i > self.num_interiors() { - return None; - } - - Some(GEOSConstLinearRing::new_unchecked( + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + GEOSConstLinearRing::new_unchecked( self.0.get_interior_ring_n(i.try_into().unwrap()).unwrap(), - )) - } - - fn interiors(&self) -> Self::Iter<'_> { - todo!() + ) } } @@ -141,7 +130,6 @@ impl<'a, 'b> GEOSConstPolygon<'a, 'b> { impl<'a, 'b> PolygonTrait for GEOSConstPolygon<'a, 'b> { type T = f64; type ItemType<'c> = GEOSConstLinearRing<'a, 'c> where Self: 'c; - type Iter<'c> = Cloned>> where Self: 'c; fn num_interiors(&self) -> usize { self.0.get_num_interior_rings().unwrap() @@ -157,29 +145,9 @@ impl<'a, 'b> PolygonTrait for GEOSConstPolygon<'a, 'b> { )) } - fn interior(&self, i: usize) -> Option> { - if i > self.num_interiors() { - return None; - } - - Some(GEOSConstLinearRing::new_unchecked( + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + GEOSConstLinearRing::new_unchecked( self.0.get_interior_ring_n(i.try_into().unwrap()).unwrap(), - )) - } - - fn interiors(&self) -> Self::Iter<'_> { - todo!() - } -} - -// This is a big HACK to try and get the MultiPolygonTrait to successfully implement on -// GEOSMultiPolygon. We never use this because we never use the trait iterators. -impl<'a, 'b> Clone for GEOSConstPolygon<'a, 'b> { - fn clone(&self) -> Self { - todo!() - } - - fn clone_from(&mut self, _source: &Self) { - todo!() + ) } } diff --git a/src/io/wkb/reader/geometry_collection.rs b/src/io/wkb/reader/geometry_collection.rs index 3f8e4bf47..b604ae957 100644 --- a/src/io/wkb/reader/geometry_collection.rs +++ b/src/io/wkb/reader/geometry_collection.rs @@ -1,7 +1,5 @@ use crate::geo_traits::GeometryCollectionTrait; use crate::io::wkb::reader::geometry::{Endianness, WKBGeometry}; -use std::iter::Cloned; -use std::slice::Iter; /// Not yet implemented but required for WKBGeometry #[derive(Debug, Clone, Copy)] @@ -20,17 +18,12 @@ impl<'a> WKBGeometryCollection<'a> { impl<'a> GeometryCollectionTrait for WKBGeometryCollection<'a> { type T = f64; type ItemType<'b> = WKBGeometry<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_geometries(&self) -> usize { todo!() } - fn geometry(&self, _i: usize) -> Option> { - todo!() - } - - fn geometries(&self) -> Self::Iter<'_> { + unsafe fn geometry_unchecked(&self, _i: usize) -> Self::ItemType<'_> { todo!() } } diff --git a/src/io/wkb/reader/linearring.rs b/src/io/wkb/reader/linearring.rs index d8f88b9cb..70fd58512 100644 --- a/src/io/wkb/reader/linearring.rs +++ b/src/io/wkb/reader/linearring.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -70,26 +68,16 @@ impl<'a> WKBLinearRing<'a> { impl<'a> LineStringTrait for WKBLinearRing<'a> { type T = f64; type ItemType<'b> = WKBCoord<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_coords(&self) -> usize { self.num_points } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_points) { - return None; - } - - let coord = WKBCoord::new( + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + WKBCoord::new( self.buf, self.byte_order, self.coord_offset(i.try_into().unwrap()), - ); - Some(coord) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + ) } } diff --git a/src/io/wkb/reader/linestring.rs b/src/io/wkb/reader/linestring.rs index eec8baec8..32a356a03 100644 --- a/src/io/wkb/reader/linestring.rs +++ b/src/io/wkb/reader/linestring.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -75,95 +73,60 @@ impl<'a> WKBLineString<'a> { impl<'a> LineStringTrait for WKBLineString<'a> { type T = f64; type ItemType<'b> = WKBCoord<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_coords(&self) -> usize { self.num_points } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - - let coord = WKBCoord::new( + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + WKBCoord::new( self.buf, self.byte_order, self.coord_offset(i.try_into().unwrap()), - ); - Some(coord) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + ) } } impl<'a> LineStringTrait for &'a WKBLineString<'a> { type T = f64; type ItemType<'b> = WKBCoord<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_coords(&self) -> usize { self.num_points } - fn coord(&self, i: usize) -> Option> { - if i > (self.num_coords()) { - return None; - } - - let offset = self.offset + 1 + 4 + 4 + (2 * 8 * i as u64); - let coord = WKBCoord::new(self.buf, self.byte_order, offset); - Some(coord) - } - - fn coords(&self) -> Self::Iter<'_> { - todo!() + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + WKBCoord::new( + self.buf, + self.byte_order, + self.coord_offset(i.try_into().unwrap()), + ) } } impl<'a> MultiLineStringTrait for WKBLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { 1 } - fn line(&self, i: usize) -> Option> { - if i > self.num_lines() { - return None; - } - - Some(*self) - } - - fn lines(&self) -> Self::Iter<'_> { - todo!() + unsafe fn line_unchecked(&self, _i: usize) -> Self::ItemType<'_> { + *self } } impl<'a> MultiLineStringTrait for &'a WKBLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { 1 } - fn line(&self, i: usize) -> Option> { - if i > self.num_lines() { - return None; - } - - Some(**self) - } - - fn lines(&self) -> Self::Iter<'_> { - todo!() + unsafe fn line_unchecked(&self, _i: usize) -> Self::ItemType<'_> { + **self } } diff --git a/src/io/wkb/reader/maybe_multi_line_string.rs b/src/io/wkb/reader/maybe_multi_line_string.rs index 87cf8738e..de94cc5d6 100644 --- a/src/io/wkb/reader/maybe_multi_line_string.rs +++ b/src/io/wkb/reader/maybe_multi_line_string.rs @@ -2,8 +2,6 @@ use crate::algorithm::native::eq::multi_line_string_eq; use crate::geo_traits::MultiLineStringTrait; use crate::io::wkb::reader::linestring::WKBLineString; use crate::io::wkb::reader::multilinestring::WKBMultiLineString; -use std::iter::Cloned; -use std::slice::Iter; /// An WKB object that can be either a WKBLineString or a WKBMultiLineString. /// @@ -24,7 +22,6 @@ impl<'a> WKBMaybeMultiLineString<'a> { impl<'a> MultiLineStringTrait for WKBMaybeMultiLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { match self { @@ -33,17 +30,10 @@ impl<'a> MultiLineStringTrait for WKBMaybeMultiLineString<'a> { } } - fn line(&self, i: usize) -> Option> { + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiLineString::LineString(geom) => geom.line(i), - WKBMaybeMultiLineString::MultiLineString(geom) => geom.line(i), - } - } - - fn lines(&self) -> Self::Iter<'_> { - match self { - WKBMaybeMultiLineString::LineString(geom) => geom.lines(), - WKBMaybeMultiLineString::MultiLineString(geom) => geom.lines(), + WKBMaybeMultiLineString::LineString(geom) => geom.line_unchecked(i), + WKBMaybeMultiLineString::MultiLineString(geom) => geom.line_unchecked(i), } } } @@ -51,7 +41,6 @@ impl<'a> MultiLineStringTrait for WKBMaybeMultiLineString<'a> { impl<'a> MultiLineStringTrait for &'a WKBMaybeMultiLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { match self { @@ -60,17 +49,10 @@ impl<'a> MultiLineStringTrait for &'a WKBMaybeMultiLineString<'a> { } } - fn line(&self, i: usize) -> Option> { - match self { - WKBMaybeMultiLineString::LineString(geom) => geom.line(i), - WKBMaybeMultiLineString::MultiLineString(geom) => geom.line(i), - } - } - - fn lines(&self) -> Self::Iter<'_> { + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiLineString::LineString(geom) => geom.lines(), - WKBMaybeMultiLineString::MultiLineString(geom) => geom.lines(), + WKBMaybeMultiLineString::LineString(geom) => geom.line_unchecked(i), + WKBMaybeMultiLineString::MultiLineString(geom) => geom.line_unchecked(i), } } } diff --git a/src/io/wkb/reader/maybe_multi_point.rs b/src/io/wkb/reader/maybe_multi_point.rs index d18234be1..bcd9bc171 100644 --- a/src/io/wkb/reader/maybe_multi_point.rs +++ b/src/io/wkb/reader/maybe_multi_point.rs @@ -2,10 +2,6 @@ use crate::algorithm::native::eq::multi_point_eq; use crate::geo_traits::MultiPointTrait; use crate::io::wkb::reader::multipoint::WKBMultiPoint; use crate::io::wkb::reader::point::WKBPoint; -// use crate::io::wkb::Point::WKBPoint; -// use crate::io::wkb::multiPoint::WKBMultiPoint; -use std::iter::Cloned; -use std::slice::Iter; /// An WKB object that can be either a WKBPoint or a WKBMultiPoint. /// @@ -26,7 +22,6 @@ impl<'a> WKBMaybeMultiPoint<'a> { impl<'a> MultiPointTrait for WKBMaybeMultiPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { match self { @@ -35,17 +30,10 @@ impl<'a> MultiPointTrait for WKBMaybeMultiPoint<'a> { } } - fn point(&self, i: usize) -> Option> { + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiPoint::Point(geom) => geom.point(i), - WKBMaybeMultiPoint::MultiPoint(geom) => geom.point(i), - } - } - - fn points(&self) -> Self::Iter<'_> { - match self { - WKBMaybeMultiPoint::Point(geom) => geom.points(), - WKBMaybeMultiPoint::MultiPoint(geom) => geom.points(), + WKBMaybeMultiPoint::Point(geom) => geom.point_unchecked(i), + WKBMaybeMultiPoint::MultiPoint(geom) => geom.point_unchecked(i), } } } @@ -53,7 +41,6 @@ impl<'a> MultiPointTrait for WKBMaybeMultiPoint<'a> { impl<'a> MultiPointTrait for &'a WKBMaybeMultiPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { match self { @@ -62,17 +49,10 @@ impl<'a> MultiPointTrait for &'a WKBMaybeMultiPoint<'a> { } } - fn point(&self, i: usize) -> Option> { - match self { - WKBMaybeMultiPoint::Point(geom) => geom.point(i), - WKBMaybeMultiPoint::MultiPoint(geom) => geom.point(i), - } - } - - fn points(&self) -> Self::Iter<'_> { + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiPoint::Point(geom) => geom.points(), - WKBMaybeMultiPoint::MultiPoint(geom) => geom.points(), + WKBMaybeMultiPoint::Point(geom) => geom.point_unchecked(i), + WKBMaybeMultiPoint::MultiPoint(geom) => geom.point_unchecked(i), } } } diff --git a/src/io/wkb/reader/maybe_multipolygon.rs b/src/io/wkb/reader/maybe_multipolygon.rs index f0eb0f36f..791fb1ebe 100644 --- a/src/io/wkb/reader/maybe_multipolygon.rs +++ b/src/io/wkb/reader/maybe_multipolygon.rs @@ -2,8 +2,6 @@ use crate::algorithm::native::eq::multi_polygon_eq; use crate::geo_traits::MultiPolygonTrait; use crate::io::wkb::reader::multipolygon::WKBMultiPolygon; use crate::io::wkb::reader::polygon::WKBPolygon; -use std::iter::Cloned; -use std::slice::Iter; /// An WKB object that can be either a WKBPolygon or a WKBMultiPolygon. /// @@ -24,7 +22,6 @@ impl<'a> WKBMaybeMultiPolygon<'a> { impl<'a> MultiPolygonTrait for WKBMaybeMultiPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { match self { @@ -33,17 +30,10 @@ impl<'a> MultiPolygonTrait for WKBMaybeMultiPolygon<'a> { } } - fn polygon(&self, i: usize) -> Option> { + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiPolygon::Polygon(geom) => geom.polygon(i), - WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygon(i), - } - } - - fn polygons(&self) -> Self::Iter<'_> { - match self { - WKBMaybeMultiPolygon::Polygon(geom) => geom.polygons(), - WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygons(), + WKBMaybeMultiPolygon::Polygon(geom) => geom.polygon_unchecked(i), + WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygon_unchecked(i), } } } @@ -51,7 +41,6 @@ impl<'a> MultiPolygonTrait for WKBMaybeMultiPolygon<'a> { impl<'a> MultiPolygonTrait for &'a WKBMaybeMultiPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { match self { @@ -60,17 +49,10 @@ impl<'a> MultiPolygonTrait for &'a WKBMaybeMultiPolygon<'a> { } } - fn polygon(&self, i: usize) -> Option> { - match self { - WKBMaybeMultiPolygon::Polygon(geom) => geom.polygon(i), - WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygon(i), - } - } - - fn polygons(&self) -> Self::Iter<'_> { + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { match self { - WKBMaybeMultiPolygon::Polygon(geom) => geom.polygons(), - WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygons(), + WKBMaybeMultiPolygon::Polygon(geom) => geom.polygon_unchecked(i), + WKBMaybeMultiPolygon::MultiPolygon(geom) => geom.polygon_unchecked(i), } } } diff --git a/src/io/wkb/reader/multilinestring.rs b/src/io/wkb/reader/multilinestring.rs index fb01d4cc1..698871067 100644 --- a/src/io/wkb/reader/multilinestring.rs +++ b/src/io/wkb/reader/multilinestring.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -66,44 +64,26 @@ impl<'a> WKBMultiLineString<'a> { impl<'a> MultiLineStringTrait for WKBMultiLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { self.wkb_line_strings.len() } - fn line(&self, i: usize) -> Option> { - if i > self.num_lines() { - return None; - } - - Some(self.wkb_line_strings[i]) - } - - fn lines(&self) -> Self::Iter<'_> { - todo!() + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + *self.wkb_line_strings.get_unchecked(i) } } impl<'a> MultiLineStringTrait for &'a WKBMultiLineString<'a> { type T = f64; type ItemType<'b> = WKBLineString<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_lines(&self) -> usize { self.wkb_line_strings.len() } - fn line(&self, i: usize) -> Option> { - if i > self.num_lines() { - return None; - } - - Some(self.wkb_line_strings[i]) - } - - fn lines(&self) -> Self::Iter<'_> { - todo!() + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + *self.wkb_line_strings.get_unchecked(i) } } diff --git a/src/io/wkb/reader/multipoint.rs b/src/io/wkb/reader/multipoint.rs index 8ce0f0641..fd00ae320 100644 --- a/src/io/wkb/reader/multipoint.rs +++ b/src/io/wkb/reader/multipoint.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -65,52 +63,34 @@ impl<'a> WKBMultiPoint<'a> { impl<'a> MultiPointTrait for WKBMultiPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { self.num_points } - fn point(&self, i: usize) -> Option> { - if i > self.num_points() { - return None; - } - - Some(WKBPoint::new( + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + WKBPoint::new( self.buf, self.byte_order, self.point_offset(i.try_into().unwrap()), - )) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + ) } } impl<'a> MultiPointTrait for &'a WKBMultiPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { self.num_points } - fn point(&self, i: usize) -> Option> { - if i > self.num_points() { - return None; - } - - Some(WKBPoint::new( + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + WKBPoint::new( self.buf, self.byte_order, self.point_offset(i.try_into().unwrap()), - )) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + ) } } diff --git a/src/io/wkb/reader/multipolygon.rs b/src/io/wkb/reader/multipolygon.rs index e169b1221..30fa762eb 100644 --- a/src/io/wkb/reader/multipolygon.rs +++ b/src/io/wkb/reader/multipolygon.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -63,44 +61,26 @@ impl<'a> WKBMultiPolygon<'a> { impl<'a> MultiPolygonTrait for WKBMultiPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { self.wkb_polygons.len() } - fn polygon(&self, i: usize) -> Option> { - if i > self.num_polygons() { - return None; - } - - Some(self.wkb_polygons[i].clone()) - } - - fn polygons(&self) -> Self::Iter<'_> { - todo!() + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.wkb_polygons.get_unchecked(i).clone() } } impl<'a> MultiPolygonTrait for &'a WKBMultiPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { self.wkb_polygons.len() } - fn polygon(&self, i: usize) -> Option> { - if i > self.num_polygons() { - return None; - } - - Some(self.wkb_polygons[i].clone()) - } - - fn polygons(&self) -> Self::Iter<'_> { - todo!() + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.wkb_polygons.get_unchecked(i).clone() } } diff --git a/src/io/wkb/reader/point.rs b/src/io/wkb/reader/point.rs index 0bf66f595..9aa40f15f 100644 --- a/src/io/wkb/reader/point.rs +++ b/src/io/wkb/reader/point.rs @@ -2,8 +2,6 @@ use crate::algorithm::native::eq::point_eq; use crate::geo_traits::{CoordTrait, MultiPointTrait, PointTrait}; use crate::io::wkb::reader::coord::WKBCoord; use crate::io::wkb::reader::geometry::Endianness; -use std::iter::Cloned; -use std::slice::Iter; /// A 2D Point in WKB /// @@ -67,44 +65,26 @@ impl<'a> PointTrait for &WKBPoint<'a> { impl<'a> MultiPointTrait for WKBPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { 1 } - fn point(&self, i: usize) -> Option> { - if i > self.num_points() { - return None; - } - - Some(*self) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + unsafe fn point_unchecked(&self, _i: usize) -> Self::ItemType<'_> { + *self } } impl<'a> MultiPointTrait for &'a WKBPoint<'a> { type T = f64; type ItemType<'b> = WKBPoint<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_points(&self) -> usize { 1 } - fn point(&self, i: usize) -> Option> { - if i > self.num_points() { - return None; - } - - Some(**self) - } - - fn points(&self) -> Self::Iter<'_> { - todo!() + unsafe fn point_unchecked(&self, _i: usize) -> Self::ItemType<'_> { + **self } } diff --git a/src/io/wkb/reader/polygon.rs b/src/io/wkb/reader/polygon.rs index a7bd9db17..d8f1551e0 100644 --- a/src/io/wkb/reader/polygon.rs +++ b/src/io/wkb/reader/polygon.rs @@ -1,6 +1,4 @@ use std::io::Cursor; -use std::iter::Cloned; -use std::slice::Iter; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; @@ -80,7 +78,6 @@ impl<'a> WKBPolygon<'a> { impl<'a> PolygonTrait for WKBPolygon<'a> { type T = f64; type ItemType<'b> = WKBLinearRing<'a>where Self: 'b; - type Iter<'b> = Cloned>>where Self: 'b; fn num_interiors(&self) -> usize { // Support an empty polygon with no rings @@ -99,23 +96,14 @@ impl<'a> PolygonTrait for WKBPolygon<'a> { } } - fn interior(&self, i: usize) -> Option> { - if i > self.num_interiors() { - return None; - } - - Some(self.wkb_linear_rings[i + 1]) - } - - fn interiors(&self) -> Self::Iter<'_> { - todo!() + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + *self.wkb_linear_rings.get_unchecked(i + 1) } } impl<'a> PolygonTrait for &'a WKBPolygon<'a> { type T = f64; type ItemType<'b> = WKBLinearRing<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_interiors(&self) -> usize { // Support an empty polygon with no rings @@ -134,62 +122,36 @@ impl<'a> PolygonTrait for &'a WKBPolygon<'a> { } } - fn interior(&self, i: usize) -> Option> { - if i > self.num_interiors() { - return None; - } - - Some(self.wkb_linear_rings[i + 1]) - } - - fn interiors(&self) -> Self::Iter<'_> { - todo!() + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + *self.wkb_linear_rings.get_unchecked(i + 1) } } impl<'a> MultiPolygonTrait for WKBPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { 1 } - fn polygon(&self, i: usize) -> Option> { - if i > self.num_polygons() { - return None; - } - - Some(self.clone()) - } - - fn polygons(&self) -> Self::Iter<'_> { - todo!() + unsafe fn polygon_unchecked(&self, _i: usize) -> Self::ItemType<'_> { + self.clone() } } impl<'a> MultiPolygonTrait for &'a WKBPolygon<'a> { type T = f64; type ItemType<'b> = WKBPolygon<'a> where Self: 'b; - type Iter<'b> = Cloned>> where Self: 'b; fn num_polygons(&self) -> usize { 1 } - fn polygon(&self, i: usize) -> Option> { - if i > self.num_polygons() { - return None; - } - + unsafe fn polygon_unchecked(&self, _i: usize) -> Self::ItemType<'_> { // TODO: this looks bad #[allow(suspicious_double_ref_op)] - Some(self.clone().clone()) - } - - fn polygons(&self) -> Self::Iter<'_> { - todo!() + self.clone().clone() } } diff --git a/src/scalar/geometrycollection/iterator.rs b/src/scalar/geometrycollection/iterator.rs deleted file mode 100644 index 59ed810a3..000000000 --- a/src/scalar/geometrycollection/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::GeometryCollectionTrait; -use crate::scalar::{Geometry, GeometryCollection}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`GeometryCollectionArray`] -#[derive(Clone, Debug)] -pub struct GeometryCollectionIterator<'a, O: OffsetSizeTrait> { - geom: &'a GeometryCollection<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> GeometryCollectionIterator<'a, O> { - #[inline] - pub fn new(geom: &'a GeometryCollection<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_geometries(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for GeometryCollectionIterator<'a, O> { - type Item = crate::scalar::Geometry<'a, O>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.geometry(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for GeometryCollectionIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for GeometryCollectionIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.geometry(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a GeometryCollection<'a, O> { - type Item = Geometry<'a, O>; - type IntoIter = GeometryCollectionIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> GeometryCollection<'a, O> { - /// Returns an iterator of `Point` - pub fn iter(&'a self) -> GeometryCollectionIterator<'a, O> { - GeometryCollectionIterator::new(self) - } -} diff --git a/src/scalar/geometrycollection/mod.rs b/src/scalar/geometrycollection/mod.rs index 3d47e553a..17aef0c28 100644 --- a/src/scalar/geometrycollection/mod.rs +++ b/src/scalar/geometrycollection/mod.rs @@ -1,5 +1,3 @@ -mod iterator; mod scalar; -pub use iterator::GeometryCollectionIterator; pub use scalar::GeometryCollection; diff --git a/src/scalar/geometrycollection/scalar.rs b/src/scalar/geometrycollection/scalar.rs index 5d7a67382..9ec9a8718 100644 --- a/src/scalar/geometrycollection/scalar.rs +++ b/src/scalar/geometrycollection/scalar.rs @@ -2,7 +2,6 @@ use crate::algorithm::native::eq::geometry_collection_eq; use crate::array::util::OffsetBufferUtils; use crate::array::MixedGeometryArray; use crate::geo_traits::GeometryCollectionTrait; -use crate::scalar::geometrycollection::GeometryCollectionIterator; use crate::scalar::Geometry; use crate::trait_::GeometryArrayAccessor; use crate::trait_::GeometryScalarTrait; @@ -19,6 +18,24 @@ pub struct GeometryCollection<'a, O: OffsetSizeTrait> { pub(crate) geom_offsets: &'a OffsetBuffer, pub(crate) geom_index: usize, + + start_offset: usize, +} + +impl<'a, O: OffsetSizeTrait> GeometryCollection<'a, O> { + pub fn new( + array: &'a MixedGeometryArray, + geom_offsets: &'a OffsetBuffer, + geom_index: usize, + ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); + Self { + array, + geom_offsets, + geom_index, + start_offset, + } + } } impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for GeometryCollection<'a, O> { @@ -32,49 +49,28 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for GeometryCollection<'a, O> { impl<'a, O: OffsetSizeTrait> GeometryCollectionTrait for GeometryCollection<'a, O> { type T = f64; type ItemType<'b> = Geometry<'a, O> where Self: 'b; - type Iter<'b> = GeometryCollectionIterator<'a, O> where Self: 'b; - - fn geometries(&self) -> Self::Iter<'_> { - todo!() - // GeometryCollectionIterator::new(self) - } fn num_geometries(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn geometry(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(self.array.value(start + i)) + unsafe fn geometry_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.array.value(self.start_offset + i) } } impl<'a, O: OffsetSizeTrait> GeometryCollectionTrait for &'a GeometryCollection<'a, O> { type T = f64; type ItemType<'b> = Geometry<'a, O> where Self: 'b; - type Iter<'b> = GeometryCollectionIterator<'a, O> where Self: 'b; - - fn geometries(&self) -> Self::Iter<'_> { - GeometryCollectionIterator::new(self) - } fn num_geometries(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn geometry(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(self.array.value(start + i)) + unsafe fn geometry_unchecked(&self, i: usize) -> Self::ItemType<'_> { + self.array.value(self.start_offset + i) } } diff --git a/src/scalar/linestring/iterator.rs b/src/scalar/linestring/iterator.rs deleted file mode 100644 index 4d3db876d..000000000 --- a/src/scalar/linestring/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::LineStringTrait; -use crate::scalar::{LineString, Point}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`LineStringArray`](crate::array::LineStringArray) -#[derive(Clone, Debug)] -pub struct LineStringIterator<'a, O: OffsetSizeTrait> { - geom: &'a LineString<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> LineStringIterator<'a, O> { - #[inline] - pub fn new(geom: &'a LineString<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_coords(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for LineStringIterator<'a, O> { - type Item = crate::scalar::Point<'a>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.coord(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for LineStringIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for LineStringIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.coord(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a LineString<'a, O> { - type Item = Point<'a>; - type IntoIter = LineStringIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> LineString<'a, O> { - /// Returns an iterator of `Point` - pub fn iter(&'a self) -> LineStringIterator<'a, O> { - LineStringIterator::new(self) - } -} diff --git a/src/scalar/linestring/mod.rs b/src/scalar/linestring/mod.rs index 31c1a9f02..79fa8084e 100644 --- a/src/scalar/linestring/mod.rs +++ b/src/scalar/linestring/mod.rs @@ -1,7 +1,5 @@ -pub mod iterator; mod owned; mod scalar; -pub use iterator::LineStringIterator; pub use owned::OwnedLineString; pub use scalar::LineString; diff --git a/src/scalar/linestring/scalar.rs b/src/scalar/linestring/scalar.rs index 1cba2ff35..9a19612a8 100644 --- a/src/scalar/linestring/scalar.rs +++ b/src/scalar/linestring/scalar.rs @@ -10,8 +10,6 @@ use arrow_buffer::OffsetBuffer; use rstar::{RTreeObject, AABB}; use std::borrow::Cow; -use crate::scalar::linestring::LineStringIterator; - /// An Arrow equivalent of a LineString #[derive(Debug, Clone)] pub struct LineString<'a, O: OffsetSizeTrait> { @@ -21,6 +19,8 @@ pub struct LineString<'a, O: OffsetSizeTrait> { pub(crate) geom_offsets: Cow<'a, OffsetBuffer>, pub(crate) geom_index: usize, + + start_offset: usize, } impl<'a, O: OffsetSizeTrait> LineString<'a, O> { @@ -29,10 +29,12 @@ impl<'a, O: OffsetSizeTrait> LineString<'a, O> { geom_offsets: Cow<'a, OffsetBuffer>, geom_index: usize, ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); Self { coords, geom_offsets, geom_index, + start_offset, } } @@ -41,11 +43,11 @@ impl<'a, O: OffsetSizeTrait> LineString<'a, O> { geom_offsets: &'a OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Borrowed(coords), - geom_offsets: Cow::Borrowed(geom_offsets), + Self::new( + Cow::Borrowed(coords), + Cow::Borrowed(geom_offsets), geom_index, - } + ) } pub fn new_owned( @@ -53,11 +55,7 @@ impl<'a, O: OffsetSizeTrait> LineString<'a, O> { geom_offsets: OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Owned(coords), - geom_offsets: Cow::Owned(geom_offsets), - geom_index, - } + Self::new(Cow::Owned(coords), Cow::Owned(geom_offsets), geom_index) } /// Extracts the owned data. @@ -95,49 +93,28 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for LineString<'a, O> { impl<'a, O: OffsetSizeTrait> LineStringTrait for LineString<'a, O> { type T = f64; type ItemType<'b> = Point<'a> where Self: 'b; - type Iter<'b> = LineStringIterator<'a, O> where Self: 'b; - - fn coords(&self) -> Self::Iter<'_> { - todo!() - // LineStringIterator::new(self) - } fn num_coords(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn coord(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(Point::new(self.coords.clone(), start + i)) + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Point::new(self.coords.clone(), self.start_offset + i) } } impl<'a, O: OffsetSizeTrait> LineStringTrait for &'a LineString<'a, O> { type T = f64; type ItemType<'b> = Point<'a> where Self: 'b; - type Iter<'b> = LineStringIterator<'a, O> where Self: 'b; - - fn coords(&self) -> Self::Iter<'_> { - LineStringIterator::new(self) - } fn num_coords(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn coord(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(Point::new(self.coords.clone(), start + i)) + unsafe fn coord_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Point::new(self.coords.clone(), self.start_offset + i) } } diff --git a/src/scalar/multilinestring/iterator.rs b/src/scalar/multilinestring/iterator.rs deleted file mode 100644 index d0b1d024b..000000000 --- a/src/scalar/multilinestring/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::MultiLineStringTrait; -use crate::scalar::{LineString, MultiLineString}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`MultiLineStringArray`] -#[derive(Clone, Debug)] -pub struct MultiLineStringIterator<'a, O: OffsetSizeTrait> { - geom: &'a MultiLineString<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> MultiLineStringIterator<'a, O> { - #[inline] - pub fn new(geom: &'a MultiLineString<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_lines(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for MultiLineStringIterator<'a, O> { - type Item = crate::scalar::LineString<'a, O>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.line(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for MultiLineStringIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for MultiLineStringIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.line(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a MultiLineString<'a, O> { - type Item = LineString<'a, O>; - type IntoIter = MultiLineStringIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> MultiLineString<'a, O> { - /// Returns an iterator of `Point` - pub fn iter(&'a self) -> MultiLineStringIterator<'a, O> { - MultiLineStringIterator::new(self) - } -} diff --git a/src/scalar/multilinestring/mod.rs b/src/scalar/multilinestring/mod.rs index c2113246a..dccd1eb27 100644 --- a/src/scalar/multilinestring/mod.rs +++ b/src/scalar/multilinestring/mod.rs @@ -1,7 +1,5 @@ -mod iterator; mod owned; mod scalar; -pub use iterator::MultiLineStringIterator; pub use owned::OwnedMultiLineString; pub use scalar::MultiLineString; diff --git a/src/scalar/multilinestring/scalar.rs b/src/scalar/multilinestring/scalar.rs index d81760a7e..14c192521 100644 --- a/src/scalar/multilinestring/scalar.rs +++ b/src/scalar/multilinestring/scalar.rs @@ -3,7 +3,6 @@ use crate::algorithm::native::eq::multi_line_string_eq; use crate::array::util::OffsetBufferUtils; use crate::array::{CoordBuffer, MultiLineStringArray}; use crate::geo_traits::MultiLineStringTrait; -use crate::scalar::multilinestring::MultiLineStringIterator; use crate::scalar::LineString; use crate::trait_::GeometryScalarTrait; use crate::trait_::{GeometryArrayAccessor, GeometryArraySelfMethods}; @@ -24,6 +23,8 @@ pub struct MultiLineString<'a, O: OffsetSizeTrait> { pub(crate) ring_offsets: Cow<'a, OffsetBuffer>, pub(crate) geom_index: usize, + + start_offset: usize, } impl<'a, O: OffsetSizeTrait> MultiLineString<'a, O> { @@ -33,11 +34,13 @@ impl<'a, O: OffsetSizeTrait> MultiLineString<'a, O> { ring_offsets: Cow<'a, OffsetBuffer>, geom_index: usize, ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); Self { coords, geom_offsets, ring_offsets, geom_index, + start_offset, } } @@ -47,12 +50,12 @@ impl<'a, O: OffsetSizeTrait> MultiLineString<'a, O> { ring_offsets: &'a OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Borrowed(coords), - geom_offsets: Cow::Borrowed(geom_offsets), - ring_offsets: Cow::Borrowed(ring_offsets), + Self::new( + Cow::Borrowed(coords), + Cow::Borrowed(geom_offsets), + Cow::Borrowed(ring_offsets), geom_index, - } + ) } pub fn new_owned( @@ -61,12 +64,12 @@ impl<'a, O: OffsetSizeTrait> MultiLineString<'a, O> { ring_offsets: OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Owned(coords), - geom_offsets: Cow::Owned(geom_offsets), - ring_offsets: Cow::Owned(ring_offsets), + Self::new( + Cow::Owned(coords), + Cow::Owned(geom_offsets), + Cow::Owned(ring_offsets), geom_index, - } + ) } /// Extracts the owned data. @@ -111,57 +114,36 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for MultiLineString<'a, O> { impl<'a, O: OffsetSizeTrait> MultiLineStringTrait for MultiLineString<'a, O> { type T = f64; type ItemType<'b> = LineString<'a, O> where Self: 'b; - type Iter<'b> = MultiLineStringIterator<'a, O> where Self: 'b; - - fn lines(&self) -> Self::Iter<'_> { - todo!() - // MultiLineStringIterator::new(self) - } fn num_lines(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn line(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(LineString::new( + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + LineString::new( self.coords.clone(), self.ring_offsets.clone(), - start + i, - )) + self.start_offset + i, + ) } } impl<'a, O: OffsetSizeTrait> MultiLineStringTrait for &'a MultiLineString<'a, O> { type T = f64; type ItemType<'b> = LineString<'a, O> where Self: 'b; - type Iter<'b> = MultiLineStringIterator<'a, O> where Self: 'b; - - fn lines(&self) -> Self::Iter<'_> { - MultiLineStringIterator::new(self) - } fn num_lines(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn line(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(LineString::new( + unsafe fn line_unchecked(&self, i: usize) -> Self::ItemType<'_> { + LineString::new( self.coords.clone(), self.ring_offsets.clone(), - start + i, - )) + self.start_offset + i, + ) } } diff --git a/src/scalar/multipoint/iterator.rs b/src/scalar/multipoint/iterator.rs deleted file mode 100644 index 1a6f93db7..000000000 --- a/src/scalar/multipoint/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::MultiPointTrait; -use crate::scalar::{MultiPoint, Point}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`MultiPointArray`] -#[derive(Clone, Debug)] -pub struct MultiPointIterator<'a, O: OffsetSizeTrait> { - geom: &'a MultiPoint<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> MultiPointIterator<'a, O> { - #[inline] - pub fn new(geom: &'a MultiPoint<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_points(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for MultiPointIterator<'a, O> { - type Item = crate::scalar::Point<'a>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.point(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for MultiPointIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for MultiPointIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.point(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a MultiPoint<'a, O> { - type Item = Point<'a>; - type IntoIter = MultiPointIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> MultiPoint<'a, O> { - /// Returns an iterator of `Point` - pub fn iter(&'a self) -> MultiPointIterator<'a, O> { - MultiPointIterator::new(self) - } -} diff --git a/src/scalar/multipoint/mod.rs b/src/scalar/multipoint/mod.rs index 99cee9940..f1f3f4a74 100644 --- a/src/scalar/multipoint/mod.rs +++ b/src/scalar/multipoint/mod.rs @@ -1,7 +1,5 @@ -mod iterator; mod owned; mod scalar; -pub use iterator::MultiPointIterator; pub use owned::OwnedMultiPoint; pub use scalar::MultiPoint; diff --git a/src/scalar/multipoint/scalar.rs b/src/scalar/multipoint/scalar.rs index 0fca273dd..db0d23f83 100644 --- a/src/scalar/multipoint/scalar.rs +++ b/src/scalar/multipoint/scalar.rs @@ -3,7 +3,6 @@ use crate::algorithm::native::eq::multi_point_eq; use crate::array::util::OffsetBufferUtils; use crate::array::{CoordBuffer, MultiPointArray}; use crate::geo_traits::MultiPointTrait; -use crate::scalar::multipoint::MultiPointIterator; use crate::scalar::Point; use crate::trait_::GeometryScalarTrait; use crate::trait_::{GeometryArrayAccessor, GeometryArraySelfMethods}; @@ -22,6 +21,8 @@ pub struct MultiPoint<'a, O: OffsetSizeTrait> { pub(crate) geom_offsets: Cow<'a, OffsetBuffer>, pub(crate) geom_index: usize, + + start_offset: usize, } impl<'a, O: OffsetSizeTrait> MultiPoint<'a, O> { @@ -30,10 +31,12 @@ impl<'a, O: OffsetSizeTrait> MultiPoint<'a, O> { geom_offsets: Cow<'a, OffsetBuffer>, geom_index: usize, ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); Self { coords, geom_offsets, geom_index, + start_offset, } } @@ -42,11 +45,11 @@ impl<'a, O: OffsetSizeTrait> MultiPoint<'a, O> { geom_offsets: &'a OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Borrowed(coords), - geom_offsets: Cow::Borrowed(geom_offsets), + Self::new( + Cow::Borrowed(coords), + Cow::Borrowed(geom_offsets), geom_index, - } + ) } pub fn new_owned( @@ -54,11 +57,7 @@ impl<'a, O: OffsetSizeTrait> MultiPoint<'a, O> { geom_offsets: OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Owned(coords), - geom_offsets: Cow::Owned(geom_offsets), - geom_index, - } + Self::new(Cow::Owned(coords), Cow::Owned(geom_offsets), geom_index) } /// Extracts the owned data. @@ -96,49 +95,28 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for MultiPoint<'a, O> { impl<'a, O: OffsetSizeTrait> MultiPointTrait for MultiPoint<'a, O> { type T = f64; type ItemType<'b> = Point<'a> where Self: 'b; - type Iter<'b> = MultiPointIterator<'a, O> where Self: 'b; - - fn points(&self) -> Self::Iter<'_> { - todo!() - // MultiPointIterator::new(self) - } fn num_points(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn point(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(Point::new(self.coords.clone(), start + i)) + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Point::new(self.coords.clone(), self.start_offset + i) } } impl<'a, O: OffsetSizeTrait> MultiPointTrait for &'a MultiPoint<'a, O> { type T = f64; type ItemType<'b> = Point<'a> where Self: 'b; - type Iter<'b> = MultiPointIterator<'a, O> where Self: 'b; - - fn points(&self) -> Self::Iter<'_> { - MultiPointIterator::new(self) - } fn num_points(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn point(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - Some(Point::new(self.coords.clone(), start + i)) + unsafe fn point_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Point::new(self.coords.clone(), self.start_offset + i) } } diff --git a/src/scalar/multipolygon/iterator.rs b/src/scalar/multipolygon/iterator.rs deleted file mode 100644 index 392e69d79..000000000 --- a/src/scalar/multipolygon/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::MultiPolygonTrait; -use crate::scalar::{MultiPolygon, Polygon}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`MultiPolygonArray`] -#[derive(Clone, Debug)] -pub struct MultiPolygonIterator<'a, O: OffsetSizeTrait> { - geom: &'a MultiPolygon<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> MultiPolygonIterator<'a, O> { - #[inline] - pub fn new(geom: &'a MultiPolygon<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_polygons(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for MultiPolygonIterator<'a, O> { - type Item = crate::scalar::Polygon<'a, O>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.polygon(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for MultiPolygonIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for MultiPolygonIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.polygon(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a MultiPolygon<'a, O> { - type Item = Polygon<'a, O>; - type IntoIter = MultiPolygonIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> MultiPolygon<'a, O> { - /// Returns an iterator of `Point` - pub fn iter(&'a self) -> MultiPolygonIterator<'a, O> { - MultiPolygonIterator::new(self) - } -} diff --git a/src/scalar/multipolygon/mod.rs b/src/scalar/multipolygon/mod.rs index a292aade0..28bf67270 100644 --- a/src/scalar/multipolygon/mod.rs +++ b/src/scalar/multipolygon/mod.rs @@ -1,7 +1,5 @@ -mod iterator; mod owned; mod scalar; -pub use iterator::MultiPolygonIterator; pub use owned::OwnedMultiPolygon; pub use scalar::MultiPolygon; diff --git a/src/scalar/multipolygon/scalar.rs b/src/scalar/multipolygon/scalar.rs index db0af0634..3e245583e 100644 --- a/src/scalar/multipolygon/scalar.rs +++ b/src/scalar/multipolygon/scalar.rs @@ -3,7 +3,6 @@ use crate::algorithm::native::eq::multi_polygon_eq; use crate::array::util::OffsetBufferUtils; use crate::array::{CoordBuffer, MultiPolygonArray}; use crate::geo_traits::MultiPolygonTrait; -use crate::scalar::multipolygon::MultiPolygonIterator; use crate::scalar::Polygon; use crate::trait_::{GeometryArraySelfMethods, GeometryScalarTrait}; use arrow_array::OffsetSizeTrait; @@ -26,6 +25,8 @@ pub struct MultiPolygon<'a, O: OffsetSizeTrait> { pub(crate) ring_offsets: Cow<'a, OffsetBuffer>, pub(crate) geom_index: usize, + + start_offset: usize, } impl<'a, O: OffsetSizeTrait> MultiPolygon<'a, O> { @@ -36,12 +37,14 @@ impl<'a, O: OffsetSizeTrait> MultiPolygon<'a, O> { ring_offsets: Cow<'a, OffsetBuffer>, geom_index: usize, ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); Self { coords, geom_offsets, polygon_offsets, ring_offsets, geom_index, + start_offset, } } @@ -52,13 +55,13 @@ impl<'a, O: OffsetSizeTrait> MultiPolygon<'a, O> { ring_offsets: &'a OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Borrowed(coords), - geom_offsets: Cow::Borrowed(geom_offsets), - polygon_offsets: Cow::Borrowed(polygon_offsets), - ring_offsets: Cow::Borrowed(ring_offsets), + Self::new( + Cow::Borrowed(coords), + Cow::Borrowed(geom_offsets), + Cow::Borrowed(polygon_offsets), + Cow::Borrowed(ring_offsets), geom_index, - } + ) } pub fn new_owned( @@ -68,13 +71,13 @@ impl<'a, O: OffsetSizeTrait> MultiPolygon<'a, O> { ring_offsets: OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Owned(coords), - geom_offsets: Cow::Owned(geom_offsets), - polygon_offsets: Cow::Owned(polygon_offsets), - ring_offsets: Cow::Owned(ring_offsets), + Self::new( + Cow::Owned(coords), + Cow::Owned(geom_offsets), + Cow::Owned(polygon_offsets), + Cow::Owned(ring_offsets), geom_index, - } + ) } /// Extracts the owned data. @@ -130,61 +133,38 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for MultiPolygon<'a, O> { impl<'a, O: OffsetSizeTrait> MultiPolygonTrait for MultiPolygon<'a, O> { type T = f64; type ItemType<'b> = Polygon<'a, O> where Self: 'b; - type Iter<'b> = MultiPolygonIterator<'a, O> where Self: 'b; - - fn polygons(&self) -> Self::Iter<'_> { - todo!() - // MultiPolygonIterator::new(self) - } fn num_polygons(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn polygon(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - // TODO: double check offsets is correct - Some(Polygon::new( + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Polygon::new( self.coords.clone(), self.polygon_offsets.clone(), self.ring_offsets.clone(), - start + i, - )) + self.start_offset + i, + ) } } impl<'a, O: OffsetSizeTrait> MultiPolygonTrait for &'a MultiPolygon<'a, O> { type T = f64; type ItemType<'b> = Polygon<'a, O> where Self: 'b; - type Iter<'b> = MultiPolygonIterator<'a, O> where Self: 'b; - - fn polygons(&self) -> Self::Iter<'_> { - MultiPolygonIterator::new(self) - } fn num_polygons(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start } - fn polygon(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start) { - return None; - } - - // TODO: double check offsets is correct - Some(Polygon::new( + unsafe fn polygon_unchecked(&self, i: usize) -> Self::ItemType<'_> { + Polygon::new( self.coords.clone(), self.polygon_offsets.clone(), self.ring_offsets.clone(), - start + i, - )) + self.start_offset + i, + ) } } diff --git a/src/scalar/polygon/iterator.rs b/src/scalar/polygon/iterator.rs deleted file mode 100644 index b3a804fdf..000000000 --- a/src/scalar/polygon/iterator.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::geo_traits::PolygonTrait; -use crate::scalar::{LineString, Polygon}; -use arrow_array::OffsetSizeTrait; - -/// Iterator of values of a [`PolygonArray`](crate::array::PolygonArray) -#[derive(Clone, Debug)] -pub struct PolygonInteriorIterator<'a, O: OffsetSizeTrait> { - geom: &'a Polygon<'a, O>, - index: usize, - end: usize, -} - -impl<'a, O: OffsetSizeTrait> PolygonInteriorIterator<'a, O> { - #[inline] - pub fn new(geom: &'a Polygon<'a, O>) -> Self { - Self { - geom, - index: 0, - end: geom.num_interiors(), - } - } -} - -impl<'a, O: OffsetSizeTrait> Iterator for PolygonInteriorIterator<'a, O> { - type Item = crate::scalar::LineString<'a, O>; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.end { - return None; - } - let old = self.index; - self.index += 1; - self.geom.interior(old) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.end - self.index, Some(self.end - self.index)) - } -} - -impl<'a, O: OffsetSizeTrait> ExactSizeIterator for PolygonInteriorIterator<'a, O> {} - -impl<'a, O: OffsetSizeTrait> DoubleEndedIterator for PolygonInteriorIterator<'a, O> { - #[inline] - fn next_back(&mut self) -> Option { - if self.index == self.end { - None - } else { - self.end -= 1; - self.geom.interior(self.end) - } - } -} - -impl<'a, O: OffsetSizeTrait> IntoIterator for &'a Polygon<'a, O> { - type Item = LineString<'a, O>; - type IntoIter = PolygonInteriorIterator<'a, O>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, O: OffsetSizeTrait> Polygon<'a, O> { - /// Returns an iterator of `LineString` - pub fn iter(&'a self) -> PolygonInteriorIterator<'a, O> { - PolygonInteriorIterator::new(self) - } -} diff --git a/src/scalar/polygon/mod.rs b/src/scalar/polygon/mod.rs index ee24f81c7..1ce32ec5e 100644 --- a/src/scalar/polygon/mod.rs +++ b/src/scalar/polygon/mod.rs @@ -1,7 +1,5 @@ -pub mod iterator; mod owned; mod scalar; -// pub use iterator::PolygonInteriorIterator; pub use owned::OwnedPolygon; pub use scalar::Polygon; diff --git a/src/scalar/polygon/scalar.rs b/src/scalar/polygon/scalar.rs index 733e376d4..d4fd3bcb7 100644 --- a/src/scalar/polygon/scalar.rs +++ b/src/scalar/polygon/scalar.rs @@ -4,7 +4,6 @@ use crate::array::polygon::parse_polygon; use crate::array::util::OffsetBufferUtils; use crate::array::{CoordBuffer, PolygonArray}; use crate::geo_traits::PolygonTrait; -use crate::scalar::polygon::iterator::PolygonInteriorIterator; use crate::scalar::LineString; use crate::trait_::{GeometryArraySelfMethods, GeometryScalarTrait}; use arrow_array::OffsetSizeTrait; @@ -24,6 +23,8 @@ pub struct Polygon<'a, O: OffsetSizeTrait> { pub(crate) ring_offsets: Cow<'a, OffsetBuffer>, pub(crate) geom_index: usize, + + start_offset: usize, } impl<'a, O: OffsetSizeTrait> Polygon<'a, O> { @@ -33,11 +34,13 @@ impl<'a, O: OffsetSizeTrait> Polygon<'a, O> { ring_offsets: Cow<'a, OffsetBuffer>, geom_index: usize, ) -> Self { + let (start_offset, _) = geom_offsets.start_end(geom_index); Self { coords, geom_offsets, ring_offsets, geom_index, + start_offset, } } @@ -47,12 +50,12 @@ impl<'a, O: OffsetSizeTrait> Polygon<'a, O> { ring_offsets: &'a OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Borrowed(coords), - geom_offsets: Cow::Borrowed(geom_offsets), - ring_offsets: Cow::Borrowed(ring_offsets), + Self::new( + Cow::Borrowed(coords), + Cow::Borrowed(geom_offsets), + Cow::Borrowed(ring_offsets), geom_index, - } + ) } pub fn new_owned( @@ -61,12 +64,12 @@ impl<'a, O: OffsetSizeTrait> Polygon<'a, O> { ring_offsets: OffsetBuffer, geom_index: usize, ) -> Self { - Self { - coords: Cow::Owned(coords), - geom_offsets: Cow::Owned(geom_offsets), - ring_offsets: Cow::Owned(ring_offsets), + Self::new( + Cow::Owned(coords), + Cow::Owned(geom_offsets), + Cow::Owned(ring_offsets), geom_index, - } + ) } /// Extracts the owned data. @@ -111,7 +114,6 @@ impl<'a, O: OffsetSizeTrait> GeometryScalarTrait for Polygon<'a, O> { impl<'a, O: OffsetSizeTrait> PolygonTrait for Polygon<'a, O> { type T = f64; type ItemType<'b> = LineString<'a, O> where Self: 'b; - type Iter<'b> = PolygonInteriorIterator<'a, O> where Self: 'b; fn exterior(&self) -> Option> { let (start, end) = self.geom_offsets.start_end(self.geom_index); @@ -126,34 +128,23 @@ impl<'a, O: OffsetSizeTrait> PolygonTrait for Polygon<'a, O> { } } - fn interiors(&self) -> Self::Iter<'_> { - todo!() - // PolygonInteriorIterator::new(self) - } - fn num_interiors(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start - 1 } - fn interior(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start - 1) { - return None; - } - - Some(LineString::new( + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + LineString::new( self.coords.clone(), self.ring_offsets.clone(), - start + 1 + i, - )) + self.start_offset + 1 + i, + ) } } impl<'a, O: OffsetSizeTrait> PolygonTrait for &'a Polygon<'a, O> { type T = f64; type ItemType<'b> = LineString<'a, O> where Self: 'b; - type Iter<'b> = PolygonInteriorIterator<'a, O> where Self: 'b; fn exterior(&self) -> Option> { let (start, end) = self.geom_offsets.start_end(self.geom_index); @@ -168,26 +159,17 @@ impl<'a, O: OffsetSizeTrait> PolygonTrait for &'a Polygon<'a, O> { } } - fn interiors(&self) -> Self::Iter<'_> { - PolygonInteriorIterator::new(self) - } - fn num_interiors(&self) -> usize { let (start, end) = self.geom_offsets.start_end(self.geom_index); end - start - 1 } - fn interior(&self, i: usize) -> Option> { - let (start, end) = self.geom_offsets.start_end(self.geom_index); - if i > (end - start - 1) { - return None; - } - - Some(LineString::new( + unsafe fn interior_unchecked(&self, i: usize) -> Self::ItemType<'_> { + LineString::new( self.coords.clone(), self.ring_offsets.clone(), - start + 1 + i, - )) + self.start_offset + 1 + i, + ) } }