Skip to content

Commit

Permalink
Implement geo_traits for geojson types.
Browse files Browse the repository at this point in the history
  • Loading branch information
frewsxcv committed Oct 25, 2024
1 parent ab5d70d commit fca637e
Show file tree
Hide file tree
Showing 12 changed files with 688 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ serde_json = "~1.0"
geo-types = { version = "0.7.13", features = ["serde"], optional = true }
thiserror = "1.0.20"
log = "0.4.17"
geo-traits = { git = "https://github.com/kylebarron/geo/", branch = "kyle/geo-traits-crate" }
bytemuck = { version = "1", features = ["derive"] }

[dev-dependencies]
num-traits = "0.2"
Expand Down
52 changes: 52 additions & 0 deletions src/geo_traits_impl/coord.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use super::PointType;
use geo_traits::{CoordTrait, Dimensions};

impl geo_traits::CoordTrait for PointType {
type T = f64;

fn dim(&self) -> Dimensions {
match self.0.len() {
0 | 1 => panic!("Position must have at least 2 dimensions"),
2 => Dimensions::Xy,
3 => Dimensions::Xyz,
_ => Dimensions::Unknown(self.0.len()),
}
}

fn x(&self) -> Self::T {
self.0[0]
}

fn y(&self) -> Self::T {
self.0[1]
}

fn nth_unchecked(&self, n: usize) -> Self::T {
self.0[n]
}
}

impl geo_traits::CoordTrait for &PointType {
type T = f64;

fn dim(&self) -> Dimensions {
match self.0.len() {
0 | 1 => panic!("Position must have at least 2 dimensions"),
2 => Dimensions::Xy,
3 => Dimensions::Xyz,
_ => Dimensions::Unknown(self.0.len()),
}
}

fn x(&self) -> Self::T {
self.0[0]
}

fn y(&self) -> Self::T {
self.0[1]
}

fn nth_unchecked(&self, n: usize) -> Self::T {
self.0[n]
}
}
174 changes: 174 additions & 0 deletions src/geo_traits_impl/geometry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use super::{
GeometryCollectionType, LineStringType, MultiLineStringType, MultiPointType, MultiPolygonType,
PointType, PolygonType,
};
use bytemuck::TransparentWrapper;
use geo_traits::{
Dimensions, GeometryCollectionTrait, LineStringTrait, MultiLineStringTrait, MultiPointTrait,
MultiPolygonTrait, PointTrait, PolygonTrait, UnimplementedLine, UnimplementedRect,
UnimplementedTriangle,
};

impl geo_traits::GeometryTrait for crate::Value {
type T = f64;
type PointType<'a> = PointType;
type LineStringType<'a> = LineStringType;
type PolygonType<'a> = PolygonType;
type MultiPointType<'a> = MultiPointType;
type MultiLineStringType<'a> = MultiLineStringType;
type MultiPolygonType<'a> = MultiPolygonType;
type GeometryCollectionType<'a> = GeometryCollectionType;
type RectType<'a> = UnimplementedRect<Self::T>;
type TriangleType<'a> = UnimplementedTriangle<Self::T>;
type LineType<'a> = UnimplementedLine<Self::T>;

fn as_type(
&self,
) -> geo_traits::GeometryType<
'_,
Self::PointType<'_>,
Self::LineStringType<'_>,
Self::PolygonType<'_>,
Self::MultiPointType<'_>,
Self::MultiLineStringType<'_>,
Self::MultiPolygonType<'_>,
Self::GeometryCollectionType<'_>,
Self::RectType<'_>,
Self::TriangleType<'_>,
Self::LineType<'_>,
> {
match self {
crate::Value::Point(p) => geo_traits::GeometryType::Point(PointType::wrap_ref(p)),
crate::Value::LineString(ls) => {
geo_traits::GeometryType::LineString(LineStringType::wrap_ref(ls))
}
crate::Value::Polygon(p) => geo_traits::GeometryType::Polygon(PolygonType::wrap_ref(p)),
crate::Value::MultiPoint(mp) => {
geo_traits::GeometryType::MultiPoint(MultiPointType::wrap_ref(mp))
}
crate::Value::MultiLineString(mls) => {
geo_traits::GeometryType::MultiLineString(MultiLineStringType::wrap_ref(mls))
}
crate::Value::MultiPolygon(mp) => {
geo_traits::GeometryType::MultiPolygon(MultiPolygonType::wrap_ref(mp))
}
crate::Value::GeometryCollection(gc) => {
geo_traits::GeometryType::GeometryCollection(GeometryCollectionType::wrap_ref(gc))
}
}
}

fn dim(&self) -> Dimensions {
match self {
crate::Value::Point(ref p) => PointType::wrap_ref(p).dim(),
crate::Value::LineString(ref ls) => LineStringType::wrap_ref(ls).dim(),
crate::Value::Polygon(ref p) => PolygonType::wrap_ref(p).dim(),
crate::Value::MultiPoint(ref mp) => MultiPointType::wrap_ref(mp).dim(),
crate::Value::MultiLineString(ref mls) => MultiLineStringType::wrap_ref(mls).dim(),
crate::Value::MultiPolygon(ref mp) => MultiPolygonType::wrap_ref(mp).dim(),
crate::Value::GeometryCollection(ref gc) => GeometryCollectionType::wrap_ref(gc).dim(),
}
}
}

