Skip to content

Commit

Permalink
geozero (backward)
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn committed Jul 5, 2024
1 parent 5b539b8 commit 8d37c60
Show file tree
Hide file tree
Showing 8 changed files with 468 additions and 104 deletions.
5 changes: 5 additions & 0 deletions src/geometry/linestring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ impl<'a, T: Coord> LineString<'a, T> {
self.coords.to_mut().push(coord);
}

/// Extends the LineString with coordinates.
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.coords.to_mut().extend(iter);
}

/// Removes all points from the LineString.
pub fn clear(&mut self) {
self.coords.to_mut().clear();
Expand Down
3 changes: 3 additions & 0 deletions src/geometry/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::vec::Vec;

mod linestring;
mod multi_linestring;
mod multi_point;
Expand Down Expand Up @@ -55,6 +57,7 @@ pub enum Geometry<'a, T: Coord> {
MultiPolygon(MultiPolygon<'a, T>),
// Triangle?
// TIN?
GeometryCollection(Vec<Geometry<'a, T>>),
}

pub type Geometry2<'a, C = f64> = Geometry<'a, [C; 2]>;
Expand Down
5 changes: 5 additions & 0 deletions src/geometry/multi_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ impl<'a, T: Coord> MultiPoint<'a, T> {
self.coords.to_mut().push(coord);
}

/// Extends the MultiPoint with coordinates.
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.coords.to_mut().extend(iter);
}

/// Removes all points from the LineString.
pub fn clear(&mut self) {
self.coords.to_mut().clear();
Expand Down
22 changes: 20 additions & 2 deletions src/geozero/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
mod reader;
mod writer;
pub mod reader;
pub mod writer;

use alloc::string::ToString;
use geozero::error::{GeozeroError, Result};
use geozero::GeozeroGeometry;

pub trait ToFlatgeom<const D: usize> {
fn to_flatgeom(&self) -> Result<crate::Geometry<[f64; D]>>;
}

impl<const D: usize, T: GeozeroGeometry> ToFlatgeom<D> for T {
fn to_flatgeom(&self) -> Result<crate::Geometry<[f64; D]>> {
let mut writer = writer::FlatgeomWriter::<D>::new();
self.process_geom(&mut writer)?;
writer
.take_geometry()
.ok_or(GeozeroError::Geometry("Missing geometry".to_string()))
}
}
250 changes: 158 additions & 92 deletions src/geozero/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,29 @@ use geozero::{GeomProcessor, GeozeroGeometry};

impl<const D: usize> GeozeroGeometry for Geometry<'_, [f64; D]> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> geozero::error::Result<()> {
match self {
Geometry::MultiPoint(geom) => geom.process_geom(processor),
Geometry::LineString(geom) => geom.process_geom(processor),
Geometry::MultiLineString(geom) => geom.process_geom(processor),
Geometry::Polygon(geom) => geom.process_geom(processor),
Geometry::MultiPolygon(geom) => geom.process_geom(processor),
process_geometry(self, processor, 0)
}

Check warning on line 8 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L7-L8

Added lines #L7 - L8 were not covered by tests
}

fn process_geometry<const D: usize, P: geozero::GeomProcessor>(
geom: &Geometry<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
match geom {
Geometry::GeometryCollection(geoms) => {
processor.geometrycollection_begin(geoms.len(), idx)?;
for (geom_idx, geom) in geoms.iter().enumerate() {
process_geometry(geom, processor, geom_idx)?; // FIXME: idx

Check warning on line 20 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L11-L20

Added lines #L11 - L20 were not covered by tests
}
processor.geometrycollection_end(idx)?;
Ok(())

Check warning on line 23 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L22-L23

Added lines #L22 - L23 were not covered by tests
}
Geometry::MultiPoint(geom) => process_multipoint(geom, processor, idx),
Geometry::LineString(geom) => process_linestring(geom, processor, idx),
Geometry::MultiLineString(geom) => process_multilinestring(geom, processor, idx),
Geometry::Polygon(geom) => process_polygon(geom, processor, idx),
Geometry::MultiPolygon(geom) => process_multipolygon(geom, processor, idx),

Check warning on line 29 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L25-L29

Added lines #L25 - L29 were not covered by tests
}
}

Expand All @@ -19,133 +35,183 @@ impl<const D: usize> geozero::GeozeroGeometry for MultiPoint<'_, [f64; D]> {
&self,
processor: &mut P,
) -> geozero::error::Result<()> {
let idx = 0;
processor.multipoint_begin(self.len(), idx)?;
for point in self.iter() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(point[0], point[1], Some(point[2]), None, None, None, idx)?;
} else {
processor.xy(point[0], point[1], idx)?;
}
process_multipoint(self, processor, 0)
}
}

