Skip to content

Commit

Permalink
Merge pull request #4 from MIERUNE/geozero-backward
Browse files Browse the repository at this point in the history
From GeoZero (reverse conversion)
  • Loading branch information
ciscorn authored Jul 5, 2024
2 parents 5b539b8 + 0310d85 commit cc236eb
Show file tree
Hide file tree
Showing 8 changed files with 655 additions and 106 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)
}
}

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
}
processor.geometrycollection_end(idx)?;
Ok(())
}
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),
}
}

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,
)?;
} 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,
)?;
} 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,
)?;
} 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,
)?;
} 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,
)?;
} 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 cc236eb

Please sign in to comment.