impl geo_traits::GeometryTrait for crate::Geometry {
type T = f64;
type PointType<'b> = PointType;
type LineStringType<'b> = LineStringType;
type PolygonType<'b> = PolygonType;
type MultiPointType<'b> = MultiPointType;
type MultiLineStringType<'b> = MultiLineStringType;
type MultiPolygonType<'b> = MultiPolygonType;
type GeometryCollectionType<'b> = GeometryCollectionType;
type RectType<'b> = UnimplementedRect<Self::T>;
type TriangleType<'b> = UnimplementedTriangle<Self::T>;
type LineType<'b> = UnimplementedLine<Self::T>;

fn dim(&self) -> Dimensions {
self.value.dim()
}

fn as_type(
&self,
) -> geo_traits::GeometryType<
'_,
Self::PointType<'_>,
Self::LineStringType<'_>,
Self::PolygonType<'_>,
Self::MultiPointType<'_>,
Self::MultiLineStringType<'_>,
Self::MultiPolygonType<'_>,
Self::GeometryCollectionType<'_>,
Self::RectType<'_>,
Self::TriangleType<'_>,
Self::LineType<'_>,
> {
self.value.as_type()
}
}

impl geo_traits::GeometryTrait for &crate::Geometry {
type T = f64;
type PointType<'b>
= PointType
where
Self: 'b;
type LineStringType<'b>
= LineStringType
where
Self: 'b;
type PolygonType<'b>
= PolygonType
where
Self: 'b;
type MultiPointType<'b>
= MultiPointType
where
Self: 'b;
type MultiLineStringType<'b>
= MultiLineStringType
where
Self: 'b;
type MultiPolygonType<'b>
= MultiPolygonType
where
Self: 'b;
type GeometryCollectionType<'b>
= GeometryCollectionType
where
Self: 'b;
type RectType<'b>
= UnimplementedRect<Self::T>
where
Self: 'b;
type TriangleType<'b>
= UnimplementedTriangle<Self::T>
where
Self: 'b;
type LineType<'b>
= UnimplementedLine<Self::T>
where
Self: 'b;

fn as_type(
&self,
) -> geo_traits::GeometryType<
'_,
Self::PointType<'_>,
Self::LineStringType<'_>,
Self::PolygonType<'_>,
Self::MultiPointType<'_>,
Self::MultiLineStringType<'_>,
Self::MultiPolygonType<'_>,
Self::GeometryCollectionType<'_>,
Self::RectType<'_>,
Self::TriangleType<'_>,
Self::LineType<'_>,
> {
self.value.as_type()
}

fn dim(&self) -> Dimensions {
self.value.dim()
}
}
62 changes: 62 additions & 0 deletions src/geo_traits_impl/geometry_collection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use super::GeometryCollectionType;
use geo_traits::{Dimensions, GeometryTrait};

impl geo_traits::GeometryCollectionTrait for GeometryCollectionType {
type T = f64;
type GeometryType<'b>
= &'b crate::Geometry
where
Self: 'b;

fn dim(&self) -> Dimensions {
self.geometry(0).unwrap().dim()
}

fn geometries(
&self,
) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::GeometryType<'_>> {
self.0.iter()
}

fn geometry(&self, i: usize) -> Option<Self::GeometryType<'_>> {
self.0.get(i)
}

unsafe fn geometry_unchecked(&self, i: usize) -> Self::GeometryType<'_> {
self.0.get_unchecked(i)
}

fn num_geometries(&self) -> usize {
self.0.len()
}
}

impl<'a> geo_traits::GeometryCollectionTrait for &'a GeometryCollectionType {
type T = f64;
type GeometryType<'b>
= &'b crate::Geometry
where
Self: 'b;

fn dim(&self) -> Dimensions {
unimplemented!()
}

fn geometries(
&self,
) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::GeometryType<'_>> {
self.0.iter()
}

fn geometry(&self, i: usize) -> Option<Self::GeometryType<'_>> {
self.0.get(i)
}

unsafe fn geometry_unchecked(&self, i: usize) -> Self::GeometryType<'_> {
self.0.get_unchecked(i)
}

fn num_geometries(&self) -> usize {
self.0.len()
}
}
59 changes: 59 additions & 0 deletions src/geo_traits_impl/line_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use super::{LineStringType, PointType};
use bytemuck::TransparentWrapper;
use geo_traits::{Dimensions, LineStringTrait, PointTrait};

impl LineStringTrait for LineStringType {
type T = f64;
type CoordType<'b>
= &'b PointType
where
Self: 'b;

fn num_coords(&self) -> usize {
self.0.len()
}

fn coord(&self, i: usize) -> Option<Self::CoordType<'_>> {
Some(PointType::wrap_ref(&self.0[i]))
}

unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
self.coord(i).unwrap()
}

fn coords(&self) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::CoordType<'_>> {
self.0.iter().map(PointType::wrap_ref)
}

fn dim(&self) -> Dimensions {
self.coord(0).unwrap().dim() // TODO: is this okay?
}
}

impl<'a> geo_traits::LineStringTrait for &'a LineStringType {
type T = f64;
type CoordType<'b>
= &'b PointType
where
Self: 'b;

fn num_coords(&self) -> usize {
self.0.len()
}

fn coord(&self, i: usize) -> Option<Self::CoordType<'_>> {
Some(PointType::wrap_ref(&self.0[i]))
}

unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
self.coord(i).unwrap()
}

fn coords(&self) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::CoordType<'_>> {
self.0.iter().map(PointType::wrap_ref)
}

fn dim(&self) -> Dimensions {
self.coord(0).unwrap().dim()
}
}
Loading

0 comments on commit fca637e

Please sign in to comment.