fn process_multipoint<const D: usize, P: geozero::GeomProcessor>(
geom: &MultiPoint<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
processor.multipoint_begin(geom.len(), idx)?;
for (coord_idx, coord) in geom.iter().enumerate() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
coord[0],
coord[1],
Some(coord[2]),
None,
None,
None,
coord_idx,
)?;

Check warning on line 58 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L50-L58

Added lines #L50 - L58 were not covered by tests
} else {
processor.xy(coord[0], coord[1], coord_idx)?;
}
processor.multipoint_end(idx)?;
Ok(())
}
processor.multipoint_end(idx)?;
Ok(())
}

impl<const D: usize> geozero::GeozeroGeometry for LineString<'_, [f64; D]> {
fn process_geom<P: geozero::GeomProcessor>(
&self,
processor: &mut P,
) -> geozero::error::Result<()> {
let idx = 0;
processor.linestring_begin(true, self.len(), idx)?;
for point in self.iter() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(point[0], point[1], Some(point[2]), None, None, None, idx)?;
} else {
processor.xy(point[0], point[1], idx)?;
}
process_linestring(self, processor, 0)
}
}

fn process_linestring<const D: usize, P: geozero::GeomProcessor>(
geom: &LineString<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
processor.linestring_begin(true, geom.len(), idx)?;
for (coord_idx, coord) in geom.iter().enumerate() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
coord[0],
coord[1],
Some(coord[2]),
None,
None,
None,
coord_idx,
)?;

Check warning on line 92 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L84-L92

Added lines #L84 - L92 were not covered by tests
} else {
processor.xy(coord[0], coord[1], coord_idx)?;
}
processor.linestring_end(true, idx)?;
Ok(())
}
processor.linestring_end(true, idx)?;
Ok(())
}

impl<const D: usize> geozero::GeozeroGeometry for MultiLineString<'_, [f64; D]> {
fn process_geom<P: geozero::GeomProcessor>(
&self,
processor: &mut P,
) -> geozero::error::Result<()> {
let idx = 0;
processor.multilinestring_begin(self.len(), idx)?;
for ls in self {
processor.linestring_begin(false, ls.len(), idx)?;
for point in &ls {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
point[0],
point[1],
Some(point[2]),
None,
None,
None,
idx,
)?;
} else {
processor.xy(point[0], point[1], idx)?;
}
process_multilinestring(self, processor, 0)
}
}

fn process_multilinestring<const D: usize, P: geozero::GeomProcessor>(
geom: &MultiLineString<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
processor.multilinestring_begin(geom.len(), idx)?;
for (ls_idx, ls) in geom.iter().enumerate() {
processor.linestring_begin(false, ls.len(), ls_idx)?;
for (coord_idx, coord) in ls.iter().enumerate() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
coord[0],
coord[1],
Some(coord[2]),
None,
None,
None,
coord_idx,
)?;

Check warning on line 128 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L120-L128

Added lines #L120 - L128 were not covered by tests
} else {
processor.xy(coord[0], coord[1], coord_idx)?;
}
processor.linestring_end(false, idx)?;
}
processor.multilinestring_end(idx)?;
Ok(())
processor.linestring_end(false, ls_idx)?;
}
processor.multilinestring_end(idx)?;
Ok(())
}

