Skip to content

Commit

Permalink
Merge #431 #432
Browse files Browse the repository at this point in the history
431: Add conditional Eq impl for Coordinate, maybe other types? r=frewsxcv a=nick-parker

I haven't written tests or anything for this but I wanted to throw the PR in to get discussion started.

Many geometry algorithms eg this [optimal algorithm for computing mesh cross-sections and reconstructing the polygons](https://www.researchgate.net/publication/309619647_An_Optimal_Algorithm_for_3D_Triangle_Mesh_Slicing) use Hashtables or similar to keep track of coordinates. This impl lets me put geo Coordinate structs in the Hashtable instead of dealing with a separate struct just for this step.

I haven't put much thought into whether similar one-liner Eq impl's should be added for Linestring, Polygon, etc but I don't really see why not. The use cases are rarer but probably still exist.

432: Add Triangle and Rect to Geometry. r=frewsxcv a=frewsxcv

Fixes #390

Extracted from https://github.com/georust/geo/pull/421/files

Co-authored-by: Nick Parker <[email protected]>
Co-authored-by: Corey Farwell <[email protected]>
  • Loading branch information
3 people authored Mar 29, 2020
3 parents d85adab + 5887f91 + 3bee141 commit 2c7b434
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 3 deletions.
2 changes: 2 additions & 0 deletions geo-types/src/coordinate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ where
pub y: T,
}

impl<T: CoordinateType> std::cmp::Eq for Coordinate<T> where T: std::cmp::Eq {}

impl<T: CoordinateType> From<(T, T)> for Coordinate<T> {
fn from(coords: (T, T)) -> Self {
Coordinate {
Expand Down
16 changes: 15 additions & 1 deletion geo-types/src/geometry.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -36,6 +36,8 @@ where
MultiLineString(MultiLineString<T>),
MultiPolygon(MultiPolygon<T>),
GeometryCollection(GeometryCollection<T>),
Rect(Rect<T>),
Triangle(Triangle<T>),
}

impl<T: CoordinateType> From<Point<T>> for Geometry<T> {
Expand Down Expand Up @@ -74,6 +76,18 @@ impl<T: CoordinateType> From<MultiPolygon<T>> for Geometry<T> {
}
}

impl<T: CoordinateType> From<Rect<T>> for Geometry<T> {
fn from(x: Rect<T>) -> Geometry<T> {
Geometry::Rect(x)
}
}

impl<T: CoordinateType> From<Triangle<T>> for Geometry<T> {
fn from(x: Triangle<T>) -> Geometry<T> {
Geometry::Triangle(x)
}
}

impl<T: CoordinateType> Geometry<T> {
/// If this Geometry is a Point, then return that, else None.
///
Expand Down
2 changes: 1 addition & 1 deletion geo-types/src/triangle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{polygon, Coordinate, CoordinateType, Line, Polygon};

/// 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<T: CoordinateType>(pub Coordinate<T>, pub Coordinate<T>, pub Coordinate<T>);

Expand Down
59 changes: 58 additions & 1 deletion geo/src/algorithm/map_coords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
use crate::{
Coordinate, CoordinateType, Geometry, GeometryCollection, Line, LineString, MultiLineString,
MultiPoint, MultiPolygon, Point, Polygon, Rect,
MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle
};
use std::error::Error;

Expand Down Expand Up @@ -416,6 +416,8 @@ impl<T: CoordinateType, NT: CoordinateType> MapCoords<T, NT> for Geometry<T> {
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)),
}
}
}
Expand All @@ -440,6 +442,8 @@ impl<T: CoordinateType, NT: CoordinateType> TryMapCoords<T, NT> for Geometry<T>
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)?)),
}
}
}
Expand All @@ -455,6 +459,8 @@ impl<T: CoordinateType> MapCoordsInplace<T> for Geometry<T> {
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),
}
}
}
Expand Down Expand Up @@ -545,6 +551,57 @@ impl<T: CoordinateType> MapCoordsInplace<T> for Rect<T> {
}
}

impl<T: CoordinateType, NT: CoordinateType> MapCoords<T, NT> for Triangle<T> {
type Output = Triangle<NT>;

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.1.x_y());
let p3 = func(&self.2.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<T: CoordinateType, NT: CoordinateType> TryMapCoords<T, NT> for Triangle<T> {
type Output = Triangle<NT>;

fn try_map_coords(
&self,
func: impl Fn(&(T, T)) -> Result<(NT, NT), Box<dyn Error + Send + Sync>>,
) -> Result<Self::Output, Box<dyn Error + Send + Sync>> {
let p1 = 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 },
Coordinate { x: p2.0, y: p2.1 },
Coordinate { x: p3.0, y: p3.1 },
))
}
}

impl<T: CoordinateType> MapCoordsInplace<T> for Triangle<T> {
fn map_coords_inplace(&mut self, func: impl Fn(&(T, T)) -> (T, T)) {
let p1 = 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 },
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::*;
Expand Down
6 changes: 6 additions & 0 deletions geo/src/algorithm/to_postgis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ impl ToPostgis<ewkb::Geometry> for Geometry<f64> {
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))
}
}
}
}

0 comments on commit 2c7b434

Please sign in to comment.