Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deps and try #78

Merged
merged 5 commits into from Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "geos"
version = "6.0.0"
version = "7.0.0"
authors = ["Matthieu Viry <matthieu.viry@cnrs.fr>", "Adrien Matissart <a.matissart@qwantresearch.com>", "Antoine Desbordes <antoine.desbordes@gmail.com>", "Guillaume Pinot <texitoi@texitoi.eu>", "Guillaume Gomez <guillaume1.gomez@gmail.com>"]
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
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
@@ -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