impl<const D: usize> geozero::GeozeroGeometry for Polygon<'_, [f64; D]> {
fn process_geom<P: geozero::GeomProcessor>(
&self,
processor: &mut P,
) -> geozero::error::Result<()> {
let idx = 0;
processor.polygon_begin(true, self.len(), idx)?;
for ls in self.rings() {
processor.linestring_begin(false, ls.len(), idx)?;
for point in ls.iter_closed() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
point[0],
point[1],
Some(point[2]),
None,
None,
None,
idx,
)?;
} else {
processor.xy(point[0], point[1], idx)?;
}
process_polygon(self, processor, 0)
}
}

fn process_polygon<const D: usize, P: geozero::GeomProcessor>(
geom: &Polygon<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
processor.polygon_begin(true, geom.len(), idx)?;
for (ls_idx, ls) in geom.rings().enumerate() {
processor.linestring_begin(false, ls.len(), ls_idx)?;
for (coord_idx, coord) in ls.iter_closed().enumerate() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
coord[0],
coord[1],
Some(coord[2]),
None,
None,
None,
coord_idx,
)?;

Check warning on line 166 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L158-L166

Added lines #L158 - L166 were not covered by tests
} else {
processor.xy(coord[0], coord[1], coord_idx)?;
}
processor.linestring_end(false, idx)?;
}
processor.polygon_end(true, idx)?;
Ok(())
processor.linestring_end(false, ls_idx)?;
}
processor.polygon_end(true, idx)?;
Ok(())
}

impl<const D: usize> geozero::GeozeroGeometry for MultiPolygon<'_, [f64; D]> {
fn process_geom<P: geozero::GeomProcessor>(
&self,
processor: &mut P,
) -> geozero::error::Result<()> {
let idx = 0;
process_multipolygon(self, processor, 0)
}
}

processor.multipolygon_begin(self.len(), idx)?;
for poly in self.iter() {
processor.polygon_begin(false, poly.len() + 1, idx)?;
for ls in poly.rings() {
processor.linestring_begin(false, ls.len(), idx)?;
for point in ls.iter_closed() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
point[0],
point[1],
Some(point[2]),
None,
None,
None,
idx,
)?;
} else {
processor.xy(point[0], point[1], idx)?;
}
fn process_multipolygon<const D: usize, P: geozero::GeomProcessor>(
geom: &MultiPolygon<'_, [f64; D]>,
processor: &mut P,
idx: usize,
) -> Result<(), geozero::error::GeozeroError> {
processor.multipolygon_begin(geom.len(), idx)?;
for (poly_idx, poly) in geom.iter().enumerate() {
processor.polygon_begin(false, poly.len() + 1, poly_idx)?;
for (ls_idx, ls) in poly.rings().enumerate() {
processor.linestring_begin(false, ls.len(), ls_idx)?;
for (coord_idx, coord) in ls.iter_closed().enumerate() {
if processor.multi_dim() && D >= 3 {
processor.coordinate(
coord[0],
coord[1],
Some(coord[2]),
None,
None,
None,
coord_idx,
)?;

Check warning on line 206 in src/geozero/reader.rs

View check run for this annotation

Codecov / codecov/patch

src/geozero/reader.rs#L198-L206

Added lines #L198 - L206 were not covered by tests
} else {
processor.xy(coord[0], coord[1], coord_idx)?;
}
processor.linestring_end(false, idx)?;
}
processor.polygon_end(false, idx)?;
processor.linestring_end(false, ls_idx)?;
}
processor.multipolygon_end(idx)?;
Ok(())
processor.polygon_end(false, poly_idx)?;
}
processor.multipolygon_end(idx)?;
Ok(())
}
Loading

0 comments on commit 8d37c60

Please sign in to comment.