Skip to content

Commit

Permalink
Merge pull request #78 from GuillaumeGomez/deps-and-try
Browse files Browse the repository at this point in the history
Deps and try
  • Loading branch information
GuillaumeGomez authored Jul 30, 2020
2 parents f014049 + 11f909a commit fb6dc85
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 113 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "geos"
version = "6.0.0"
version = "7.0.0"
authors = ["Matthieu Viry <[email protected]>", "Adrien Matissart <[email protected]>", "Antoine Desbordes <[email protected]>", "Guillaume Pinot <[email protected]>", "Guillaume Gomez <[email protected]>"]
license = "MIT"
repository = "https://github.com/georust/geos"
Expand All @@ -22,8 +22,8 @@ libc = "0.2"
num = "0.2"
c_vec = "1.3"
geojson = { version = "0.19", optional = true }
geo-types = { version = "0.4", optional = true }
wkt = { version = "0.5", optional = true }
geo-types = { version = "0.6", optional = true }
wkt = { version = "0.8", optional = true }
geos-sys = "2.0"
doc-comment = "0.3"

Expand Down
11 changes: 6 additions & 5 deletions examples/from_geo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ extern crate geos;
#[cfg(feature = "geo")]
use geo_types::{Coordinate, LineString, Polygon};
#[cfg(feature = "geo")]
use geos::from_geo::TryInto;
#[cfg(feature = "geo")]
use geos::{Error, Geom, Geometry};
#[cfg(feature = "geo")]
use std::convert::TryInto;

#[cfg(feature = "geo")]
fn fun() -> Result<(), Error> {
Expand All @@ -33,10 +33,11 @@ fn fun() -> Result<(), Error> {
let geom: Geometry = (&p).try_into()?;

assert!(geom.contains(&geom)?);
assert!(!geom.contains(&(&exterior).try_into()?)?);
let tmp: Geometry = (&exterior).try_into()?;
assert!(!geom.contains(&tmp)?);

assert!(geom.covers(&(&exterior).try_into()?)?);
assert!(geom.touches(&(&exterior).try_into()?)?);
assert!(geom.covers(&tmp)?);
assert!(geom.touches(&tmp)?);
Ok(())
}

Expand Down
112 changes: 72 additions & 40 deletions src/from_geo.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
use crate::{CoordDimensions, CoordSeq, Geometry as GGeometry};
use error::Error;
use geo_types::{Coordinate, LineString, MultiPolygon, Point, Polygon};

use std;
use std::borrow::Borrow;
use std::convert::{TryFrom, TryInto};

// define our own TryInto while the std trait is not stable
pub trait TryInto<T> {
type Err;
fn try_into(self) -> Result<T, Self::Err>;
}

fn create_coord_seq_from_vec<'a>(coords: &'a [Coordinate<f64>]) -> Result<CoordSeq, Error> {
fn create_coord_seq_from_vec<'a, 'b>(coords: &'a [Coordinate<f64>]) -> Result<CoordSeq<'b>, Error> {
create_coord_seq(coords.iter(), coords.len())
}

Expand All @@ -27,21 +23,29 @@ where
Ok(coord_seq)
}

impl<'a> TryInto<GGeometry<'a>> for &'a Point<f64> {
type Err = Error;
impl<'a, 'b> TryFrom<&'a Point<f64>> for GGeometry<'b> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'a>, Self::Err> {
let coord_seq = create_coord_seq(std::iter::once(&self.0), 1)?;
fn try_from(other: &'a Point<f64>) -> Result<GGeometry<'b>, Self::Error> {
let coord_seq = create_coord_seq(std::iter::once(&other.0), 1)?;

GGeometry::create_point(coord_seq)
}
}

impl<'a, T: Borrow<Point<f64>>> TryInto<GGeometry<'a>> for &'a [T] {
type Err = Error;
impl<'a> TryFrom<Point<f64>> for GGeometry<'a> {
type Error = Error;

fn try_from(other: Point<f64>) -> Result<GGeometry<'a>, Self::Error> {
GGeometry::try_from(&other)
}
}

impl<'a, T: Borrow<Point<f64>>> TryFrom<&'a [T]> for GGeometry<'a> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'a>, Self::Err> {
let geom_points = self
fn try_from(other: &'a [T]) -> Result<GGeometry<'a>, Self::Error> {
let geom_points = other
.into_iter()
.map(|p| p.borrow().try_into())
.collect::<Result<Vec<_>, _>>()?;
Expand All @@ -50,27 +54,35 @@ impl<'a, T: Borrow<Point<f64>>> TryInto<GGeometry<'a>> for &'a [T] {
}
}

impl<'a> TryInto<GGeometry<'a>> for &'a LineString<f64> {
type Err = Error;
impl<'a, 'b> TryFrom<&'a LineString<f64>> for GGeometry<'b> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'a>, Self::Err> {
let coord_seq = create_coord_seq_from_vec(self.0.as_slice())?;
fn try_from(other: &'a LineString<f64>) -> Result<GGeometry<'b>, Self::Error> {
let coord_seq = create_coord_seq_from_vec(other.0.as_slice())?;

GGeometry::create_line_string(coord_seq)
}
}

impl<'a> TryFrom<LineString<f64>> for GGeometry<'a> {
type Error = Error;

fn try_from(other: LineString<f64>) -> Result<GGeometry<'a>, Self::Error> {
GGeometry::try_from(&other)
}
}

