From 963a3cd14aebb58a5d1638cc208ca2afb66bcfaf Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 1 Mar 2020 21:44:12 -0800 Subject: [PATCH 01/10] _ --- geo-types/src/geometry.rs | 93 ++++++++++++++++- geo-types/src/lib.rs | 2 +- geo-types/src/triangle.rs | 2 +- geo/src/algorithm/area.rs | 172 ++++++++++++++++++++++++-------- geo/src/algorithm/map_coords.rs | 90 ++++++++++++++++- geo/src/lib.rs | 2 +- 6 files changed, 315 insertions(+), 46 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index 85b28bea4..22518a581 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -1,6 +1,6 @@ use crate::{ CoordinateType, GeometryCollection, Line, LineString, MultiLineString, MultiPoint, - MultiPolygon, Point, Polygon, + MultiPolygon, Point, Polygon, Rect, Triangle }; use num_traits::Float; use std::convert::TryFrom; @@ -36,6 +36,8 @@ where MultiLineString(MultiLineString), MultiPolygon(MultiPolygon), GeometryCollection(GeometryCollection), + Rect(Rect), + Triangle(Triangle), } impl From> for Geometry { @@ -73,6 +75,95 @@ impl From> for Geometry { Geometry::MultiPolygon(x) } } +impl From> for Geometry { + fn from(x: Rect) -> Geometry { + Geometry::Rect(x) + } +} +impl From> for Geometry { + fn from(x: Triangle) -> Geometry { + Geometry::Triangle(x) + } +} + +// TODO impl deref? or borrow? or as_ref? + +#[derive(PartialEq, Clone, Debug, Hash)] +pub enum GeometryRef<'a, T> +where + T: CoordinateType, +{ + Point(&'a Point), + Line(&'a Line), + LineString(&'a LineString), + Polygon(&'a Polygon), + MultiPoint(&'a MultiPoint), + MultiLineString(&'a MultiLineString), + MultiPolygon(&'a MultiPolygon), + GeometryCollection(&'a GeometryCollection), + Rect(&'a Rect), + Triangle(&'a Triangle), +} + +impl<'a, T: 'a + CoordinateType> From<&'a Point> for GeometryRef<'a, T> { + fn from(x: &'a Point) -> GeometryRef<'a, T> { + GeometryRef::Point(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a Line> for GeometryRef<'a, T> { + fn from(x: &'a Line) -> GeometryRef<'a, T> { + GeometryRef::Line(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a LineString> for GeometryRef<'a, T> { + fn from(x: &'a LineString) -> GeometryRef<'a, T> { + GeometryRef::LineString(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a Polygon> for GeometryRef<'a, T> { + fn from(x: &'a Polygon) -> GeometryRef<'a, T> { + GeometryRef::Polygon(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a MultiPoint> for GeometryRef<'a, T> { + fn from(x: &'a MultiPoint) -> GeometryRef<'a, T> { + GeometryRef::MultiPoint(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a MultiLineString> for GeometryRef<'a, T> { + fn from(x: &'a MultiLineString) -> GeometryRef<'a, T> { + GeometryRef::MultiLineString(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a MultiPolygon> for GeometryRef<'a, T> { + fn from(x: &'a MultiPolygon) -> GeometryRef<'a, T> { + GeometryRef::MultiPolygon(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a GeometryCollection> for GeometryRef<'a, T> { + fn from(x: &'a GeometryCollection) -> GeometryRef<'a, T> { + GeometryRef::GeometryCollection(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a Rect> for GeometryRef<'a, T> { + fn from(x: &'a Rect) -> GeometryRef<'a, T> { + GeometryRef::Rect(x) + } +} + +impl<'a, T: 'a + CoordinateType> From<&'a Triangle> for GeometryRef<'a, T> { + fn from(x: &'a Triangle) -> GeometryRef<'a, T> { + GeometryRef::Triangle(x) + } +} impl Geometry { /// If this Geometry is a Point, then return that, else None. diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index 0a054b6ed..cc83e0577 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -50,7 +50,7 @@ mod multi_polygon; pub use crate::multi_polygon::MultiPolygon; mod geometry; -pub use crate::geometry::Geometry; +pub use crate::geometry::{Geometry, GeometryRef}; mod geometry_collection; pub use crate::geometry_collection::GeometryCollection; diff --git a/geo-types/src/triangle.rs b/geo-types/src/triangle.rs index 03233e555..c144b22aa 100644 --- a/geo-types/src/triangle.rs +++ b/geo-types/src/triangle.rs @@ -1,7 +1,7 @@ use crate::{Coordinate, CoordinateType, Line}; /// A bounded 2D area whose three vertices are defined by `Coordinate`s. -#[derive(Copy, Clone, Debug, Hash)] +#[derive(Copy, Clone, Debug, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Triangle(pub Coordinate, pub Coordinate, pub Coordinate); diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 5183242ae..218d2fced 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,5 +1,6 @@ -use crate::{CoordinateType, Line, LineString, MultiPolygon, Polygon, Rect, Triangle}; +use crate::{Geometry, CoordinateType, Line, LineString, MultiPolygon, Polygon, Rect, Triangle, GeometryRef, Point}; use num_traits::Float; +use std::borrow::Cow; use crate::algorithm::winding_order::twice_signed_ring_area; @@ -42,60 +43,149 @@ where twice_signed_ring_area(linestring) / (T::one() + T::one()) } -impl Area for Line +// impl Area for Line +// where +// T: CoordinateType, +// { +// fn area(&self) -> T { +// T::zero() +// } +// } + +// impl Area for Polygon +// where +// T: Float, +// { +// fn area(&self) -> T { +// self.interiors() +// .iter() +// .fold(get_linestring_area(self.exterior()), |total, next| { +// total - get_linestring_area(next) +// }) +// } +// } + +// impl Area for MultiPolygon +// where +// T: Float, +// { +// fn area(&self) -> T { +// self.0 +// .iter() +// .fold(T::zero(), |total, next| total + next.area()) +// } +// } + +// impl Area for Rect +// where +// T: CoordinateType, +// { +// fn area(&self) -> T { +// self.width() * self.height() +// } +// } + +// impl Area for Triangle +// where +// T: Float, +// { +// fn area(&self) -> T { +// self.to_lines() +// .iter() +// .fold(T::zero(), |total, line| total + line.determinant()) +// / (T::one() + T::one()) +// } +// } + +/////////////////////////////////////////////// + +// impl Area for &I +// where +// I: Into>, +// T: CoordinateType, +// { +// fn area(&self) -> T { +// let geometry: Geometry = self.into(); +// match geometry { +// Geometry::Point(g) => unimplemented!(), +// Geometry::Line(g) => unimplemented!(), +// Geometry::LineString(g) => unimplemented!(), +// Geometry::Polygon(g) => unimplemented!(), +// Geometry::MultiPoint(g) => unimplemented!(), +// Geometry::MultiLineString(g) => unimplemented!(), +// Geometry::MultiPolygon(g) => unimplemented!(), +// Geometry::GeometryCollection(g) => unimplemented!(), +// Geometry::Rect(g) => unimplemented!(), +// Geometry::Triangle(g) => unimplemented!(), +// } +// } +// } + +// impl Area for I +// where +// I: ToOwned, +// J: Into> + std::borrow::Borrow, +// T: CoordinateType, +// { +// fn area(&self) -> T { +// let owned: J = self.to_owned().to_owned(); +// let geometry: Geometry = owned.into(); +// match geometry { +// Geometry::Point(g) => unimplemented!(), +// Geometry::Line(g) => unimplemented!(), +// Geometry::LineString(g) => unimplemented!(), +// Geometry::Polygon(g) => unimplemented!(), +// Geometry::MultiPoint(g) => unimplemented!(), +// Geometry::MultiLineString(g) => unimplemented!(), +// Geometry::MultiPolygon(g) => unimplemented!(), +// Geometry::GeometryCollection(g) => unimplemented!(), +// Geometry::Rect(g) => unimplemented!(), +// Geometry::Triangle(g) => unimplemented!(), +// } +// } +// } + +impl Area for I where + for<'a> &'a I: Into>>, T: CoordinateType, { fn area(&self) -> T { - T::zero() + let geometry_ref: Cow> = self.into(); + match *geometry_ref { + Geometry::Point(g) => unimplemented!(), + Geometry::Line(g) => unimplemented!(), + Geometry::LineString(g) => unimplemented!(), + Geometry::Polygon(g) => unimplemented!(), + Geometry::MultiPoint(g) => unimplemented!(), + Geometry::MultiLineString(g) => unimplemented!(), + Geometry::MultiPolygon(g) => unimplemented!(), + Geometry::GeometryCollection(g) => unimplemented!(), + Geometry::Rect(g) => unimplemented!(), + Geometry::Triangle(g) => unimplemented!(), + } } } -impl Area for Polygon -where - T: Float, -{ - fn area(&self) -> T { - self.interiors() - .iter() - .fold(get_linestring_area(self.exterior()), |total, next| { - total - get_linestring_area(next) - }) - } -} +/////////////////////////////////////////////// -impl Area for MultiPolygon -where - T: Float, -{ - fn area(&self) -> T { - self.0 - .iter() - .fold(T::zero(), |total, next| total + next.area()) - } -} +struct NewPoint(Point); -impl Area for Rect -where - T: CoordinateType, -{ - fn area(&self) -> T { - self.width() * self.height() +impl<'a, T: Float> Into>> for &'_ NewPoint { + fn into(self) -> Cow<'a, Geometry> { + Cow::Owned(Geometry::Point(self.0)) } } -impl Area for Triangle -where - T: Float, -{ - fn area(&self) -> T { - self.to_lines() - .iter() - .fold(T::zero(), |total, line| total + line.determinant()) - / (T::one() + T::one()) - } +// /////////////////////////////////////////////// + +fn foo() { + let n = NewPoint(geo_types::point!(x: 1.0, y: 1.0)); + let a = n.area(); } +/////////////////////////////////////////////// + #[cfg(test)] mod test { use crate::algorithm::area::Area; diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index 9bde6143b..8462d7b22 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -1,6 +1,6 @@ use crate::{ Coordinate, CoordinateType, Geometry, GeometryCollection, Line, LineString, MultiLineString, - MultiPoint, MultiPolygon, Point, Polygon, Rect, + MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle }; use std::error::Error; @@ -380,6 +380,8 @@ impl MapCoords for Geometry { Geometry::MultiLineString(ref x) => Geometry::MultiLineString(x.map_coords(func)), Geometry::MultiPolygon(ref x) => Geometry::MultiPolygon(x.map_coords(func)), Geometry::GeometryCollection(ref x) => Geometry::GeometryCollection(x.map_coords(func)), + Geometry::Rect(ref x) => Geometry::Rect(x.map_coords(func)), + Geometry::Triangle(ref x) => Geometry::Triangle(x.map_coords(func)), } } } @@ -404,6 +406,12 @@ impl TryMapCoords for Geometry Geometry::GeometryCollection(ref x) => { Ok(Geometry::GeometryCollection(x.try_map_coords(func)?)) } + Geometry::Rect(ref x) => { + Ok(Geometry::Rect(x.try_map_coords(func)?)) + } + Geometry::Triangle(ref x) => { + Ok(Geometry::Triangle(x.try_map_coords(func)?)) + } } } } @@ -419,6 +427,8 @@ impl MapCoordsInplace for Geometry { Geometry::MultiLineString(ref mut x) => x.map_coords_inplace(func), Geometry::MultiPolygon(ref mut x) => x.map_coords_inplace(func), Geometry::GeometryCollection(ref mut x) => x.map_coords_inplace(func), + Geometry::Rect(ref mut x) => x.map_coords_inplace(func), + Geometry::Triangle(ref mut x) => x.map_coords_inplace(func), } } } @@ -509,6 +519,84 @@ impl MapCoordsInplace for Rect { } } +impl MapCoords for Triangle { + type Output = Triangle; + + fn map_coords(&self, func: impl Fn(&(T, T)) -> (NT, NT) + Copy) -> Self::Output { + let p1 = func(&self.0.x_y()); + let p2 = func(&self.0.x_y()); + let p3 = func(&self.0.x_y()); + + Triangle( + Coordinate { + x: p1.0, + y: p1.1, + }, + Coordinate { + x: p2.0, + y: p2.1, + }, + Coordinate { + x: p3.0, + y: p3.1, + }, + ) + } +} + +impl TryMapCoords for Triangle { + type Output = Triangle; + + fn try_map_coords( + &self, + func: impl Fn(&(T, T)) -> Result<(NT, NT), Box>, + ) -> Result> { + let p1 = func(&self.0.x_y())?; + let p2 = func(&self.0.x_y())?; + let p3 = func(&self.0.x_y())?; + + Ok(Triangle( + Coordinate { + x: p1.0, + y: p1.1, + }, + Coordinate { + x: p2.0, + y: p2.1, + }, + Coordinate { + x: p3.0, + y: p3.1, + }, + )) + } +} + +impl MapCoordsInplace for Triangle { + fn map_coords_inplace(&mut self, func: impl Fn(&(T, T)) -> (T, T)) { + let p1 = func(&self.0.x_y()); + let p2 = func(&self.0.x_y()); + let p3 = func(&self.0.x_y()); + + let mut new_triangle = Triangle( + Coordinate { + x: p1.0, + y: p1.1, + }, + Coordinate { + x: p2.0, + y: p2.1, + }, + Coordinate { + x: p3.0, + y: p3.1, + }, + ); + + ::std::mem::swap(self, &mut new_triangle); + } +} + #[cfg(test)] mod test { use super::*; diff --git a/geo/src/lib.rs b/geo/src/lib.rs index 6a940f750..de065eab5 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -55,7 +55,7 @@ pub use crate::types::*; pub use geo_types::{ line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, Line, - LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, + LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, GeometryRef }; /// This module includes all the functions of geometric calculations From ad5dee5106739b8c2058698f4efbddabc5735121 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 2 Mar 2020 21:35:23 -0800 Subject: [PATCH 02/10] _ --- geo-types/src/geometry.rs | 84 ++++++++++++++++++++++++++++++++++++++- geo-types/src/lib.rs | 2 +- geo/src/algorithm/area.rs | 51 ++++++++++++++---------- geo/src/lib.rs | 2 +- 4 files changed, 114 insertions(+), 25 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index 22518a581..b79db020f 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -6,6 +6,7 @@ use num_traits::Float; use std::convert::TryFrom; use std::error::Error; use std::fmt; +use std::borrow::{Borrow, Cow}; /// An enum representing any possible geometry type. /// @@ -86,9 +87,90 @@ impl From> for Geometry { } } +pub enum GeometryIsh<'a, T: CoordinateType> { + Owned(Geometry), + Borrowed(GeometryRef<'a, T>), +} + +impl<'a, T: CoordinateType> Into> for &'a Point { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Point(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a LineString { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::LineString(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a Line { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Line(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a Polygon { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Polygon(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a MultiPoint { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::MultiPoint(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a MultiLineString { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::MultiLineString(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a MultiPolygon { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::MultiPolygon(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a GeometryCollection { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::GeometryCollection(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a Rect { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Rect(self)) + } +} + +impl<'a, T: CoordinateType> Into> for &'a Triangle { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Triangle(self)) + } +} + +// impl<'a, T: CoordinateType> Borrow> for Geometry { +// fn borrow(&self) -> &GeometryRef<'a, T> { +// unimplemented!() +// } +// } + +// impl<'a, T: CoordinateType> ToOwned for GeometryRef<'a, T> { +// type Owned = Geometry; + +// fn to_owned(&self) -> Geometry { +// match self { + +// } +// } +// } + // TODO impl deref? or borrow? or as_ref? -#[derive(PartialEq, Clone, Debug, Hash)] +#[derive(PartialEq, Debug, Hash)] pub enum GeometryRef<'a, T> where T: CoordinateType, diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index cc83e0577..ea61740a2 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -50,7 +50,7 @@ mod multi_polygon; pub use crate::multi_polygon::MultiPolygon; mod geometry; -pub use crate::geometry::{Geometry, GeometryRef}; +pub use crate::geometry::{Geometry, GeometryRef, GeometryIsh}; mod geometry_collection; pub use crate::geometry_collection::GeometryCollection; diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 218d2fced..521ce6a04 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,4 +1,4 @@ -use crate::{Geometry, CoordinateType, Line, LineString, MultiPolygon, Polygon, Rect, Triangle, GeometryRef, Point}; +use crate::{Geometry, CoordinateType, Line, LineString, MultiPolygon, Polygon, Rect, Triangle, GeometryRef, Point, GeometryIsh}; use num_traits::Float; use std::borrow::Cow; @@ -28,11 +28,11 @@ use crate::algorithm::winding_order::twice_signed_ring_area; /// /// assert_eq!(polygon.area(), -30.); /// ``` -pub trait Area +pub trait Area<'a, T> where T: CoordinateType, { - fn area(&self) -> T; + fn area(&'a self) -> T; } // Calculation of simple (no interior holes) Polygon area @@ -145,25 +145,26 @@ where // } // } -impl Area for I +impl<'a, I: 'a, T: 'a> Area<'a, T> for I where - for<'a> &'a I: Into>>, + &'a I: Into>, T: CoordinateType, { - fn area(&self) -> T { - let geometry_ref: Cow> = self.into(); - match *geometry_ref { - Geometry::Point(g) => unimplemented!(), - Geometry::Line(g) => unimplemented!(), - Geometry::LineString(g) => unimplemented!(), - Geometry::Polygon(g) => unimplemented!(), - Geometry::MultiPoint(g) => unimplemented!(), - Geometry::MultiLineString(g) => unimplemented!(), - Geometry::MultiPolygon(g) => unimplemented!(), - Geometry::GeometryCollection(g) => unimplemented!(), - Geometry::Rect(g) => unimplemented!(), - Geometry::Triangle(g) => unimplemented!(), - } + fn area(&'a self) -> T { + let geometry_ref: GeometryIsh<'a, T> = self.into(); + unimplemented!() + // match geometry_ref { + // Geometry::Point(g) => unimplemented!(), + // Geometry::Line(g) => unimplemented!(), + // Geometry::LineString(g) => unimplemented!(), + // Geometry::Polygon(g) => unimplemented!(), + // Geometry::MultiPoint(g) => unimplemented!(), + // Geometry::MultiLineString(g) => unimplemented!(), + // Geometry::MultiPolygon(g) => unimplemented!(), + // Geometry::GeometryCollection(g) => unimplemented!(), + // Geometry::Rect(g) => unimplemented!(), + // Geometry::Triangle(g) => unimplemented!(), + // } } } @@ -171,9 +172,15 @@ where struct NewPoint(Point); -impl<'a, T: Float> Into>> for &'_ NewPoint { - fn into(self) -> Cow<'a, Geometry> { - Cow::Owned(Geometry::Point(self.0)) +impl<'a, T: Float> Into> for &'a NewPoint { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Borrowed(GeometryRef::Point(&self.0)) + } +} + +impl<'a, T: Float> Into> for NewPoint { + fn into(self) -> GeometryIsh<'a, T> { + GeometryIsh::Owned(Geometry::Point(self.0)) } } diff --git a/geo/src/lib.rs b/geo/src/lib.rs index de065eab5..6382ed2e5 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -55,7 +55,7 @@ pub use crate::types::*; pub use geo_types::{ line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, Line, - LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, GeometryRef + LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, GeometryRef, GeometryIsh }; /// This module includes all the functions of geometric calculations From 430d3e209965ed64ccf6038d0dab59cd5e574dbc Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 2 Mar 2020 22:10:33 -0800 Subject: [PATCH 03/10] _ --- geo-types/src/geometry.rs | 25 ++++- geo-types/src/lib.rs | 2 +- geo/src/algorithm/area.rs | 170 +++++++++++--------------------- geo/src/algorithm/map_coords.rs | 55 +++-------- geo/src/lib.rs | 5 +- 5 files changed, 96 insertions(+), 161 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index b79db020f..089c25db7 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -1,12 +1,12 @@ use crate::{ CoordinateType, GeometryCollection, Line, LineString, MultiLineString, MultiPoint, - MultiPolygon, Point, Polygon, Rect, Triangle + MultiPolygon, Point, Polygon, Rect, Triangle, }; use num_traits::Float; +use std::borrow::{Borrow, Cow}; use std::convert::TryFrom; use std::error::Error; use std::fmt; -use std::borrow::{Borrow, Cow}; /// An enum representing any possible geometry type. /// @@ -92,6 +92,27 @@ pub enum GeometryIsh<'a, T: CoordinateType> { Borrowed(GeometryRef<'a, T>), } +// TODO: prefer From instead of Into + +impl<'a, T: CoordinateType> Into> for &'a Geometry { + fn into(self) -> GeometryIsh<'a, T> { + match self { + Geometry::Point(g) => GeometryIsh::Borrowed(GeometryRef::Point(g)), + Geometry::Line(g) => GeometryIsh::Borrowed(GeometryRef::Line(g)), + Geometry::LineString(g) => GeometryIsh::Borrowed(GeometryRef::LineString(g)), + Geometry::Polygon(g) => GeometryIsh::Borrowed(GeometryRef::Polygon(g)), + Geometry::MultiPoint(g) => GeometryIsh::Borrowed(GeometryRef::MultiPoint(g)), + Geometry::MultiLineString(g) => GeometryIsh::Borrowed(GeometryRef::MultiLineString(g)), + Geometry::MultiPolygon(g) => GeometryIsh::Borrowed(GeometryRef::MultiPolygon(g)), + Geometry::GeometryCollection(g) => { + GeometryIsh::Borrowed(GeometryRef::GeometryCollection(g)) + } + Geometry::Rect(g) => GeometryIsh::Borrowed(GeometryRef::Rect(g)), + Geometry::Triangle(g) => GeometryIsh::Borrowed(GeometryRef::Triangle(g)), + } + } +} + impl<'a, T: CoordinateType> Into> for &'a Point { fn into(self) -> GeometryIsh<'a, T> { GeometryIsh::Borrowed(GeometryRef::Point(self)) diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index ea61740a2..4b599a3ac 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -50,7 +50,7 @@ mod multi_polygon; pub use crate::multi_polygon::MultiPolygon; mod geometry; -pub use crate::geometry::{Geometry, GeometryRef, GeometryIsh}; +pub use crate::geometry::{Geometry, GeometryIsh, GeometryRef}; mod geometry_collection; pub use crate::geometry_collection::GeometryCollection; diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 521ce6a04..331d861be 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,6 +1,8 @@ -use crate::{Geometry, CoordinateType, Line, LineString, MultiPolygon, Polygon, Rect, Triangle, GeometryRef, Point, GeometryIsh}; +use crate::{ + CoordinateType, Geometry, GeometryCollection, GeometryIsh, GeometryRef, LineString, + MultiPolygon, Point, Polygon, Rect, Triangle, +}; use num_traits::Float; -use std::borrow::Cow; use crate::algorithm::winding_order::twice_signed_ring_area; @@ -38,112 +40,44 @@ where // Calculation of simple (no interior holes) Polygon area pub(crate) fn get_linestring_area(linestring: &LineString) -> T where - T: Float, + T: CoordinateType, { twice_signed_ring_area(linestring) / (T::one() + T::one()) } -// impl Area for Line -// where -// T: CoordinateType, -// { -// fn area(&self) -> T { -// T::zero() -// } -// } - -// impl Area for Polygon -// where -// T: Float, -// { -// fn area(&self) -> T { -// self.interiors() -// .iter() -// .fold(get_linestring_area(self.exterior()), |total, next| { -// total - get_linestring_area(next) -// }) -// } -// } - -// impl Area for MultiPolygon -// where -// T: Float, -// { -// fn area(&self) -> T { -// self.0 -// .iter() -// .fold(T::zero(), |total, next| total + next.area()) -// } -// } - -// impl Area for Rect -// where -// T: CoordinateType, -// { -// fn area(&self) -> T { -// self.width() * self.height() -// } -// } +fn area_polygon(polygon: &Polygon) -> T { + polygon + .interiors() + .iter() + .fold(get_linestring_area(polygon.exterior()), |total, next| { + total - get_linestring_area(next) + }) +} -// impl Area for Triangle -// where -// T: Float, -// { -// fn area(&self) -> T { -// self.to_lines() -// .iter() -// .fold(T::zero(), |total, line| total + line.determinant()) -// / (T::one() + T::one()) -// } -// } +fn area_multi_polygon(multi_polygon: &MultiPolygon) -> T { + multi_polygon + .0 + .iter() + .fold(T::zero(), |total, next| total + next.area()) +} -/////////////////////////////////////////////// +fn area_geometry_collection(geometry_collection: &GeometryCollection) -> T { + geometry_collection + .iter() + .fold(T::zero(), |total, geometry| total + geometry.area()) +} -// impl Area for &I -// where -// I: Into>, -// T: CoordinateType, -// { -// fn area(&self) -> T { -// let geometry: Geometry = self.into(); -// match geometry { -// Geometry::Point(g) => unimplemented!(), -// Geometry::Line(g) => unimplemented!(), -// Geometry::LineString(g) => unimplemented!(), -// Geometry::Polygon(g) => unimplemented!(), -// Geometry::MultiPoint(g) => unimplemented!(), -// Geometry::MultiLineString(g) => unimplemented!(), -// Geometry::MultiPolygon(g) => unimplemented!(), -// Geometry::GeometryCollection(g) => unimplemented!(), -// Geometry::Rect(g) => unimplemented!(), -// Geometry::Triangle(g) => unimplemented!(), -// } -// } -// } +fn area_rect(rect: &Rect) -> T { + rect.width() * rect.height() +} -// impl Area for I -// where -// I: ToOwned, -// J: Into> + std::borrow::Borrow, -// T: CoordinateType, -// { -// fn area(&self) -> T { -// let owned: J = self.to_owned().to_owned(); -// let geometry: Geometry = owned.into(); -// match geometry { -// Geometry::Point(g) => unimplemented!(), -// Geometry::Line(g) => unimplemented!(), -// Geometry::LineString(g) => unimplemented!(), -// Geometry::Polygon(g) => unimplemented!(), -// Geometry::MultiPoint(g) => unimplemented!(), -// Geometry::MultiLineString(g) => unimplemented!(), -// Geometry::MultiPolygon(g) => unimplemented!(), -// Geometry::GeometryCollection(g) => unimplemented!(), -// Geometry::Rect(g) => unimplemented!(), -// Geometry::Triangle(g) => unimplemented!(), -// } -// } -// } +fn area_triangle(triangle: &Triangle) -> T { + triangle + .to_lines() + .iter() + .fold(T::zero(), |total, line| total + line.determinant()) + / (T::one() + T::one()) +} impl<'a, I: 'a, T: 'a> Area<'a, T> for I where @@ -152,19 +86,28 @@ where { fn area(&'a self) -> T { let geometry_ref: GeometryIsh<'a, T> = self.into(); - unimplemented!() - // match geometry_ref { - // Geometry::Point(g) => unimplemented!(), - // Geometry::Line(g) => unimplemented!(), - // Geometry::LineString(g) => unimplemented!(), - // Geometry::Polygon(g) => unimplemented!(), - // Geometry::MultiPoint(g) => unimplemented!(), - // Geometry::MultiLineString(g) => unimplemented!(), - // Geometry::MultiPolygon(g) => unimplemented!(), - // Geometry::GeometryCollection(g) => unimplemented!(), - // Geometry::Rect(g) => unimplemented!(), - // Geometry::Triangle(g) => unimplemented!(), - // } + match geometry_ref { + GeometryIsh::Borrowed(GeometryRef::Point(_)) + | GeometryIsh::Owned(Geometry::Point(_)) + | GeometryIsh::Borrowed(GeometryRef::Line(_)) + | GeometryIsh::Owned(Geometry::Line(_)) + | GeometryIsh::Borrowed(GeometryRef::LineString(_)) + | GeometryIsh::Owned(Geometry::LineString(_)) + | GeometryIsh::Borrowed(GeometryRef::MultiPoint(_)) + | GeometryIsh::Owned(Geometry::MultiPoint(_)) + | GeometryIsh::Borrowed(GeometryRef::MultiLineString(_)) + | GeometryIsh::Owned(Geometry::MultiLineString(_)) => T::zero(), + GeometryIsh::Borrowed(GeometryRef::Polygon(g)) => area_polygon(g), + GeometryIsh::Owned(Geometry::Polygon(g)) => area_polygon(&g), + GeometryIsh::Borrowed(GeometryRef::MultiPolygon(g)) => area_multi_polygon(g), + GeometryIsh::Owned(Geometry::MultiPolygon(g)) => area_multi_polygon(&g), + GeometryIsh::Borrowed(GeometryRef::GeometryCollection(g)) => area_geometry_collection(g), + GeometryIsh::Owned(Geometry::GeometryCollection(g)) => area_geometry_collection(&g), + GeometryIsh::Borrowed(GeometryRef::Rect(g)) => area_rect(g), + GeometryIsh::Owned(Geometry::Rect(g)) => area_rect(&g), + GeometryIsh::Borrowed(GeometryRef::Triangle(g)) => area_triangle(g), + GeometryIsh::Owned(Geometry::Triangle(g)) => area_triangle(&g), + } } } @@ -189,6 +132,7 @@ impl<'a, T: Float> Into> for NewPoint { fn foo() { let n = NewPoint(geo_types::point!(x: 1.0, y: 1.0)); let a = n.area(); + let b = n.area(); } /////////////////////////////////////////////// diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index 8462d7b22..3dd408e67 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -1,6 +1,6 @@ use crate::{ Coordinate, CoordinateType, Geometry, GeometryCollection, Line, LineString, MultiLineString, - MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle + MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, }; use std::error::Error; @@ -406,12 +406,8 @@ impl TryMapCoords for Geometry Geometry::GeometryCollection(ref x) => { Ok(Geometry::GeometryCollection(x.try_map_coords(func)?)) } - Geometry::Rect(ref x) => { - Ok(Geometry::Rect(x.try_map_coords(func)?)) - } - Geometry::Triangle(ref x) => { - Ok(Geometry::Triangle(x.try_map_coords(func)?)) - } + Geometry::Rect(ref x) => Ok(Geometry::Rect(x.try_map_coords(func)?)), + Geometry::Triangle(ref x) => Ok(Geometry::Triangle(x.try_map_coords(func)?)), } } } @@ -528,18 +524,9 @@ impl MapCoords for Triangle { let p3 = func(&self.0.x_y()); Triangle( - Coordinate { - x: p1.0, - y: p1.1, - }, - Coordinate { - x: p2.0, - y: p2.1, - }, - Coordinate { - x: p3.0, - y: p3.1, - }, + Coordinate { x: p1.0, y: p1.1 }, + Coordinate { x: p2.0, y: p2.1 }, + Coordinate { x: p3.0, y: p3.1 }, ) } } @@ -556,18 +543,9 @@ impl TryMapCoords for Triangle let p3 = func(&self.0.x_y())?; Ok(Triangle( - Coordinate { - x: p1.0, - y: p1.1, - }, - Coordinate { - x: p2.0, - y: p2.1, - }, - Coordinate { - x: p3.0, - y: p3.1, - }, + Coordinate { x: p1.0, y: p1.1 }, + Coordinate { x: p2.0, y: p2.1 }, + Coordinate { x: p3.0, y: p3.1 }, )) } } @@ -579,18 +557,9 @@ impl MapCoordsInplace for Triangle { let p3 = func(&self.0.x_y()); let mut new_triangle = Triangle( - Coordinate { - x: p1.0, - y: p1.1, - }, - Coordinate { - x: p2.0, - y: p2.1, - }, - Coordinate { - x: p3.0, - y: p3.1, - }, + Coordinate { x: p1.0, y: p1.1 }, + Coordinate { x: p2.0, y: p2.1 }, + Coordinate { x: p3.0, y: p3.1 }, ); ::std::mem::swap(self, &mut new_triangle); diff --git a/geo/src/lib.rs b/geo/src/lib.rs index 6382ed2e5..6224a1e3e 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -54,8 +54,9 @@ pub use crate::traits::ToGeo; pub use crate::types::*; pub use geo_types::{ - line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, Line, - LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, GeometryRef, GeometryIsh + line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, + GeometryIsh, GeometryRef, Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, + Polygon, Rect, Triangle, }; /// This module includes all the functions of geometric calculations From 7c53b23f82f4334467d0493539373dee9de4832a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 2 Mar 2020 22:51:42 -0800 Subject: [PATCH 04/10] _ --- geo-types/src/geometry.rs | 199 +++++++++++--------------------------- geo-types/src/lib.rs | 2 +- geo/src/algorithm/area.rs | 58 ++++++----- geo/src/lib.rs | 4 +- 4 files changed, 88 insertions(+), 175 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index 089c25db7..11aac6046 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -3,7 +3,7 @@ use crate::{ MultiPolygon, Point, Polygon, Rect, Triangle, }; use num_traits::Float; -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; use std::convert::TryFrom; use std::error::Error; use std::fmt; @@ -87,184 +87,101 @@ impl From> for Geometry { } } -pub enum GeometryIsh<'a, T: CoordinateType> { - Owned(Geometry), - Borrowed(GeometryRef<'a, T>), +#[derive(PartialEq, Debug, Hash)] +pub enum GeometryCow<'a, T> +where + T: CoordinateType, +{ + Point(Cow<'a, Point>), + Line(Cow<'a, Line>), + LineString(Cow<'a, LineString>), + Polygon(Cow<'a, Polygon>), + MultiPoint(Cow<'a, MultiPoint>), + MultiLineString(Cow<'a, MultiLineString>), + MultiPolygon(Cow<'a, MultiPolygon>), + GeometryCollection(Cow<'a, GeometryCollection>), + Rect(Cow<'a, Rect>), + Triangle(Cow<'a, Triangle>), } // TODO: prefer From instead of Into -impl<'a, T: CoordinateType> Into> for &'a Geometry { - fn into(self) -> GeometryIsh<'a, T> { +impl<'a, T: CoordinateType> Into> for &'a Geometry { + fn into(self) -> GeometryCow<'a, T> { match self { - Geometry::Point(g) => GeometryIsh::Borrowed(GeometryRef::Point(g)), - Geometry::Line(g) => GeometryIsh::Borrowed(GeometryRef::Line(g)), - Geometry::LineString(g) => GeometryIsh::Borrowed(GeometryRef::LineString(g)), - Geometry::Polygon(g) => GeometryIsh::Borrowed(GeometryRef::Polygon(g)), - Geometry::MultiPoint(g) => GeometryIsh::Borrowed(GeometryRef::MultiPoint(g)), - Geometry::MultiLineString(g) => GeometryIsh::Borrowed(GeometryRef::MultiLineString(g)), - Geometry::MultiPolygon(g) => GeometryIsh::Borrowed(GeometryRef::MultiPolygon(g)), + Geometry::Point(g) => GeometryCow::Point(Cow::Borrowed(g)), + Geometry::Line(g) => GeometryCow::Line(Cow::Borrowed(g)), + Geometry::LineString(g) => GeometryCow::LineString(Cow::Borrowed(g)), + Geometry::Polygon(g) => GeometryCow::Polygon(Cow::Borrowed(g)), + Geometry::MultiPoint(g) => GeometryCow::MultiPoint(Cow::Borrowed(g)), + Geometry::MultiLineString(g) => GeometryCow::MultiLineString(Cow::Borrowed(g)), + Geometry::MultiPolygon(g) => GeometryCow::MultiPolygon(Cow::Borrowed(g)), Geometry::GeometryCollection(g) => { - GeometryIsh::Borrowed(GeometryRef::GeometryCollection(g)) + GeometryCow::GeometryCollection(Cow::Borrowed(g)) } - Geometry::Rect(g) => GeometryIsh::Borrowed(GeometryRef::Rect(g)), - Geometry::Triangle(g) => GeometryIsh::Borrowed(GeometryRef::Triangle(g)), + Geometry::Rect(g) => GeometryCow::Rect(Cow::Borrowed(g)), + Geometry::Triangle(g) => GeometryCow::Triangle(Cow::Borrowed(g)), } } } -impl<'a, T: CoordinateType> Into> for &'a Point { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Point(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a LineString { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::LineString(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a Line { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Line(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a Polygon { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Polygon(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a MultiPoint { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::MultiPoint(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a MultiLineString { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::MultiLineString(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a MultiPolygon { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::MultiPolygon(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a GeometryCollection { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::GeometryCollection(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a Rect { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Rect(self)) - } -} - -impl<'a, T: CoordinateType> Into> for &'a Triangle { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Triangle(self)) - } -} - -// impl<'a, T: CoordinateType> Borrow> for Geometry { -// fn borrow(&self) -> &GeometryRef<'a, T> { -// unimplemented!() -// } -// } - -// impl<'a, T: CoordinateType> ToOwned for GeometryRef<'a, T> { -// type Owned = Geometry; - -// fn to_owned(&self) -> Geometry { -// match self { - -// } -// } -// } - -// TODO impl deref? or borrow? or as_ref? - -#[derive(PartialEq, Debug, Hash)] -pub enum GeometryRef<'a, T> -where - T: CoordinateType, -{ - Point(&'a Point), - Line(&'a Line), - LineString(&'a LineString), - Polygon(&'a Polygon), - MultiPoint(&'a MultiPoint), - MultiLineString(&'a MultiLineString), - MultiPolygon(&'a MultiPolygon), - GeometryCollection(&'a GeometryCollection), - Rect(&'a Rect), - Triangle(&'a Triangle), -} - -impl<'a, T: 'a + CoordinateType> From<&'a Point> for GeometryRef<'a, T> { - fn from(x: &'a Point) -> GeometryRef<'a, T> { - GeometryRef::Point(x) +impl<'a, T: CoordinateType> Into> for &'a Point { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Point(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a Line> for GeometryRef<'a, T> { - fn from(x: &'a Line) -> GeometryRef<'a, T> { - GeometryRef::Line(x) +impl<'a, T: CoordinateType> Into> for &'a LineString { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::LineString(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a LineString> for GeometryRef<'a, T> { - fn from(x: &'a LineString) -> GeometryRef<'a, T> { - GeometryRef::LineString(x) +impl<'a, T: CoordinateType> Into> for &'a Line { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Line(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a Polygon> for GeometryRef<'a, T> { - fn from(x: &'a Polygon) -> GeometryRef<'a, T> { - GeometryRef::Polygon(x) +impl<'a, T: CoordinateType> Into> for &'a Polygon { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Polygon(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a MultiPoint> for GeometryRef<'a, T> { - fn from(x: &'a MultiPoint) -> GeometryRef<'a, T> { - GeometryRef::MultiPoint(x) +impl<'a, T: CoordinateType> Into> for &'a MultiPoint { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::MultiPoint(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a MultiLineString> for GeometryRef<'a, T> { - fn from(x: &'a MultiLineString) -> GeometryRef<'a, T> { - GeometryRef::MultiLineString(x) +impl<'a, T: CoordinateType> Into> for &'a MultiLineString { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::MultiLineString(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a MultiPolygon> for GeometryRef<'a, T> { - fn from(x: &'a MultiPolygon) -> GeometryRef<'a, T> { - GeometryRef::MultiPolygon(x) +impl<'a, T: CoordinateType> Into> for &'a MultiPolygon { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::MultiPolygon(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a GeometryCollection> for GeometryRef<'a, T> { - fn from(x: &'a GeometryCollection) -> GeometryRef<'a, T> { - GeometryRef::GeometryCollection(x) +impl<'a, T: CoordinateType> Into> for &'a GeometryCollection { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::GeometryCollection(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a Rect> for GeometryRef<'a, T> { - fn from(x: &'a Rect) -> GeometryRef<'a, T> { - GeometryRef::Rect(x) +impl<'a, T: CoordinateType> Into> for &'a Rect { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Rect(Cow::Borrowed(self)) } } -impl<'a, T: 'a + CoordinateType> From<&'a Triangle> for GeometryRef<'a, T> { - fn from(x: &'a Triangle) -> GeometryRef<'a, T> { - GeometryRef::Triangle(x) +impl<'a, T: CoordinateType> Into> for &'a Triangle { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Triangle(Cow::Borrowed(self)) } } diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index 4b599a3ac..aedbbef55 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -50,7 +50,7 @@ mod multi_polygon; pub use crate::multi_polygon::MultiPolygon; mod geometry; -pub use crate::geometry::{Geometry, GeometryIsh, GeometryRef}; +pub use crate::geometry::{Geometry, GeometryCow}; mod geometry_collection; pub use crate::geometry_collection::GeometryCollection; diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 331d861be..a97359595 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,6 +1,6 @@ use crate::{ - CoordinateType, Geometry, GeometryCollection, GeometryIsh, GeometryRef, LineString, - MultiPolygon, Point, Polygon, Rect, Triangle, + CoordinateType, GeometryCollection, LineString, + MultiPolygon, Point, Polygon, Rect, Triangle, GeometryCow }; use num_traits::Float; @@ -81,32 +81,22 @@ fn area_triangle(triangle: &Triangle) -> T { impl<'a, I: 'a, T: 'a> Area<'a, T> for I where - &'a I: Into>, + &'a I: Into>, T: CoordinateType, { fn area(&'a self) -> T { - let geometry_ref: GeometryIsh<'a, T> = self.into(); - match geometry_ref { - GeometryIsh::Borrowed(GeometryRef::Point(_)) - | GeometryIsh::Owned(Geometry::Point(_)) - | GeometryIsh::Borrowed(GeometryRef::Line(_)) - | GeometryIsh::Owned(Geometry::Line(_)) - | GeometryIsh::Borrowed(GeometryRef::LineString(_)) - | GeometryIsh::Owned(Geometry::LineString(_)) - | GeometryIsh::Borrowed(GeometryRef::MultiPoint(_)) - | GeometryIsh::Owned(Geometry::MultiPoint(_)) - | GeometryIsh::Borrowed(GeometryRef::MultiLineString(_)) - | GeometryIsh::Owned(Geometry::MultiLineString(_)) => T::zero(), - GeometryIsh::Borrowed(GeometryRef::Polygon(g)) => area_polygon(g), - GeometryIsh::Owned(Geometry::Polygon(g)) => area_polygon(&g), - GeometryIsh::Borrowed(GeometryRef::MultiPolygon(g)) => area_multi_polygon(g), - GeometryIsh::Owned(Geometry::MultiPolygon(g)) => area_multi_polygon(&g), - GeometryIsh::Borrowed(GeometryRef::GeometryCollection(g)) => area_geometry_collection(g), - GeometryIsh::Owned(Geometry::GeometryCollection(g)) => area_geometry_collection(&g), - GeometryIsh::Borrowed(GeometryRef::Rect(g)) => area_rect(g), - GeometryIsh::Owned(Geometry::Rect(g)) => area_rect(&g), - GeometryIsh::Borrowed(GeometryRef::Triangle(g)) => area_triangle(g), - GeometryIsh::Owned(Geometry::Triangle(g)) => area_triangle(&g), + let geometry_cow: GeometryCow<'a, T> = self.into(); + match geometry_cow { + GeometryCow::Point(_) => T::zero(), + GeometryCow::Line(_) => T::zero(), + GeometryCow::LineString(_) => T::zero(), + GeometryCow::Polygon(g) => area_polygon(&*g), + GeometryCow::MultiPoint(_) => T::zero(), + GeometryCow::MultiLineString(_) => T::zero(), + GeometryCow::MultiPolygon(g) => area_multi_polygon(&*g), + GeometryCow::GeometryCollection(g) => area_geometry_collection(&*g), + GeometryCow::Rect(g) => area_rect(&*g), + GeometryCow::Triangle(g) => area_triangle(&*g), } } } @@ -115,15 +105,17 @@ where struct NewPoint(Point); -impl<'a, T: Float> Into> for &'a NewPoint { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Borrowed(GeometryRef::Point(&self.0)) +impl<'a, T: Float> Into> for &'a NewPoint { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Point(std::borrow::Cow::Borrowed(&self.0)) } } -impl<'a, T: Float> Into> for NewPoint { - fn into(self) -> GeometryIsh<'a, T> { - GeometryIsh::Owned(Geometry::Point(self.0)) +struct NewPoint2(T, T); + +impl<'a, T: Float> Into> for &'a NewPoint2 { + fn into(self) -> GeometryCow<'a, T> { + GeometryCow::Point(std::borrow::Cow::Owned(Point::new(self.0, self.1))) } } @@ -133,6 +125,10 @@ fn foo() { let n = NewPoint(geo_types::point!(x: 1.0, y: 1.0)); let a = n.area(); let b = n.area(); + + let n = NewPoint2(1.0, 1.0); + let a = n.area(); + let b = n.area(); } /////////////////////////////////////////////// diff --git a/geo/src/lib.rs b/geo/src/lib.rs index 6224a1e3e..e2d55c518 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -55,8 +55,8 @@ pub use crate::types::*; pub use geo_types::{ line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, - GeometryIsh, GeometryRef, Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, - Polygon, Rect, Triangle, + Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, + Polygon, Rect, Triangle, GeometryCow }; /// This module includes all the functions of geometric calculations From 8bf248e37d85e3a2f544ddc20e9cc1ccd0f6c2b5 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 3 Mar 2020 06:43:09 -0800 Subject: [PATCH 05/10] _ --- geo-types/src/geometry.rs | 72 ++++++++++++++++----------------- geo-types/src/rect.rs | 12 +++++- geo-types/src/triangle.rs | 6 ++- geo/src/algorithm/area.rs | 37 +---------------- geo/src/algorithm/to_postgis.rs | 6 +++ geo/src/lib.rs | 4 +- 6 files changed, 60 insertions(+), 77 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index 11aac6046..b964cd45b 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -104,11 +104,9 @@ where Triangle(Cow<'a, Triangle>), } -// TODO: prefer From instead of Into - -impl<'a, T: CoordinateType> Into> for &'a Geometry { - fn into(self) -> GeometryCow<'a, T> { - match self { +impl<'a, T: CoordinateType> From<&'a Geometry> for GeometryCow<'a, T> { + fn from(geometry: &'a Geometry) -> Self { + match geometry { Geometry::Point(g) => GeometryCow::Point(Cow::Borrowed(g)), Geometry::Line(g) => GeometryCow::Line(Cow::Borrowed(g)), Geometry::LineString(g) => GeometryCow::LineString(Cow::Borrowed(g)), @@ -116,72 +114,70 @@ impl<'a, T: CoordinateType> Into> for &'a Geometry { Geometry::MultiPoint(g) => GeometryCow::MultiPoint(Cow::Borrowed(g)), Geometry::MultiLineString(g) => GeometryCow::MultiLineString(Cow::Borrowed(g)), Geometry::MultiPolygon(g) => GeometryCow::MultiPolygon(Cow::Borrowed(g)), - Geometry::GeometryCollection(g) => { - GeometryCow::GeometryCollection(Cow::Borrowed(g)) - } + Geometry::GeometryCollection(g) => GeometryCow::GeometryCollection(Cow::Borrowed(g)), Geometry::Rect(g) => GeometryCow::Rect(Cow::Borrowed(g)), Geometry::Triangle(g) => GeometryCow::Triangle(Cow::Borrowed(g)), } } } -impl<'a, T: CoordinateType> Into> for &'a Point { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Point(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a Point> for GeometryCow<'a, T> { + fn from(point: &'a Point) -> Self { + GeometryCow::Point(Cow::Borrowed(point)) } } -impl<'a, T: CoordinateType> Into> for &'a LineString { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::LineString(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a LineString> for GeometryCow<'a, T> { + fn from(line_string: &'a LineString) -> Self { + GeometryCow::LineString(Cow::Borrowed(line_string)) } } -impl<'a, T: CoordinateType> Into> for &'a Line { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Line(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a Line> for GeometryCow<'a, T> { + fn from(line: &'a Line) -> Self { + GeometryCow::Line(Cow::Borrowed(line)) } } -impl<'a, T: CoordinateType> Into> for &'a Polygon { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Polygon(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a Polygon> for GeometryCow<'a, T> { + fn from(polygon: &'a Polygon) -> Self { + GeometryCow::Polygon(Cow::Borrowed(polygon)) } } -impl<'a, T: CoordinateType> Into> for &'a MultiPoint { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::MultiPoint(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a MultiPoint> for GeometryCow<'a, T> { + fn from(multi_point: &'a MultiPoint) -> GeometryCow<'a, T> { + GeometryCow::MultiPoint(Cow::Borrowed(multi_point)) } } -impl<'a, T: CoordinateType> Into> for &'a MultiLineString { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::MultiLineString(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a MultiLineString> for GeometryCow<'a, T> { + fn from(multi_line_string: &'a MultiLineString) -> Self { + GeometryCow::MultiLineString(Cow::Borrowed(multi_line_string)) } } -impl<'a, T: CoordinateType> Into> for &'a MultiPolygon { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::MultiPolygon(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a MultiPolygon> for GeometryCow<'a, T> { + fn from(multi_polygon: &'a MultiPolygon) -> Self { + GeometryCow::MultiPolygon(Cow::Borrowed(multi_polygon)) } } -impl<'a, T: CoordinateType> Into> for &'a GeometryCollection { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::GeometryCollection(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a GeometryCollection> for GeometryCow<'a, T> { + fn from(geometry_collection: &'a GeometryCollection) -> Self { + GeometryCow::GeometryCollection(Cow::Borrowed(geometry_collection)) } } -impl<'a, T: CoordinateType> Into> for &'a Rect { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Rect(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a Rect> for GeometryCow<'a, T> { + fn from(rect: &'a Rect) -> Self { + GeometryCow::Rect(Cow::Borrowed(rect)) } } -impl<'a, T: CoordinateType> Into> for &'a Triangle { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Triangle(Cow::Borrowed(self)) +impl<'a, T: CoordinateType> From<&'a Triangle> for GeometryCow<'a, T> { + fn from(triangle: &'a Triangle) -> Self { + GeometryCow::Triangle(Cow::Borrowed(triangle)) } } diff --git a/geo-types/src/rect.rs b/geo-types/src/rect.rs index c5d67cb71..75bb59658 100644 --- a/geo-types/src/rect.rs +++ b/geo-types/src/rect.rs @@ -1,4 +1,4 @@ -use crate::{Coordinate, CoordinateType}; +use crate::{polygon, Coordinate, CoordinateType, Polygon}; /// A bounded 2D quadrilateral whose area is defined by minimum and maximum `Coordinates`. #[derive(PartialEq, Clone, Copy, Debug, Hash)] @@ -73,6 +73,16 @@ impl Rect { self.max().y - self.min().y } + pub fn to_polygon(self) -> Polygon { + polygon![ + (x: self.min.x, y: self.min.y), + (x: self.min.x, y: self.max.y), + (x: self.max.x, y: self.max.y), + (x: self.max.x, y: self.min.y), + (x: self.min.x, y: self.min.y), + ] + } + fn assert_valid_bounds(min: Coordinate, max: Coordinate) { assert!( min.x <= max.x && min.y <= max.y, diff --git a/geo-types/src/triangle.rs b/geo-types/src/triangle.rs index c144b22aa..8078cf94c 100644 --- a/geo-types/src/triangle.rs +++ b/geo-types/src/triangle.rs @@ -1,4 +1,4 @@ -use crate::{Coordinate, CoordinateType, Line}; +use crate::{polygon, Coordinate, CoordinateType, Line, Polygon}; /// A bounded 2D area whose three vertices are defined by `Coordinate`s. #[derive(Copy, Clone, Debug, Hash, PartialEq)] @@ -17,6 +17,10 @@ impl Triangle { Line::new(self.2, self.0), ] } + + pub fn to_polygon(self) -> Polygon { + polygon![self.0, self.1, self.2, self.0] + } } impl> + Copy, T: CoordinateType> From<[IC; 3]> for Triangle { diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index a97359595..c4249456a 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,8 +1,7 @@ use crate::{ - CoordinateType, GeometryCollection, LineString, - MultiPolygon, Point, Polygon, Rect, Triangle, GeometryCow + CoordinateType, GeometryCollection, GeometryCow, LineString, MultiPolygon, Polygon, Rect, + Triangle, }; -use num_traits::Float; use crate::algorithm::winding_order::twice_signed_ring_area; @@ -101,38 +100,6 @@ where } } -/////////////////////////////////////////////// - -struct NewPoint(Point); - -impl<'a, T: Float> Into> for &'a NewPoint { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Point(std::borrow::Cow::Borrowed(&self.0)) - } -} - -struct NewPoint2(T, T); - -impl<'a, T: Float> Into> for &'a NewPoint2 { - fn into(self) -> GeometryCow<'a, T> { - GeometryCow::Point(std::borrow::Cow::Owned(Point::new(self.0, self.1))) - } -} - -// /////////////////////////////////////////////// - -fn foo() { - let n = NewPoint(geo_types::point!(x: 1.0, y: 1.0)); - let a = n.area(); - let b = n.area(); - - let n = NewPoint2(1.0, 1.0); - let a = n.area(); - let b = n.area(); -} - -/////////////////////////////////////////////// - #[cfg(test)] mod test { use crate::algorithm::area::Area; diff --git a/geo/src/algorithm/to_postgis.rs b/geo/src/algorithm/to_postgis.rs index 9616f63a7..6e84f2e17 100644 --- a/geo/src/algorithm/to_postgis.rs +++ b/geo/src/algorithm/to_postgis.rs @@ -88,6 +88,12 @@ impl ToPostgis for Geometry { Geometry::GeometryCollection(ref p) => { ewkb::GeometryT::GeometryCollection(p.to_postgis_with_srid(srid)) } + Geometry::Rect(ref p) => { + ewkb::GeometryT::Polygon(p.to_polygon().to_postgis_with_srid(srid)) + } + Geometry::Triangle(ref p) => { + ewkb::GeometryT::Polygon(p.to_polygon().to_postgis_with_srid(srid)) + } } } } diff --git a/geo/src/lib.rs b/geo/src/lib.rs index e2d55c518..8dfe918ff 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -55,8 +55,8 @@ pub use crate::types::*; pub use geo_types::{ line_string, point, polygon, Coordinate, CoordinateType, Geometry, GeometryCollection, - Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, - Polygon, Rect, Triangle, GeometryCow + GeometryCow, Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, + Triangle, }; /// This module includes all the functions of geometric calculations From 5e7300d1525db4d71f37464c7d15e637c44ac0fe Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 28 Mar 2020 21:29:31 -0400 Subject: [PATCH 06/10] Update geo/src/algorithm/map_coords.rs Co-Authored-By: Michael Kirk --- geo/src/algorithm/map_coords.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index 3dd408e67..faac86bf7 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -520,8 +520,8 @@ impl MapCoords for Triangle { fn map_coords(&self, func: impl Fn(&(T, T)) -> (NT, NT) + Copy) -> Self::Output { let p1 = func(&self.0.x_y()); - let p2 = func(&self.0.x_y()); - let p3 = func(&self.0.x_y()); + let p2 = func(&self.1.x_y()); + let p3 = func(&self.2.x_y()); Triangle( Coordinate { x: p1.0, y: p1.1 }, From ba1009b77ff395c826acffcc749bb918313f7d51 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 28 Mar 2020 21:29:48 -0400 Subject: [PATCH 07/10] Update geo/src/algorithm/map_coords.rs Co-Authored-By: Michael Kirk --- geo/src/algorithm/map_coords.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index faac86bf7..b9f11cfed 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -539,8 +539,8 @@ impl TryMapCoords for Triangle func: impl Fn(&(T, T)) -> Result<(NT, NT), Box>, ) -> Result> { let p1 = func(&self.0.x_y())?; - let p2 = func(&self.0.x_y())?; - let p3 = func(&self.0.x_y())?; + let p2 = func(&self.1.x_y())?; + let p3 = func(&self.2.x_y())?; Ok(Triangle( Coordinate { x: p1.0, y: p1.1 }, From c097e1bc4b40ba5c7e0ebfe8946903a183647712 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 28 Mar 2020 21:35:41 -0400 Subject: [PATCH 08/10] Update geo/src/algorithm/map_coords.rs Co-Authored-By: Michael Kirk --- geo/src/algorithm/map_coords.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index b9f11cfed..414abaa14 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -553,8 +553,8 @@ impl TryMapCoords for Triangle impl MapCoordsInplace for Triangle { fn map_coords_inplace(&mut self, func: impl Fn(&(T, T)) -> (T, T)) { let p1 = func(&self.0.x_y()); - let p2 = func(&self.0.x_y()); - let p3 = func(&self.0.x_y()); + let p2 = func(&self.1.x_y()); + let p3 = func(&self.2.x_y()); let mut new_triangle = Triangle( Coordinate { x: p1.0, y: p1.1 }, From dacb9681d460ccca605560ef873b225d97fb458e Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 29 Mar 2020 10:37:13 -0400 Subject: [PATCH 09/10] fix compilation --- geo-types/src/geometry.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/geo-types/src/geometry.rs b/geo-types/src/geometry.rs index f04bf2fef..b964cd45b 100644 --- a/geo-types/src/geometry.rs +++ b/geo-types/src/geometry.rs @@ -181,18 +181,6 @@ impl<'a, T: CoordinateType> From<&'a Triangle> for GeometryCow<'a, T> { } } -impl From> for Geometry { - fn from(x: Rect) -> Geometry { - Geometry::Rect(x) - } -} - -impl From> for Geometry { - fn from(x: Triangle) -> Geometry { - Geometry::Triangle(x) - } -} - impl Geometry { /// If this Geometry is a Point, then return that, else None. /// From d3de248b038ea1798705aab27166acbeb1af1a99 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 29 Mar 2020 10:37:24 -0400 Subject: [PATCH 10/10] rustfmt --- geo/src/algorithm/map_coords.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index 87b4e1929..8b0c2305e 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -36,7 +36,7 @@ use crate::{ Coordinate, CoordinateType, Geometry, GeometryCollection, Line, LineString, MultiLineString, - MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle + MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle, }; use std::error::Error;