-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1011: Initial geo-traits implementation r=frewsxcv a=kylebarron - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/main/CODE_OF_CONDUCT.md). - [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- As discussed on the discord, in #838, and originally in #67, this is an initial bare-bones implementation of geometry access traits for discussion. As `@frewsxcv` suggested, for now this is a separate crate in the workspace to let us iterate on some ideas. ### Future work #### Minimize cloning in the geo-types implementation I got lost in lifetime errors so to get things to compile I added cloning to the geo-types implementations. I.e. for `MultiPoint` each point is cloned when accessed. Co-authored-by: Kyle Barron <[email protected]>
- Loading branch information
Showing
12 changed files
with
598 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "geo-traits" | ||
version = "0.1.0" | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/georust/geo" | ||
documentation = "https://docs.rs/geo-traits/" | ||
readme = "../README.md" | ||
keywords = ["gis", "geo", "geography", "geospatial"] | ||
description = "Geospatial traits" | ||
rust-version = "1.65" | ||
edition = "2021" | ||
|
||
[features] | ||
|
||
[dependencies] | ||
geo-types = "0.7.9" | ||
|
||
[dev-dependencies] | ||
approx = ">= 0.4.0, < 0.6.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use geo_types::{Coord, CoordNum, Point}; | ||
|
||
pub trait CoordTrait: Send + Sync { | ||
type T: CoordNum + Send + Sync; | ||
|
||
/// x component of this coord | ||
fn x(&self) -> Self::T; | ||
|
||
/// y component of this coord | ||
fn y(&self) -> Self::T; | ||
|
||
/// Returns a tuple that contains the x/horizontal & y/vertical component of the coord. | ||
fn x_y(&self) -> (Self::T, Self::T) { | ||
(self.x(), self.y()) | ||
} | ||
} | ||
|
||
impl<T: CoordNum + Send + Sync> CoordTrait for Point<T> { | ||
type T = T; | ||
|
||
fn x(&self) -> T { | ||
self.0.x | ||
} | ||
|
||
fn y(&self) -> T { | ||
self.0.y | ||
} | ||
} | ||
|
||
impl<T: CoordNum + Send + Sync> CoordTrait for &Point<T> { | ||
type T = T; | ||
|
||
fn x(&self) -> T { | ||
self.0.x | ||
} | ||
|
||
fn y(&self) -> T { | ||
self.0.y | ||
} | ||
} | ||
|
||
impl<T: CoordNum + Send + Sync> CoordTrait for Coord<T> { | ||
type T = T; | ||
|
||
fn x(&self) -> T { | ||
self.x | ||
} | ||
|
||
fn y(&self) -> T { | ||
self.y | ||
} | ||
} | ||
|
||
impl<T: CoordNum + Send + Sync> CoordTrait for &Coord<T> { | ||
type T = T; | ||
|
||
fn x(&self) -> T { | ||
self.x | ||
} | ||
|
||
fn y(&self) -> T { | ||
self.y | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
use geo_types::{ | ||
CoordNum, Geometry, GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, | ||
Point, Polygon, | ||
}; | ||
|
||
use super::{ | ||
GeometryCollectionTrait, LineStringTrait, MultiLineStringTrait, MultiPointTrait, | ||
MultiPolygonTrait, PointTrait, PolygonTrait, | ||
}; | ||
|
||
#[allow(clippy::type_complexity)] | ||
pub trait GeometryTrait<'a>: Send + Sync { | ||
type Point: 'a + PointTrait; | ||
type LineString: 'a + LineStringTrait<'a>; | ||
type Polygon: 'a + PolygonTrait<'a>; | ||
type MultiPoint: 'a + MultiPointTrait<'a>; | ||
type MultiLineString: 'a + MultiLineStringTrait<'a>; | ||
type MultiPolygon: 'a + MultiPolygonTrait<'a>; | ||
type GeometryCollection: 'a + GeometryCollectionTrait<'a>; | ||
|
||
fn as_type( | ||
&'a self, | ||
) -> GeometryType< | ||
'a, | ||
Self::Point, | ||
Self::LineString, | ||
Self::Polygon, | ||
Self::MultiPoint, | ||
Self::MultiLineString, | ||
Self::MultiPolygon, | ||
Self::GeometryCollection, | ||
>; | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum GeometryType<'a, P, L, Y, MP, ML, MY, GC> | ||
where | ||
P: 'a + PointTrait, | ||
L: 'a + LineStringTrait<'a>, | ||
Y: 'a + PolygonTrait<'a>, | ||
MP: 'a + MultiPointTrait<'a>, | ||
ML: 'a + MultiLineStringTrait<'a>, | ||
MY: 'a + MultiPolygonTrait<'a>, | ||
GC: 'a + GeometryCollectionTrait<'a>, | ||
{ | ||
Point(&'a P), | ||
LineString(&'a L), | ||
Polygon(&'a Y), | ||
MultiPoint(&'a MP), | ||
MultiLineString(&'a ML), | ||
MultiPolygon(&'a MY), | ||
GeometryCollection(&'a GC), | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> GeometryTrait<'a> for Geometry<T> { | ||
type Point = Point<T>; | ||
type LineString = LineString<T>; | ||
type Polygon = Polygon<T>; | ||
type MultiPoint = MultiPoint<T>; | ||
type MultiLineString = MultiLineString<T>; | ||
type MultiPolygon = MultiPolygon<T>; | ||
type GeometryCollection = GeometryCollection<T>; | ||
|
||
fn as_type( | ||
&'a self, | ||
) -> GeometryType< | ||
'a, | ||
Point<T>, | ||
LineString<T>, | ||
Polygon<T>, | ||
MultiPoint<T>, | ||
MultiLineString<T>, | ||
MultiPolygon<T>, | ||
GeometryCollection<T>, | ||
> { | ||
match self { | ||
Geometry::Point(p) => GeometryType::Point(p), | ||
Geometry::LineString(p) => GeometryType::LineString(p), | ||
Geometry::Polygon(p) => GeometryType::Polygon(p), | ||
Geometry::MultiPoint(p) => GeometryType::MultiPoint(p), | ||
Geometry::MultiLineString(p) => GeometryType::MultiLineString(p), | ||
Geometry::MultiPolygon(p) => GeometryType::MultiPolygon(p), | ||
Geometry::GeometryCollection(p) => GeometryType::GeometryCollection(p), | ||
_ => todo!(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use super::GeometryTrait; | ||
use geo_types::{CoordNum, Geometry, GeometryCollection}; | ||
use std::iter::Cloned; | ||
use std::slice::Iter; | ||
|
||
pub trait GeometryCollectionTrait<'a>: Send + Sync { | ||
type ItemType: 'a + GeometryTrait<'a>; | ||
type Iter: ExactSizeIterator<Item = Self::ItemType>; | ||
|
||
/// An iterator over the geometries in this GeometryCollection | ||
fn geometries(&'a self) -> Self::Iter; | ||
|
||
/// The number of geometries in this GeometryCollection | ||
fn num_geometries(&'a self) -> usize; | ||
|
||
/// Access to a specified geometry in this GeometryCollection | ||
/// Will return None if the provided index is out of bounds | ||
fn geometry(&'a self, i: usize) -> Option<Self::ItemType>; | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for GeometryCollection<T> { | ||
type ItemType = Geometry<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn geometries(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_geometries(&'a self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn geometry(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for &GeometryCollection<T> { | ||
type ItemType = Geometry<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn geometries(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_geometries(&'a self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn geometry(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
pub use coord::CoordTrait; | ||
pub use geometry::{GeometryTrait, GeometryType}; | ||
pub use geometry_collection::GeometryCollectionTrait; | ||
pub use line_string::LineStringTrait; | ||
pub use multi_line_string::MultiLineStringTrait; | ||
pub use multi_point::MultiPointTrait; | ||
pub use multi_polygon::MultiPolygonTrait; | ||
pub use point::PointTrait; | ||
pub use polygon::PolygonTrait; | ||
|
||
mod coord; | ||
mod geometry; | ||
mod geometry_collection; | ||
mod line_string; | ||
mod multi_line_string; | ||
mod multi_point; | ||
mod multi_polygon; | ||
mod point; | ||
mod polygon; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use geo_types::{Coord, CoordNum, LineString}; | ||
|
||
use super::CoordTrait; | ||
use std::iter::Cloned; | ||
use std::slice::Iter; | ||
|
||
pub trait LineStringTrait<'a>: Send + Sync { | ||
type ItemType: 'a + CoordTrait; | ||
type Iter: ExactSizeIterator<Item = Self::ItemType>; | ||
|
||
/// An iterator over the coords in this LineString | ||
fn coords(&'a self) -> Self::Iter; | ||
|
||
/// The number of coords in this LineString | ||
fn num_coords(&'a self) -> usize; | ||
|
||
/// Access to a specified point in this LineString | ||
/// Will return None if the provided index is out of bounds | ||
fn coord(&'a self, i: usize) -> Option<Self::ItemType>; | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString<T> { | ||
type ItemType = Coord<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn coords(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_coords(&self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn coord(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for &LineString<T> { | ||
type ItemType = Coord<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn coords(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_coords(&self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn coord(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use super::line_string::LineStringTrait; | ||
use geo_types::{CoordNum, LineString, MultiLineString}; | ||
use std::iter::Cloned; | ||
use std::slice::Iter; | ||
|
||
pub trait MultiLineStringTrait<'a>: Send + Sync { | ||
type ItemType: 'a + LineStringTrait<'a>; | ||
type Iter: ExactSizeIterator<Item = Self::ItemType>; | ||
|
||
/// An iterator over the LineStrings in this MultiLineString | ||
fn lines(&'a self) -> Self::Iter; | ||
|
||
/// The number of lines in this MultiLineString | ||
fn num_lines(&'a self) -> usize; | ||
|
||
/// Access to a specified line in this MultiLineString | ||
/// Will return None if the provided index is out of bounds | ||
fn line(&'a self, i: usize) -> Option<Self::ItemType>; | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineString<T> { | ||
type ItemType = LineString<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn lines(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_lines(&'a self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn line(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} | ||
|
||
impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for &MultiLineString<T> { | ||
type ItemType = LineString<T>; | ||
type Iter = Cloned<Iter<'a, Self::ItemType>>; | ||
|
||
fn lines(&'a self) -> Self::Iter { | ||
self.0.iter().cloned() | ||
} | ||
|
||
fn num_lines(&'a self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
fn line(&'a self, i: usize) -> Option<Self::ItemType> { | ||
self.0.get(i).cloned() | ||
} | ||
} |
Oops, something went wrong.