// rust geo does not have the distinction LineString/LineRing, so we create a wrapper

struct LineRing<'a>(&'a LineString<f64>);

/// Convert a geo_types::LineString to a geos LinearRing
/// a LinearRing should be closed so cloase the geometry if needed
impl<'a, 'b> TryInto<GGeometry<'b>> for &'a LineRing<'b> {
type Err = Error;
impl<'a, 'b> TryFrom<LineRing<'a>> for GGeometry<'b> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'b>, Self::Err> {
let points = &(self.0).0;
fn try_from(other: LineRing<'a>) -> Result<GGeometry<'b>, Self::Error> {
let points = &(other.0).0;
let nb_points = points.len();
if nb_points > 0 && nb_points < 3 {
return Err(Error::InvalidGeometry(
Expand All @@ -95,14 +107,14 @@ impl<'a, 'b> TryInto<GGeometry<'b>> for &'a LineRing<'b> {
}
}

impl<'a> TryInto<GGeometry<'a>> for &'a Polygon<f64> {
type Err = Error;
impl<'a, 'b> TryFrom<&'a Polygon<f64>> for GGeometry<'b> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'a>, Self::Err> {
let ring = LineRing(self.exterior());
fn try_from(other: &'a Polygon<f64>) -> Result<GGeometry<'b>, Self::Error> {
let ring = LineRing(other.exterior());
let geom_exterior: GGeometry = ring.try_into()?;

let interiors: Vec<_> = self
let interiors: Vec<_> = other
.interiors()
.iter()
.map(|i| LineRing(i).try_into())
Expand All @@ -112,11 +124,19 @@ impl<'a> TryInto<GGeometry<'a>> for &'a Polygon<f64> {
}
}

impl<'a> TryInto<GGeometry<'a>> for &'a MultiPolygon<f64> {
type Err = Error;
impl<'a> TryFrom<Polygon<f64>> for GGeometry<'a> {
type Error = Error;

fn try_from(other: Polygon<f64>) -> Result<GGeometry<'a>, Self::Error> {
GGeometry::try_from(&other)
}
}

impl<'a, 'b> TryFrom<&'a MultiPolygon<f64>> for GGeometry<'b> {
type Error = Error;

fn try_into(self) -> Result<GGeometry<'a>, Self::Err> {
let polygons: Vec<_> = self
fn try_from(other: &'a MultiPolygon<f64>) -> Result<GGeometry<'b>, Self::Error> {
let polygons: Vec<_> = other
.0
.iter()
.map(|p| p.try_into())
Expand All @@ -126,12 +146,20 @@ impl<'a> TryInto<GGeometry<'a>> for &'a MultiPolygon<f64> {
}
}

impl<'a> TryFrom<MultiPolygon<f64>> for GGeometry<'a> {
type Error = Error;

fn try_from(other: MultiPolygon<f64>) -> Result<GGeometry<'a>, Self::Error> {
GGeometry::try_from(&other)
}
}

#[cfg(test)]
mod test {
use super::LineRing;
use crate::{Geom, Geometry as GGeometry};
use from_geo::TryInto;
use geo_types::{Coordinate, LineString, MultiPolygon, Polygon};
use std::convert::TryInto;

fn coords(tuples: Vec<(f64, f64)>) -> Vec<Coordinate<f64>> {
tuples.into_iter().map(Coordinate::from).collect()
Expand All @@ -158,13 +186,15 @@ mod test {
assert_eq!(p.exterior(), &exterior);
assert_eq!(p.interiors(), interiors.as_slice());

let geom: GGeometry = (&p).try_into().unwrap();
let geom: GGeometry = p.try_into().unwrap();

assert!(geom.contains(&geom).unwrap());
assert!(!geom.contains(&(&exterior).try_into().unwrap()).unwrap());

assert!(geom.covers(&(&exterior).try_into().unwrap()).unwrap());
assert!(geom.touches(&(&exterior).try_into().unwrap()).unwrap());
let tmp: GGeometry = exterior.try_into().unwrap();

assert!(!geom.contains(&tmp).unwrap());
assert!(geom.covers(&tmp).unwrap());
assert!(geom.touches(&tmp).unwrap());
}

#[test]
Expand All @@ -189,7 +219,9 @@ mod test {
let geom: GGeometry = (&mp).try_into().unwrap();

assert!(geom.contains(&geom).unwrap());
assert!(geom.contains(&(&p).try_into().unwrap()).unwrap());
assert!(geom
.contains::<GGeometry>(&(&p).try_into().unwrap())
.unwrap());
}

#[test]
Expand All @@ -199,7 +231,7 @@ mod test {
let p = Polygon::new(exterior, interiors);
let mp = MultiPolygon(vec![p.clone()]);

let geom = (&mp).try_into();
let geom: Result<GGeometry, _> = mp.try_into();

assert!(geom.is_err());
}
Expand All @@ -224,7 +256,7 @@ mod test {
let p = Polygon::new(exterior, interiors);
let mp = MultiPolygon(vec![p]);

let _g = (&mp).try_into().unwrap(); // no error
let _g: GGeometry = mp.try_into().unwrap(); // no error
}

/// a linear ring can be empty
Expand Down
Loading

0 comments on commit fb6dc85

Please sign in to comment.