Skip to content

Commit

Permalink
Merge #410
Browse files Browse the repository at this point in the history
410: Update Geometry enum and GeometryCollection r=urschrei a=urschrei

This PR:

- Adds non-consuming iteration functionality (`iter()`, `iter_mut()`) and indexing to `GeometryCollection`
- Adds `TryFrom` impls from `Geometry` enums to `Geo` primitives (deprecating but not removing the previous functions)
- Doctest examples of working with `GeometryCollection`

Co-authored-by: Stephan Hügel <urschrei@gmail.com>
Co-authored-by: Stephan Hügel <shugel@tcd.ie>
  • Loading branch information
3 people committed Mar 1, 2020
2 parents 3539124 + 88fc1d8 commit f584c75
Show file tree
Hide file tree
Showing 3 changed files with 316 additions and 6 deletions.
152 changes: 151 additions & 1 deletion geo-types/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@ use crate::{
CoordinateType, GeometryCollection, Line, LineString, MultiLineString, MultiPoint,
MultiPolygon, Point, Polygon,
};
use num_traits::Float;
use std::convert::TryFrom;
use std::error::Error;
use std::fmt;

/// An enum representing any possible geometry type.
///
/// All `Geo` types can be converted to a `Geometry` member using `.into()` (as part of the
/// `std::convert::Into` pattern).
/// `std::convert::Into` pattern), and `Geo` types implement the `TryFrom` trait in order to
/// convert _back_ from enum members.
///
/// # Example
///
/// ```
/// use std::convert::TryFrom;
/// use geo_types::{Point, point, Geometry, GeometryCollection};
/// let p = point!(x: 1.0, y: 1.0);
/// let pe: Geometry<f64> = p.into();
/// let pn = Point::try_from(pe).unwrap();
/// ```
///
#[derive(PartialEq, Clone, Debug, Hash)]
pub enum Geometry<T>
where
Expand Down Expand Up @@ -69,6 +85,9 @@ impl<T: CoordinateType> Geometry<T> {
/// let p2: Point<f32> = g.into_point().unwrap();
/// assert_eq!(p2, Point::new(0., 0.,));
/// ```
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Point>"
)]
pub fn into_point(self) -> Option<Point<T>> {
if let Geometry::Point(x) = self {
Some(x)
Expand All @@ -78,6 +97,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a LineString, then return that LineString, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<LineString>"
)]
pub fn into_line_string(self) -> Option<LineString<T>> {
if let Geometry::LineString(x) = self {
Some(x)
Expand All @@ -87,6 +109,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a Line, then return that Line, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Line>"
)]
pub fn into_line(self) -> Option<Line<T>> {
if let Geometry::Line(x) = self {
Some(x)
Expand All @@ -96,6 +121,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a Polygon, then return that, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Polygon>"
)]
pub fn into_polygon(self) -> Option<Polygon<T>> {
if let Geometry::Polygon(x) = self {
Some(x)
Expand All @@ -105,6 +133,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a MultiPoint, then return that, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiPoint>"
)]
pub fn into_multi_point(self) -> Option<MultiPoint<T>> {
if let Geometry::MultiPoint(x) = self {
Some(x)
Expand All @@ -114,6 +145,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a MultiLineString, then return that, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiLineString>"
)]
pub fn into_multi_line_string(self) -> Option<MultiLineString<T>> {
if let Geometry::MultiLineString(x) = self {
Some(x)
Expand All @@ -123,6 +157,9 @@ impl<T: CoordinateType> Geometry<T> {
}

/// If this Geometry is a MultiPolygon, then return that, else None.
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiPolygon>"
)]
pub fn into_multi_polygon(self) -> Option<MultiPolygon<T>> {
if let Geometry::MultiPolygon(x) = self {
Some(x)
Expand All @@ -131,3 +168,116 @@ impl<T: CoordinateType> Geometry<T> {
}
}
}

#[derive(Debug)]
pub struct FailedToConvertError;

impl fmt::Display for FailedToConvertError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Could not convert from enum member to concrete type")
}
}

impl Error for FailedToConvertError {
fn description(&self) -> &str {
"Could not convert from enum member to concrete type"
}
}

impl<T> TryFrom<Geometry<T>> for Point<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<Point<T>, Self::Error> {
match geom {
Geometry::Point(p) => Ok(p),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for Line<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<Line<T>, Self::Error> {
match geom {
Geometry::Line(l) => Ok(l),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for LineString<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<LineString<T>, Self::Error> {
match geom {
Geometry::LineString(ls) => Ok(ls),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for Polygon<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<Polygon<T>, Self::Error> {
match geom {
Geometry::Polygon(ls) => Ok(ls),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for MultiPoint<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<MultiPoint<T>, Self::Error> {
match geom {
Geometry::MultiPoint(mp) => Ok(mp),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for MultiLineString<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<MultiLineString<T>, Self::Error> {
match geom {
Geometry::MultiLineString(mls) => Ok(mls),
_ => Err(FailedToConvertError),
}
}
}

impl<T> TryFrom<Geometry<T>> for MultiPolygon<T>
where
T: Float,
{
type Error = FailedToConvertError;

fn try_from(geom: Geometry<T>) -> Result<MultiPolygon<T>, Self::Error> {
match geom {
Geometry::MultiPolygon(mp) => Ok(mp),
_ => Err(FailedToConvertError),
}
}
}

0 comments on commit f584c75

Please sign in to comment.