From 9f785267e01675e897f8dbdf179ad7d382f57ffe Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Wed, 21 Jun 2023 13:29:43 -0400 Subject: [PATCH 01/15] wip area trait --- geo-traits/src/coord.rs | 4 ++- geo/Cargo.toml | 1 + geo/src/algorithm/area.rs | 76 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/geo-traits/src/coord.rs b/geo-traits/src/coord.rs index 2036ef9f9..cdba39fe5 100644 --- a/geo-traits/src/coord.rs +++ b/geo-traits/src/coord.rs @@ -1,7 +1,9 @@ +use std::ops::{AddAssign, SubAssign}; + use geo_types::{Coord, CoordNum, Point}; pub trait CoordTrait: Send + Sync { - type T: CoordNum + Send + Sync; + type T: CoordNum + Send + Sync; // + AddAssign + SubAssign; /// x component of this coord fn x(&self) -> Self::T; diff --git a/geo/Cargo.toml b/geo/Cargo.toml index 1a13372c9..1b0da9fca 100644 --- a/geo/Cargo.toml +++ b/geo/Cargo.toml @@ -21,6 +21,7 @@ use-serde = ["serde", "geo-types/serde"] earcutr = { version = "0.4.2", optional = true } float_next_after = "1.0.0" geo-types = { version = "0.7.9", features = ["approx", "use-rstar_0_10"] } +geo-traits = { path = "../geo-traits" } geographiclib-rs = { version = "0.2.3", default-features = false } log = "0.4.11" num-traits = "0.2" diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 351a68ca6..da25b8f64 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,5 +1,7 @@ use crate::geometry::*; +use crate::num_traits::{One, Zero}; use crate::{CoordFloat, CoordNum}; +use geo_traits::{CoordTrait, LineStringTrait, PolygonTrait}; pub(crate) fn twice_signed_ring_area(linestring: &LineString) -> T where @@ -39,6 +41,52 @@ where tmp } +pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTrait<'a>) -> f64 { + // LineString with less than 3 points is empty, or a + // single point, or is not closed. + if linestring.num_coords() < 3 { + return f64::zero(); + } + + // Above test ensures the vector has at least 2 elements. + // We check if linestring is closed, and return 0 otherwise. + // TODO: should the trait require Eq? + let p1 = linestring.coord(0).unwrap(); + let p2 = linestring.coord(linestring.num_coords() - 1).unwrap(); + let closed = p1.x() == p2.x() && p1.y() == p2.y(); + if !closed { + return 0_f64; + } + + // Use a reasonable shift for the line-string coords + // to avoid numerical-errors when summing the + // determinants. + // + // Note: we can't use the `Centroid` trait as it + // requires `T: Float` and in fact computes area in the + // implementation. Another option is to use the average + // of the coordinates, but it is not fool-proof to + // divide by the length of the linestring (eg. a long + // line-string with T = u8) + let shift = linestring.coord(0).unwrap(); + + let mut tmp = 0_f64; + for i in (0..linestring.num_coords()).step_by(2) { + let mut c1 = linestring.coord(i).unwrap().x_y(); + c1.0 -= shift.x(); + c1.1 -= shift.y(); + + let mut c2 = linestring.coord(i).unwrap().x_y(); + c2.0 -= shift.x(); + c2.1 -= shift.y(); + + let line = Line::from([c1, c2]); + tmp += line.determinant(); + } + + tmp +} + /// Signed and unsigned planar area of a geometry. /// /// # Examples @@ -82,6 +130,11 @@ where twice_signed_ring_area(linestring) / (T::one() + T::one()) } +// Calculation of simple (no interior holes) Polygon area +pub(crate) fn get_linestring_area_trait<'a>(linestring: &'a impl LineStringTrait<'a>) -> f64 { + twice_signed_ring_area_trait(linestring) / (f64::one() + f64::one()) +} + impl Area for Point where T: CoordNum, @@ -151,6 +204,29 @@ where } } +pub fn unsigned_area_polygon<'a>(geom: &'a impl PolygonTrait<'a>) -> f64 { + let area = get_linestring_area_trait(&geom.exterior()); + area.abs() + + // // We could use winding order here, but that would + // // result in computing the shoelace formula twice. + // let is_negative = area < 0_f64; + + // for i in geom.num_interiors() { + + // } + + // let area = geom.interiors().iter().fold(area.abs(), |total, next| { + // total - get_linestring_area(next).abs() + // }); + + // if is_negative { + // -area + // } else { + // area + // } +} + impl Area for MultiPoint where T: CoordNum, From f233571d2fae1fc00f17588309e76306d5094aee Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Wed, 21 Jun 2023 13:30:30 -0400 Subject: [PATCH 02/15] fix index --- geo/src/algorithm/area.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index da25b8f64..5fc285fc5 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -76,7 +76,7 @@ pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTr c1.0 -= shift.x(); c1.1 -= shift.y(); - let mut c2 = linestring.coord(i).unwrap().x_y(); + let mut c2 = linestring.coord(i + 1).unwrap().x_y(); c2.0 -= shift.x(); c2.1 -= shift.y(); From 2b7f4999421b8dafbc3e8aeb5549f6e4e1da7bdb Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Thu, 22 Jun 2023 22:15:43 -0400 Subject: [PATCH 03/15] Switch to manually constructing Coord --- geo/src/algorithm/area.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 5fc285fc5..60a0cb8b5 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -72,13 +72,13 @@ pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTr let mut tmp = 0_f64; for i in (0..linestring.num_coords()).step_by(2) { - let mut c1 = linestring.coord(i).unwrap().x_y(); - c1.0 -= shift.x(); - c1.1 -= shift.y(); + let mut c1 = Coord { x: linestring.coord(i).unwrap().x(), y: linestring.coord(i).unwrap().y() }; + c1.x -= shift.x(); + c1.y -= shift.y(); - let mut c2 = linestring.coord(i + 1).unwrap().x_y(); - c2.0 -= shift.x(); - c2.1 -= shift.y(); + let mut c2 = Coord { x: linestring.coord(i + 1).unwrap().x(), y: linestring.coord(i + 1).unwrap().y() }; + c2.x -= shift.x(); + c2.y -= shift.y(); let line = Line::from([c1, c2]); tmp += line.determinant(); From c3656cce339d4b81e6a123580320d7e0721bedeb Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Thu, 22 Jun 2023 22:16:50 -0400 Subject: [PATCH 04/15] Remove Coord AddAssign SubAssign --- geo-traits/src/coord.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/geo-traits/src/coord.rs b/geo-traits/src/coord.rs index cdba39fe5..2036ef9f9 100644 --- a/geo-traits/src/coord.rs +++ b/geo-traits/src/coord.rs @@ -1,9 +1,7 @@ -use std::ops::{AddAssign, SubAssign}; - use geo_types::{Coord, CoordNum, Point}; pub trait CoordTrait: Send + Sync { - type T: CoordNum + Send + Sync; // + AddAssign + SubAssign; + type T: CoordNum + Send + Sync; /// x component of this coord fn x(&self) -> Self::T; From fd62519c82551e408c0b654408d17ccb64b7d1a0 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Thu, 22 Jun 2023 22:33:20 -0400 Subject: [PATCH 05/15] Maybe progress? --- geo-traits/src/geometry.rs | 4 +- geo-traits/src/geometry_collection.rs | 9 +++- geo-traits/src/line_string.rs | 10 +++-- geo-traits/src/multi_line_string.rs | 9 +++- geo-traits/src/multi_point.rs | 5 ++- geo-traits/src/multi_polygon.rs | 5 ++- geo-traits/src/polygon.rs | 10 +++-- geo/src/algorithm/area.rs | 61 +++++++++++++-------------- 8 files changed, 67 insertions(+), 46 deletions(-) diff --git a/geo-traits/src/geometry.rs b/geo-traits/src/geometry.rs index 3fede9acb..35c5242e2 100644 --- a/geo-traits/src/geometry.rs +++ b/geo-traits/src/geometry.rs @@ -1,3 +1,5 @@ +use std::ops::SubAssign; + use geo_types::{ CoordNum, Geometry, GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, @@ -52,7 +54,7 @@ where GeometryCollection(&'a GC), } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryTrait<'a> for Geometry { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryTrait<'a> for Geometry { type Point = Point; type LineString = LineString; type Polygon = Polygon; diff --git a/geo-traits/src/geometry_collection.rs b/geo-traits/src/geometry_collection.rs index 4343ad121..894f5ad95 100644 --- a/geo-traits/src/geometry_collection.rs +++ b/geo-traits/src/geometry_collection.rs @@ -1,6 +1,7 @@ use super::GeometryTrait; use geo_types::{CoordNum, Geometry, GeometryCollection}; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait GeometryCollectionTrait<'a>: Send + Sync { @@ -18,7 +19,9 @@ pub trait GeometryCollectionTrait<'a>: Send + Sync { fn geometry(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for GeometryCollection { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryCollectionTrait<'a> + for GeometryCollection +{ type ItemType = Geometry; type Iter = Cloned>; @@ -35,7 +38,9 @@ impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for Geometr } } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for &GeometryCollection { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryCollectionTrait<'a> + for &GeometryCollection +{ type ItemType = Geometry; type Iter = Cloned>; diff --git a/geo-traits/src/line_string.rs b/geo-traits/src/line_string.rs index b4fa30bd3..5fb73ef7b 100644 --- a/geo-traits/src/line_string.rs +++ b/geo-traits/src/line_string.rs @@ -2,10 +2,12 @@ use geo_types::{Coord, CoordNum, LineString}; use super::CoordTrait; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait LineStringTrait<'a>: Send + Sync { - type ItemType: 'a + CoordTrait; + type T: CoordNum + Send + Sync + SubAssign; + type ItemType: 'a + CoordTrait; type Iter: ExactSizeIterator; /// An iterator over the coords in this LineString @@ -19,7 +21,8 @@ pub trait LineStringTrait<'a>: Send + Sync { fn coord(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> LineStringTrait<'a> for LineString { + type T = T; type ItemType = Coord; type Iter = Cloned>; @@ -36,7 +39,8 @@ impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString { } } -impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for &LineString { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> LineStringTrait<'a> for &LineString { + type T = T; type ItemType = Coord; type Iter = Cloned>; diff --git a/geo-traits/src/multi_line_string.rs b/geo-traits/src/multi_line_string.rs index 27debbfe5..2ef462542 100644 --- a/geo-traits/src/multi_line_string.rs +++ b/geo-traits/src/multi_line_string.rs @@ -1,6 +1,7 @@ use super::line_string::LineStringTrait; use geo_types::{CoordNum, LineString, MultiLineString}; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait MultiLineStringTrait<'a>: Send + Sync { @@ -18,7 +19,9 @@ pub trait MultiLineStringTrait<'a>: Send + Sync { fn line(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineString { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiLineStringTrait<'a> + for MultiLineString +{ type ItemType = LineString; type Iter = Cloned>; @@ -35,7 +38,9 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineS } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for &MultiLineString { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiLineStringTrait<'a> + for &MultiLineString +{ type ItemType = LineString; type Iter = Cloned>; diff --git a/geo-traits/src/multi_point.rs b/geo-traits/src/multi_point.rs index 01fc858bc..8bc52768f 100644 --- a/geo-traits/src/multi_point.rs +++ b/geo-traits/src/multi_point.rs @@ -1,6 +1,7 @@ use super::point::PointTrait; use geo_types::{CoordNum, MultiPoint, Point}; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait MultiPointTrait<'a>: Send + Sync { @@ -18,7 +19,7 @@ pub trait MultiPointTrait<'a>: Send + Sync { fn point(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for MultiPoint { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPointTrait<'a> for MultiPoint { type ItemType = Point; type Iter = Cloned>; @@ -35,7 +36,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for MultiPoint { } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for &MultiPoint { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPointTrait<'a> for &MultiPoint { type ItemType = Point; type Iter = Cloned>; diff --git a/geo-traits/src/multi_polygon.rs b/geo-traits/src/multi_polygon.rs index 4b2eeacfa..d6d723c5c 100644 --- a/geo-traits/src/multi_polygon.rs +++ b/geo-traits/src/multi_polygon.rs @@ -1,6 +1,7 @@ use super::polygon::PolygonTrait; use geo_types::{CoordNum, MultiPolygon, Polygon}; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait MultiPolygonTrait<'a>: Send + Sync { @@ -18,7 +19,7 @@ pub trait MultiPolygonTrait<'a>: Send + Sync { fn polygon(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for MultiPolygon { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPolygonTrait<'a> for MultiPolygon { type ItemType = Polygon; type Iter = Cloned>; @@ -35,7 +36,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for MultiPolygon< } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for &MultiPolygon { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPolygonTrait<'a> for &MultiPolygon { type ItemType = Polygon; type Iter = Cloned>; diff --git a/geo-traits/src/polygon.rs b/geo-traits/src/polygon.rs index be8ad591b..50bbe2849 100644 --- a/geo-traits/src/polygon.rs +++ b/geo-traits/src/polygon.rs @@ -1,10 +1,12 @@ use super::line_string::LineStringTrait; use geo_types::{CoordNum, LineString, Polygon}; use std::iter::Cloned; +use std::ops::SubAssign; use std::slice::Iter; pub trait PolygonTrait<'a>: Send + Sync { - type ItemType: 'a + LineStringTrait<'a>; + type T: CoordNum + Send + Sync + SubAssign; + type ItemType: 'a + LineStringTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; /// The exterior ring of the polygon @@ -21,7 +23,8 @@ pub trait PolygonTrait<'a>: Send + Sync { fn interior(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for Polygon { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> PolygonTrait<'a> for Polygon { + type T = T; type ItemType = LineString; type Iter = Cloned>; @@ -42,7 +45,8 @@ impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for Polygon { } } -impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for &Polygon { +impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> PolygonTrait<'a> for &Polygon { + type T = T; type ItemType = LineString; type Iter = Cloned>; diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 60a0cb8b5..8275351f5 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,5 +1,6 @@ +use std::ops::{AddAssign, SubAssign}; + use crate::geometry::*; -use crate::num_traits::{One, Zero}; use crate::{CoordFloat, CoordNum}; use geo_traits::{CoordTrait, LineStringTrait, PolygonTrait}; @@ -41,11 +42,16 @@ where tmp } -pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTrait<'a>) -> f64 { +pub(crate) fn twice_signed_ring_area_trait<'a, T>( + linestring: &'a impl LineStringTrait<'a, T = T>, +) -> T +where + T: CoordNum + SubAssign + AddAssign, +{ // LineString with less than 3 points is empty, or a // single point, or is not closed. if linestring.num_coords() < 3 { - return f64::zero(); + return T::zero(); } // Above test ensures the vector has at least 2 elements. @@ -55,7 +61,7 @@ pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTr let p2 = linestring.coord(linestring.num_coords() - 1).unwrap(); let closed = p1.x() == p2.x() && p1.y() == p2.y(); if !closed { - return 0_f64; + return T::zero(); } // Use a reasonable shift for the line-string coords @@ -70,17 +76,23 @@ pub(crate) fn twice_signed_ring_area_trait<'a>(linestring: &'a impl LineStringTr // line-string with T = u8) let shift = linestring.coord(0).unwrap(); - let mut tmp = 0_f64; + let mut tmp = T::zero(); for i in (0..linestring.num_coords()).step_by(2) { - let mut c1 = Coord { x: linestring.coord(i).unwrap().x(), y: linestring.coord(i).unwrap().y() }; + let mut c1 = Coord { + x: linestring.coord(i).unwrap().x(), + y: linestring.coord(i).unwrap().y(), + }; c1.x -= shift.x(); c1.y -= shift.y(); - let mut c2 = Coord { x: linestring.coord(i + 1).unwrap().x(), y: linestring.coord(i + 1).unwrap().y() }; + let mut c2 = Coord { + x: linestring.coord(i + 1).unwrap().x(), + y: linestring.coord(i + 1).unwrap().y(), + }; c2.x -= shift.x(); c2.y -= shift.y(); - let line = Line::from([c1, c2]); + let line = Line::new(c1, c2); tmp += line.determinant(); } @@ -131,8 +143,11 @@ where } // Calculation of simple (no interior holes) Polygon area -pub(crate) fn get_linestring_area_trait<'a>(linestring: &'a impl LineStringTrait<'a>) -> f64 { - twice_signed_ring_area_trait(linestring) / (f64::one() + f64::one()) +pub(crate) fn get_linestring_area_trait<'a, T>(linestring: &'a impl LineStringTrait<'a, T = T>) -> T +where + T: CoordFloat + SubAssign + AddAssign, +{ + twice_signed_ring_area_trait(linestring) / (T::one() + T::one()) } impl Area for Point @@ -204,27 +219,11 @@ where } } -pub fn unsigned_area_polygon<'a>(geom: &'a impl PolygonTrait<'a>) -> f64 { - let area = get_linestring_area_trait(&geom.exterior()); - area.abs() - - // // We could use winding order here, but that would - // // result in computing the shoelace formula twice. - // let is_negative = area < 0_f64; - - // for i in geom.num_interiors() { - - // } - - // let area = geom.interiors().iter().fold(area.abs(), |total, next| { - // total - get_linestring_area(next).abs() - // }); - - // if is_negative { - // -area - // } else { - // area - // } +pub fn unsigned_area_polygon<'a, T>(geom: &'a impl PolygonTrait<'a, T = T>) -> T +where + T: CoordFloat + SubAssign + AddAssign, +{ + get_linestring_area_trait(&geom.exterior()).abs() } impl Area for MultiPoint From 5b267cadf5077ed5855b8a601d6fd04829b2e3fe Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Thu, 22 Jun 2023 22:48:10 -0400 Subject: [PATCH 06/15] remove global SubAssign bound --- geo-traits/src/geometry.rs | 4 +--- geo-traits/src/geometry_collection.rs | 9 ++------- geo-traits/src/line_string.rs | 7 +++---- geo-traits/src/multi_line_string.rs | 9 ++------- geo-traits/src/multi_point.rs | 5 ++--- geo-traits/src/multi_polygon.rs | 10 ++++++---- geo-traits/src/polygon.rs | 7 +++---- 7 files changed, 19 insertions(+), 32 deletions(-) diff --git a/geo-traits/src/geometry.rs b/geo-traits/src/geometry.rs index 35c5242e2..3fede9acb 100644 --- a/geo-traits/src/geometry.rs +++ b/geo-traits/src/geometry.rs @@ -1,5 +1,3 @@ -use std::ops::SubAssign; - use geo_types::{ CoordNum, Geometry, GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, @@ -54,7 +52,7 @@ where GeometryCollection(&'a GC), } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryTrait<'a> for Geometry { +impl<'a, T: CoordNum + Send + Sync + 'a> GeometryTrait<'a> for Geometry { type Point = Point; type LineString = LineString; type Polygon = Polygon; diff --git a/geo-traits/src/geometry_collection.rs b/geo-traits/src/geometry_collection.rs index 894f5ad95..4343ad121 100644 --- a/geo-traits/src/geometry_collection.rs +++ b/geo-traits/src/geometry_collection.rs @@ -1,7 +1,6 @@ use super::GeometryTrait; use geo_types::{CoordNum, Geometry, GeometryCollection}; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait GeometryCollectionTrait<'a>: Send + Sync { @@ -19,9 +18,7 @@ pub trait GeometryCollectionTrait<'a>: Send + Sync { fn geometry(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryCollectionTrait<'a> - for GeometryCollection -{ +impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for GeometryCollection { type ItemType = Geometry; type Iter = Cloned>; @@ -38,9 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryCollectionTrait<'a> } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> GeometryCollectionTrait<'a> - for &GeometryCollection -{ +impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for &GeometryCollection { type ItemType = Geometry; type Iter = Cloned>; diff --git a/geo-traits/src/line_string.rs b/geo-traits/src/line_string.rs index 5fb73ef7b..f397754e7 100644 --- a/geo-traits/src/line_string.rs +++ b/geo-traits/src/line_string.rs @@ -2,11 +2,10 @@ use geo_types::{Coord, CoordNum, LineString}; use super::CoordTrait; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait LineStringTrait<'a>: Send + Sync { - type T: CoordNum + Send + Sync + SubAssign; + type T: CoordNum + Send + Sync; type ItemType: 'a + CoordTrait; type Iter: ExactSizeIterator; @@ -21,7 +20,7 @@ pub trait LineStringTrait<'a>: Send + Sync { fn coord(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> LineStringTrait<'a> for LineString { +impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString { type T = T; type ItemType = Coord; type Iter = Cloned>; @@ -39,7 +38,7 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> LineStringTrait<'a> for Lin } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> LineStringTrait<'a> for &LineString { +impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for &LineString { type T = T; type ItemType = Coord; type Iter = Cloned>; diff --git a/geo-traits/src/multi_line_string.rs b/geo-traits/src/multi_line_string.rs index 2ef462542..27debbfe5 100644 --- a/geo-traits/src/multi_line_string.rs +++ b/geo-traits/src/multi_line_string.rs @@ -1,7 +1,6 @@ use super::line_string::LineStringTrait; use geo_types::{CoordNum, LineString, MultiLineString}; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait MultiLineStringTrait<'a>: Send + Sync { @@ -19,9 +18,7 @@ pub trait MultiLineStringTrait<'a>: Send + Sync { fn line(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiLineStringTrait<'a> - for MultiLineString -{ +impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineString { type ItemType = LineString; type Iter = Cloned>; @@ -38,9 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiLineStringTrait<'a> } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiLineStringTrait<'a> - for &MultiLineString -{ +impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for &MultiLineString { type ItemType = LineString; type Iter = Cloned>; diff --git a/geo-traits/src/multi_point.rs b/geo-traits/src/multi_point.rs index 8bc52768f..01fc858bc 100644 --- a/geo-traits/src/multi_point.rs +++ b/geo-traits/src/multi_point.rs @@ -1,7 +1,6 @@ use super::point::PointTrait; use geo_types::{CoordNum, MultiPoint, Point}; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait MultiPointTrait<'a>: Send + Sync { @@ -19,7 +18,7 @@ pub trait MultiPointTrait<'a>: Send + Sync { fn point(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPointTrait<'a> for MultiPoint { +impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for MultiPoint { type ItemType = Point; type Iter = Cloned>; @@ -36,7 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPointTrait<'a> for Mul } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPointTrait<'a> for &MultiPoint { +impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for &MultiPoint { type ItemType = Point; type Iter = Cloned>; diff --git a/geo-traits/src/multi_polygon.rs b/geo-traits/src/multi_polygon.rs index d6d723c5c..34ed3effb 100644 --- a/geo-traits/src/multi_polygon.rs +++ b/geo-traits/src/multi_polygon.rs @@ -1,11 +1,11 @@ use super::polygon::PolygonTrait; use geo_types::{CoordNum, MultiPolygon, Polygon}; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait MultiPolygonTrait<'a>: Send + Sync { - type ItemType: 'a + PolygonTrait<'a>; + type T: CoordNum + Send + Sync; + type ItemType: 'a + PolygonTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; /// An iterator over the Polygons in this MultiPolygon @@ -19,7 +19,8 @@ pub trait MultiPolygonTrait<'a>: Send + Sync { fn polygon(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPolygonTrait<'a> for MultiPolygon { +impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for MultiPolygon { + type T = T; type ItemType = Polygon; type Iter = Cloned>; @@ -36,7 +37,8 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPolygonTrait<'a> for M } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> MultiPolygonTrait<'a> for &MultiPolygon { +impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for &MultiPolygon { + type T = T; type ItemType = Polygon; type Iter = Cloned>; diff --git a/geo-traits/src/polygon.rs b/geo-traits/src/polygon.rs index 50bbe2849..469ae514a 100644 --- a/geo-traits/src/polygon.rs +++ b/geo-traits/src/polygon.rs @@ -1,11 +1,10 @@ use super::line_string::LineStringTrait; use geo_types::{CoordNum, LineString, Polygon}; use std::iter::Cloned; -use std::ops::SubAssign; use std::slice::Iter; pub trait PolygonTrait<'a>: Send + Sync { - type T: CoordNum + Send + Sync + SubAssign; + type T: CoordNum + Send + Sync; type ItemType: 'a + LineStringTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; @@ -23,7 +22,7 @@ pub trait PolygonTrait<'a>: Send + Sync { fn interior(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> PolygonTrait<'a> for Polygon { +impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for Polygon { type T = T; type ItemType = LineString; type Iter = Cloned>; @@ -45,7 +44,7 @@ impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> PolygonTrait<'a> for Polygo } } -impl<'a, T: CoordNum + Send + Sync + SubAssign + 'a> PolygonTrait<'a> for &Polygon { +impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for &Polygon { type T = T; type ItemType = LineString; type Iter = Cloned>; From 5893b97233f5988fc80f62163f64f40799329be8 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 19:51:14 -0400 Subject: [PATCH 07/15] Fix compilation, remove send + sync --- geo-traits/src/coord.rs | 12 ++++++------ geo-traits/src/geometry.rs | 4 ++-- geo-traits/src/geometry_collection.rs | 6 +++--- geo-traits/src/line_string.rs | 16 ++++++++-------- geo-traits/src/multi_line_string.rs | 6 +++--- geo-traits/src/multi_point.rs | 6 +++--- geo-traits/src/multi_polygon.rs | 8 ++++---- geo-traits/src/point.rs | 12 ++++++------ geo-traits/src/polygon.rs | 8 ++++---- geo/src/algorithm/area.rs | 22 ++++++++++------------ 10 files changed, 49 insertions(+), 51 deletions(-) diff --git a/geo-traits/src/coord.rs b/geo-traits/src/coord.rs index 2036ef9f9..5ad203f24 100644 --- a/geo-traits/src/coord.rs +++ b/geo-traits/src/coord.rs @@ -1,7 +1,7 @@ use geo_types::{Coord, CoordNum, Point}; -pub trait CoordTrait: Send + Sync { - type T: CoordNum + Send + Sync; +pub trait CoordTrait { + type T: CoordNum; /// x component of this coord fn x(&self) -> Self::T; @@ -15,7 +15,7 @@ pub trait CoordTrait: Send + Sync { } } -impl CoordTrait for Point { +impl CoordTrait for Point { type T = T; fn x(&self) -> T { @@ -27,7 +27,7 @@ impl CoordTrait for Point { } } -impl CoordTrait for &Point { +impl CoordTrait for &Point { type T = T; fn x(&self) -> T { @@ -39,7 +39,7 @@ impl CoordTrait for &Point { } } -impl CoordTrait for Coord { +impl CoordTrait for Coord { type T = T; fn x(&self) -> T { @@ -51,7 +51,7 @@ impl CoordTrait for Coord { } } -impl CoordTrait for &Coord { +impl CoordTrait for &Coord { type T = T; fn x(&self) -> T { diff --git a/geo-traits/src/geometry.rs b/geo-traits/src/geometry.rs index 3fede9acb..74135ad8c 100644 --- a/geo-traits/src/geometry.rs +++ b/geo-traits/src/geometry.rs @@ -9,7 +9,7 @@ use super::{ }; #[allow(clippy::type_complexity)] -pub trait GeometryTrait<'a>: Send + Sync { +pub trait GeometryTrait<'a> { type Point: 'a + PointTrait; type LineString: 'a + LineStringTrait<'a>; type Polygon: 'a + PolygonTrait<'a>; @@ -52,7 +52,7 @@ where GeometryCollection(&'a GC), } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryTrait<'a> for Geometry { +impl<'a, T: CoordNum + 'a> GeometryTrait<'a> for Geometry { type Point = Point; type LineString = LineString; type Polygon = Polygon; diff --git a/geo-traits/src/geometry_collection.rs b/geo-traits/src/geometry_collection.rs index 4343ad121..8eb12334a 100644 --- a/geo-traits/src/geometry_collection.rs +++ b/geo-traits/src/geometry_collection.rs @@ -3,7 +3,7 @@ use geo_types::{CoordNum, Geometry, GeometryCollection}; use std::iter::Cloned; use std::slice::Iter; -pub trait GeometryCollectionTrait<'a>: Send + Sync { +pub trait GeometryCollectionTrait<'a> { type ItemType: 'a + GeometryTrait<'a>; type Iter: ExactSizeIterator; @@ -18,7 +18,7 @@ pub trait GeometryCollectionTrait<'a>: Send + Sync { fn geometry(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for GeometryCollection { +impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for GeometryCollection { type ItemType = Geometry; type Iter = Cloned>; @@ -35,7 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for Geometr } } -impl<'a, T: CoordNum + Send + Sync + 'a> GeometryCollectionTrait<'a> for &GeometryCollection { +impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for &GeometryCollection { type ItemType = Geometry; type Iter = Cloned>; diff --git a/geo-traits/src/line_string.rs b/geo-traits/src/line_string.rs index f397754e7..d0c6f5b32 100644 --- a/geo-traits/src/line_string.rs +++ b/geo-traits/src/line_string.rs @@ -4,8 +4,8 @@ use super::CoordTrait; use std::iter::Cloned; use std::slice::Iter; -pub trait LineStringTrait<'a>: Send + Sync { - type T: CoordNum + Send + Sync; +pub trait LineStringTrait<'a> { + type T: CoordNum; type ItemType: 'a + CoordTrait; type Iter: ExactSizeIterator; @@ -13,14 +13,14 @@ pub trait LineStringTrait<'a>: Send + Sync { fn coords(&'a self) -> Self::Iter; /// The number of coords in this LineString - fn num_coords(&'a self) -> usize; + fn num_coords(&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; + fn coord(&self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString { +impl<'a, T: CoordNum + 'a> LineStringTrait<'a> for LineString { type T = T; type ItemType = Coord; type Iter = Cloned>; @@ -33,12 +33,12 @@ impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for LineString { self.0.len() } - fn coord(&'a self, i: usize) -> Option { + fn coord(&self, i: usize) -> Option { self.0.get(i).cloned() } } -impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for &LineString { +impl<'a, T: CoordNum + 'a> LineStringTrait<'a> for &LineString { type T = T; type ItemType = Coord; type Iter = Cloned>; @@ -51,7 +51,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> LineStringTrait<'a> for &LineString self.0.len() } - fn coord(&'a self, i: usize) -> Option { + fn coord(&self, i: usize) -> Option { self.0.get(i).cloned() } } diff --git a/geo-traits/src/multi_line_string.rs b/geo-traits/src/multi_line_string.rs index 27debbfe5..0824740df 100644 --- a/geo-traits/src/multi_line_string.rs +++ b/geo-traits/src/multi_line_string.rs @@ -3,7 +3,7 @@ use geo_types::{CoordNum, LineString, MultiLineString}; use std::iter::Cloned; use std::slice::Iter; -pub trait MultiLineStringTrait<'a>: Send + Sync { +pub trait MultiLineStringTrait<'a> { type ItemType: 'a + LineStringTrait<'a>; type Iter: ExactSizeIterator; @@ -18,7 +18,7 @@ pub trait MultiLineStringTrait<'a>: Send + Sync { fn line(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineString { +impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for MultiLineString { type ItemType = LineString; type Iter = Cloned>; @@ -35,7 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for MultiLineS } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiLineStringTrait<'a> for &MultiLineString { +impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for &MultiLineString { type ItemType = LineString; type Iter = Cloned>; diff --git a/geo-traits/src/multi_point.rs b/geo-traits/src/multi_point.rs index 01fc858bc..3372c5a4d 100644 --- a/geo-traits/src/multi_point.rs +++ b/geo-traits/src/multi_point.rs @@ -3,7 +3,7 @@ use geo_types::{CoordNum, MultiPoint, Point}; use std::iter::Cloned; use std::slice::Iter; -pub trait MultiPointTrait<'a>: Send + Sync { +pub trait MultiPointTrait<'a> { type ItemType: 'a + PointTrait; type Iter: ExactSizeIterator; @@ -18,7 +18,7 @@ pub trait MultiPointTrait<'a>: Send + Sync { fn point(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for MultiPoint { +impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for MultiPoint { type ItemType = Point; type Iter = Cloned>; @@ -35,7 +35,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for MultiPoint { } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPointTrait<'a> for &MultiPoint { +impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for &MultiPoint { type ItemType = Point; type Iter = Cloned>; diff --git a/geo-traits/src/multi_polygon.rs b/geo-traits/src/multi_polygon.rs index 34ed3effb..c4facf0c5 100644 --- a/geo-traits/src/multi_polygon.rs +++ b/geo-traits/src/multi_polygon.rs @@ -3,8 +3,8 @@ use geo_types::{CoordNum, MultiPolygon, Polygon}; use std::iter::Cloned; use std::slice::Iter; -pub trait MultiPolygonTrait<'a>: Send + Sync { - type T: CoordNum + Send + Sync; +pub trait MultiPolygonTrait<'a> { + type T: CoordNum; type ItemType: 'a + PolygonTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; @@ -19,7 +19,7 @@ pub trait MultiPolygonTrait<'a>: Send + Sync { fn polygon(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for MultiPolygon { +impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for MultiPolygon { type T = T; type ItemType = Polygon; type Iter = Cloned>; @@ -37,7 +37,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for MultiPolygon< } } -impl<'a, T: CoordNum + Send + Sync + 'a> MultiPolygonTrait<'a> for &MultiPolygon { +impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for &MultiPolygon { type T = T; type ItemType = Polygon; type Iter = Cloned>; diff --git a/geo-traits/src/point.rs b/geo-traits/src/point.rs index 1f33ea843..e9bac5686 100644 --- a/geo-traits/src/point.rs +++ b/geo-traits/src/point.rs @@ -1,7 +1,7 @@ use geo_types::{Coord, CoordNum, Point}; -pub trait PointTrait: Send + Sync { - type T: CoordNum + Send + Sync; +pub trait PointTrait { + type T: CoordNum; /// x component of this coord fn x(&self) -> Self::T; @@ -13,7 +13,7 @@ pub trait PointTrait: Send + Sync { fn x_y(&self) -> (Self::T, Self::T); } -impl PointTrait for Point { +impl PointTrait for Point { type T = T; fn x(&self) -> T { @@ -29,7 +29,7 @@ impl PointTrait for Point { } } -impl PointTrait for &Point { +impl PointTrait for &Point { type T = T; fn x(&self) -> T { @@ -45,7 +45,7 @@ impl PointTrait for &Point { } } -impl PointTrait for Coord { +impl PointTrait for Coord { type T = T; fn x(&self) -> T { @@ -61,7 +61,7 @@ impl PointTrait for Coord { } } -impl PointTrait for &Coord { +impl PointTrait for &Coord { type T = T; fn x(&self) -> T { diff --git a/geo-traits/src/polygon.rs b/geo-traits/src/polygon.rs index 469ae514a..2863c0c36 100644 --- a/geo-traits/src/polygon.rs +++ b/geo-traits/src/polygon.rs @@ -3,8 +3,8 @@ use geo_types::{CoordNum, LineString, Polygon}; use std::iter::Cloned; use std::slice::Iter; -pub trait PolygonTrait<'a>: Send + Sync { - type T: CoordNum + Send + Sync; +pub trait PolygonTrait<'a> { + type T: CoordNum; type ItemType: 'a + LineStringTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; @@ -22,7 +22,7 @@ pub trait PolygonTrait<'a>: Send + Sync { fn interior(&'a self, i: usize) -> Option; } -impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for Polygon { +impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { type T = T; type ItemType = LineString; type Iter = Cloned>; @@ -44,7 +44,7 @@ impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for Polygon { } } -impl<'a, T: CoordNum + Send + Sync + 'a> PolygonTrait<'a> for &Polygon { +impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for &Polygon { type T = T; type ItemType = LineString; type Iter = Cloned>; diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 8275351f5..86c70818f 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -42,11 +42,9 @@ where tmp } -pub(crate) fn twice_signed_ring_area_trait<'a, T>( - linestring: &'a impl LineStringTrait<'a, T = T>, -) -> T +pub(crate) fn twice_signed_ring_area_trait<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T where - T: CoordNum + SubAssign + AddAssign, + T: CoordNum, { // LineString with less than 3 points is empty, or a // single point, or is not closed. @@ -82,18 +80,18 @@ where x: linestring.coord(i).unwrap().x(), y: linestring.coord(i).unwrap().y(), }; - c1.x -= shift.x(); - c1.y -= shift.y(); + c1.x = c1.x - shift.x(); + c1.y = c1.y - shift.y(); let mut c2 = Coord { x: linestring.coord(i + 1).unwrap().x(), y: linestring.coord(i + 1).unwrap().y(), }; - c2.x -= shift.x(); - c2.y -= shift.y(); + c2.x = c2.x - shift.x(); + c2.y = c2.y - shift.y(); let line = Line::new(c1, c2); - tmp += line.determinant(); + tmp = tmp + line.determinant(); } tmp @@ -143,9 +141,9 @@ where } // Calculation of simple (no interior holes) Polygon area -pub(crate) fn get_linestring_area_trait<'a, T>(linestring: &'a impl LineStringTrait<'a, T = T>) -> T +pub(crate) fn get_linestring_area_trait<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T where - T: CoordFloat + SubAssign + AddAssign, + T: CoordFloat, { twice_signed_ring_area_trait(linestring) / (T::one() + T::one()) } @@ -197,7 +195,7 @@ where T: CoordFloat, { fn signed_area(&self) -> T { - let area = get_linestring_area(self.exterior()); + let area = get_linestring_area_trait(self.exterior()); // We could use winding order here, but that would // result in computing the shoelace formula twice. From 873575f1a09de54048f9851364d4b1e1b46a82a7 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 20:03:12 -0400 Subject: [PATCH 08/15] Fix tests --- geo/src/algorithm/area.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 86c70818f..ab1c108dd 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -75,7 +75,7 @@ where let shift = linestring.coord(0).unwrap(); let mut tmp = T::zero(); - for i in (0..linestring.num_coords()).step_by(2) { + for i in 0..linestring.num_coords() - 1 { let mut c1 = Coord { x: linestring.coord(i).unwrap().x(), y: linestring.coord(i).unwrap().y(), From 5d9ddf53eec8cb78eb9001dc4912d083f9d9674e Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 20:08:23 -0400 Subject: [PATCH 09/15] Comment out ci 1.63 --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f4b624699..0db6e3b5b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,7 +68,7 @@ jobs: # giving us about 6 months of coverage. # # Minimum supported rust version (MSRV) - - "georust/geo-ci:rust-1.63" + # - "georust/geo-ci:rust-1.63" # Two most recent releases - we omit older ones for expedient CI - "georust/geo-ci:rust-1.65" - "georust/geo-ci:rust-1.66" @@ -96,7 +96,7 @@ jobs: # giving us about 6 months of coverage. # # Minimum supported rust version (MSRV) - - "georust/geo-ci:rust-1.63" + # - "georust/geo-ci:rust-1.63" # Two most recent releases - we omit older ones for expedient CI - "georust/geo-ci:rust-1.65" - "georust/geo-ci:rust-1.66" @@ -123,7 +123,7 @@ jobs: # giving us about 6 months of coverage. # # Minimum supported rust version (MSRV) - - "georust/geo-ci:rust-1.63" + # - "georust/geo-ci:rust-1.63" # Two most recent releases - we omit older ones for expedient CI - "georust/geo-ci:rust-1.65" - "georust/geo-ci:rust-1.66" @@ -149,7 +149,7 @@ jobs: # giving us about 6 months of coverage. # # Minimum supported rust version (MSRV) - - "georust/geo-ci:rust-1.63" + # - "georust/geo-ci:rust-1.63" # Two most recent releases - we omit older ones for expedient CI - "georust/geo-ci:rust-1.65" - "georust/geo-ci:rust-1.66" From 0367c8fa1c71bad2b1e559b75de9cddfe3b6ddd8 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 20:10:12 -0400 Subject: [PATCH 10/15] Expose signed and unsigned area for a polygon --- geo/src/algorithm/area.rs | 95 +++++++++++---------------------------- 1 file changed, 27 insertions(+), 68 deletions(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index ab1c108dd..19372299a 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,48 +1,8 @@ -use std::ops::{AddAssign, SubAssign}; - use crate::geometry::*; use crate::{CoordFloat, CoordNum}; use geo_traits::{CoordTrait, LineStringTrait, PolygonTrait}; -pub(crate) fn twice_signed_ring_area(linestring: &LineString) -> T -where - T: CoordNum, -{ - // LineString with less than 3 points is empty, or a - // single point, or is not closed. - if linestring.0.len() < 3 { - return T::zero(); - } - - // Above test ensures the vector has at least 2 elements. - // We check if linestring is closed, and return 0 otherwise. - if linestring.0.first().unwrap() != linestring.0.last().unwrap() { - return T::zero(); - } - - // Use a reasonable shift for the line-string coords - // to avoid numerical-errors when summing the - // determinants. - // - // Note: we can't use the `Centroid` trait as it - // requires `T: Float` and in fact computes area in the - // implementation. Another option is to use the average - // of the coordinates, but it is not fool-proof to - // divide by the length of the linestring (eg. a long - // line-string with T = u8) - let shift = linestring.0[0]; - - let mut tmp = T::zero(); - for line in linestring.lines() { - use crate::MapCoords; - let line = line.map_coords(|c| c - shift); - tmp = tmp + line.determinant(); - } - - tmp -} - -pub(crate) fn twice_signed_ring_area_trait<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T +pub(crate) fn twice_signed_ring_area<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T where T: CoordNum, { @@ -133,21 +93,13 @@ where } // Calculation of simple (no interior holes) Polygon area -pub(crate) fn get_linestring_area(linestring: &LineString) -> T +pub(crate) fn get_linestring_area<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T where T: CoordFloat, { twice_signed_ring_area(linestring) / (T::one() + T::one()) } -// Calculation of simple (no interior holes) Polygon area -pub(crate) fn get_linestring_area_trait<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T -where - T: CoordFloat, -{ - twice_signed_ring_area_trait(linestring) / (T::one() + T::one()) -} - impl Area for Point where T: CoordNum, @@ -195,33 +147,40 @@ where T: CoordFloat, { fn signed_area(&self) -> T { - let area = get_linestring_area_trait(self.exterior()); - - // We could use winding order here, but that would - // result in computing the shoelace formula twice. - let is_negative = area < T::zero(); - - let area = self.interiors().iter().fold(area.abs(), |total, next| { - total - get_linestring_area(next).abs() - }); - - if is_negative { - -area - } else { - area - } + signed_area_polygon(self) } fn unsigned_area(&self) -> T { - self.signed_area().abs() + unsigned_area_polygon(self) } } pub fn unsigned_area_polygon<'a, T>(geom: &'a impl PolygonTrait<'a, T = T>) -> T where - T: CoordFloat + SubAssign + AddAssign, + T: CoordFloat, { - get_linestring_area_trait(&geom.exterior()).abs() + get_linestring_area(&geom.exterior()).abs() +} + +pub fn signed_area_polygon<'a, T>(geom: &'a impl PolygonTrait<'a, T = T>) -> T +where + T: CoordFloat, +{ + let area = get_linestring_area(&geom.exterior()); + + // We could use winding order here, but that would + // result in computing the shoelace formula twice. + let is_negative = area < T::zero(); + + let area = geom.interiors().fold(area.abs(), |total, next| { + total - get_linestring_area(&next).abs() + }); + + if is_negative { + -area + } else { + area + } } impl Area for MultiPoint From 2ebb574464d20a8067eb659f9d6960228d283901 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 20:12:41 -0400 Subject: [PATCH 11/15] Fix test --- geo/src/algorithm/area.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 19372299a..debc6203c 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -151,7 +151,7 @@ where } fn unsigned_area(&self) -> T { - unsigned_area_polygon(self) + self.signed_area().abs() } } From a61b5e235f7e871969565889904e5dfc9ee1f19c Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 23:05:58 -0400 Subject: [PATCH 12/15] Add parametrized type T to all trait definitions --- geo-traits/src/coord.rs | 16 +++++++------- geo-traits/src/geometry.rs | 30 ++++++++++++++------------- geo-traits/src/geometry_collection.rs | 9 +++++--- geo-traits/src/line_string.rs | 4 ++-- geo-traits/src/multi_line_string.rs | 9 +++++--- geo-traits/src/multi_point.rs | 9 +++++--- geo-traits/src/multi_polygon.rs | 4 ++-- geo-traits/src/point.rs | 24 ++++++++++----------- geo-traits/src/polygon.rs | 4 ++-- 9 files changed, 60 insertions(+), 49 deletions(-) diff --git a/geo-traits/src/coord.rs b/geo-traits/src/coord.rs index 5ad203f24..a4f82a186 100644 --- a/geo-traits/src/coord.rs +++ b/geo-traits/src/coord.rs @@ -18,11 +18,11 @@ pub trait CoordTrait { impl CoordTrait for Point { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.0.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.0.y } } @@ -30,11 +30,11 @@ impl CoordTrait for Point { impl CoordTrait for &Point { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.0.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.0.y } } @@ -42,11 +42,11 @@ impl CoordTrait for &Point { impl CoordTrait for Coord { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.y } } @@ -54,11 +54,11 @@ impl CoordTrait for Coord { impl CoordTrait for &Coord { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.y } } diff --git a/geo-traits/src/geometry.rs b/geo-traits/src/geometry.rs index 74135ad8c..59bd92323 100644 --- a/geo-traits/src/geometry.rs +++ b/geo-traits/src/geometry.rs @@ -10,13 +10,14 @@ use super::{ #[allow(clippy::type_complexity)] pub trait GeometryTrait<'a> { - 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>; + type T: CoordNum; + type Point: 'a + PointTrait; + type LineString: 'a + LineStringTrait<'a, T = Self::T>; + type Polygon: 'a + PolygonTrait<'a, T = Self::T>; + type MultiPoint: 'a + MultiPointTrait<'a, T = Self::T>; + type MultiLineString: 'a + MultiLineStringTrait<'a, T = Self::T>; + type MultiPolygon: 'a + MultiPolygonTrait<'a, T = Self::T>; + type GeometryCollection: 'a + GeometryCollectionTrait<'a, T = Self::T>; fn as_type( &'a self, @@ -53,13 +54,14 @@ where } impl<'a, T: CoordNum + 'a> GeometryTrait<'a> for Geometry { - type Point = Point; - type LineString = LineString; - type Polygon = Polygon; - type MultiPoint = MultiPoint; - type MultiLineString = MultiLineString; - type MultiPolygon = MultiPolygon; - type GeometryCollection = GeometryCollection; + type T = T; + type Point = Point; + type LineString = LineString; + type Polygon = Polygon; + type MultiPoint = MultiPoint; + type MultiLineString = MultiLineString; + type MultiPolygon = MultiPolygon; + type GeometryCollection = GeometryCollection; fn as_type( &'a self, diff --git a/geo-traits/src/geometry_collection.rs b/geo-traits/src/geometry_collection.rs index 8eb12334a..93c0cf17b 100644 --- a/geo-traits/src/geometry_collection.rs +++ b/geo-traits/src/geometry_collection.rs @@ -4,7 +4,8 @@ use std::iter::Cloned; use std::slice::Iter; pub trait GeometryCollectionTrait<'a> { - type ItemType: 'a + GeometryTrait<'a>; + type T: CoordNum; + type ItemType: 'a + GeometryTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; /// An iterator over the geometries in this GeometryCollection @@ -19,7 +20,8 @@ pub trait GeometryCollectionTrait<'a> { } impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for GeometryCollection { - type ItemType = Geometry; + type T = T; + type ItemType = Geometry; type Iter = Cloned>; fn geometries(&'a self) -> Self::Iter { @@ -36,7 +38,8 @@ impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for GeometryCollection } impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for &GeometryCollection { - type ItemType = Geometry; + type T = T; + type ItemType = Geometry; type Iter = Cloned>; fn geometries(&'a self) -> Self::Iter { diff --git a/geo-traits/src/line_string.rs b/geo-traits/src/line_string.rs index d0c6f5b32..89ac6d6e1 100644 --- a/geo-traits/src/line_string.rs +++ b/geo-traits/src/line_string.rs @@ -22,7 +22,7 @@ pub trait LineStringTrait<'a> { impl<'a, T: CoordNum + 'a> LineStringTrait<'a> for LineString { type T = T; - type ItemType = Coord; + type ItemType = Coord; type Iter = Cloned>; fn coords(&'a self) -> Self::Iter { @@ -40,7 +40,7 @@ impl<'a, T: CoordNum + 'a> LineStringTrait<'a> for LineString { impl<'a, T: CoordNum + 'a> LineStringTrait<'a> for &LineString { type T = T; - type ItemType = Coord; + type ItemType = Coord; type Iter = Cloned>; fn coords(&'a self) -> Self::Iter { diff --git a/geo-traits/src/multi_line_string.rs b/geo-traits/src/multi_line_string.rs index 0824740df..2868618e3 100644 --- a/geo-traits/src/multi_line_string.rs +++ b/geo-traits/src/multi_line_string.rs @@ -4,7 +4,8 @@ use std::iter::Cloned; use std::slice::Iter; pub trait MultiLineStringTrait<'a> { - type ItemType: 'a + LineStringTrait<'a>; + type T: CoordNum; + type ItemType: 'a + LineStringTrait<'a, T = Self::T>; type Iter: ExactSizeIterator; /// An iterator over the LineStrings in this MultiLineString @@ -19,7 +20,8 @@ pub trait MultiLineStringTrait<'a> { } impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for MultiLineString { - type ItemType = LineString; + type T = T; + type ItemType = LineString; type Iter = Cloned>; fn lines(&'a self) -> Self::Iter { @@ -36,7 +38,8 @@ impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for MultiLineString { } impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for &MultiLineString { - type ItemType = LineString; + type T = T; + type ItemType = LineString; type Iter = Cloned>; fn lines(&'a self) -> Self::Iter { diff --git a/geo-traits/src/multi_point.rs b/geo-traits/src/multi_point.rs index 3372c5a4d..0f3996374 100644 --- a/geo-traits/src/multi_point.rs +++ b/geo-traits/src/multi_point.rs @@ -4,7 +4,8 @@ use std::iter::Cloned; use std::slice::Iter; pub trait MultiPointTrait<'a> { - type ItemType: 'a + PointTrait; + type T: CoordNum; + type ItemType: 'a + PointTrait; type Iter: ExactSizeIterator; /// An iterator over the points in this MultiPoint @@ -19,7 +20,8 @@ pub trait MultiPointTrait<'a> { } impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for MultiPoint { - type ItemType = Point; + type T = T; + type ItemType = Point; type Iter = Cloned>; fn points(&'a self) -> Self::Iter { @@ -36,7 +38,8 @@ impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for MultiPoint { } impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for &MultiPoint { - type ItemType = Point; + type T = T; + type ItemType = Point; type Iter = Cloned>; fn points(&'a self) -> Self::Iter { diff --git a/geo-traits/src/multi_polygon.rs b/geo-traits/src/multi_polygon.rs index c4facf0c5..4d4461405 100644 --- a/geo-traits/src/multi_polygon.rs +++ b/geo-traits/src/multi_polygon.rs @@ -21,7 +21,7 @@ pub trait MultiPolygonTrait<'a> { impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for MultiPolygon { type T = T; - type ItemType = Polygon; + type ItemType = Polygon; type Iter = Cloned>; fn polygons(&'a self) -> Self::Iter { @@ -39,7 +39,7 @@ impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for MultiPolygon { impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for &MultiPolygon { type T = T; - type ItemType = Polygon; + type ItemType = Polygon; type Iter = Cloned>; fn polygons(&'a self) -> Self::Iter { diff --git a/geo-traits/src/point.rs b/geo-traits/src/point.rs index e9bac5686..e77cebb8b 100644 --- a/geo-traits/src/point.rs +++ b/geo-traits/src/point.rs @@ -16,15 +16,15 @@ pub trait PointTrait { impl PointTrait for Point { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.0.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.0.y } - fn x_y(&self) -> (T, T) { + fn x_y(&self) -> (Self::T, Self::T) { (self.0.x, self.0.y) } } @@ -32,15 +32,15 @@ impl PointTrait for Point { impl PointTrait for &Point { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.0.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.0.y } - fn x_y(&self) -> (T, T) { + fn x_y(&self) -> (Self::T, Self::T) { (self.0.x, self.0.y) } } @@ -48,15 +48,15 @@ impl PointTrait for &Point { impl PointTrait for Coord { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.y } - fn x_y(&self) -> (T, T) { + fn x_y(&self) -> (Self::T, Self::T) { (self.x, self.y) } } @@ -64,15 +64,15 @@ impl PointTrait for Coord { impl PointTrait for &Coord { type T = T; - fn x(&self) -> T { + fn x(&self) -> Self::T { self.x } - fn y(&self) -> T { + fn y(&self) -> Self::T { self.y } - fn x_y(&self) -> (T, T) { + fn x_y(&self) -> (Self::T, Self::T) { (self.x, self.y) } } diff --git a/geo-traits/src/polygon.rs b/geo-traits/src/polygon.rs index 2863c0c36..01e543e9d 100644 --- a/geo-traits/src/polygon.rs +++ b/geo-traits/src/polygon.rs @@ -24,7 +24,7 @@ pub trait PolygonTrait<'a> { impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { type T = T; - type ItemType = LineString; + type ItemType = LineString; type Iter = Cloned>; fn exterior(&'a self) -> Self::ItemType { @@ -46,7 +46,7 @@ impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for &Polygon { type T = T; - type ItemType = LineString; + type ItemType = LineString; type Iter = Cloned>; fn exterior(&'a self) -> Self::ItemType { From 82640838c2264ae781bececdf0fadc4f36bc9d84 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 23:21:49 -0400 Subject: [PATCH 13/15] Try to add signed_area_geometry --- geo/src/algorithm/area.rs | 94 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index debc6203c..9e3feeb58 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -1,6 +1,9 @@ use crate::geometry::*; use crate::{CoordFloat, CoordNum}; -use geo_traits::{CoordTrait, LineStringTrait, PolygonTrait}; +use geo_traits::{ + CoordTrait, GeometryCollectionTrait, GeometryTrait, GeometryType, LineStringTrait, + MultiPolygonTrait, PointTrait, PolygonTrait, +}; pub(crate) fn twice_signed_ring_area<'a, T>(linestring: &impl LineStringTrait<'a, T = T>) -> T where @@ -100,29 +103,57 @@ where twice_signed_ring_area(linestring) / (T::one() + T::one()) } +pub fn unsigned_area_point(_geom: &impl PointTrait) -> T +where + T: CoordNum, +{ + T::zero() +} + +pub fn signed_area_point(_geom: &impl PointTrait) -> T +where + T: CoordNum, +{ + T::zero() +} + impl Area for Point where T: CoordNum, { fn signed_area(&self) -> T { - T::zero() + signed_area_point(self) } fn unsigned_area(&self) -> T { - T::zero() + unsigned_area_point(self) } } +pub fn unsigned_area_line_string<'a, T>(_geom: &impl LineStringTrait<'a, T = T>) -> T +where + T: CoordNum, +{ + T::zero() +} + +pub fn signed_area_line_string<'a, T>(_geom: &impl LineStringTrait<'a, T = T>) -> T +where + T: CoordNum, +{ + T::zero() +} + impl Area for LineString where T: CoordNum, { fn signed_area(&self) -> T { - T::zero() + signed_area_line_string(self) } fn unsigned_area(&self) -> T { - T::zero() + unsigned_area_line_string(self) } } @@ -209,6 +240,23 @@ where } } +pub fn unsigned_area_multi_polygon<'a, T>(geom: &'a impl MultiPolygonTrait<'a, T = T>) -> T +where + T: CoordFloat, +{ + geom.polygons().fold(T::zero(), |total, next| { + total + unsigned_area_polygon(&next) + }) +} + +pub fn signed_area_multi_polygon<'a, T>(geom: &'a impl MultiPolygonTrait<'a, T = T>) -> T +where + T: CoordFloat, +{ + geom.polygons() + .fold(T::zero(), |total, next| total + signed_area_polygon(&next)) +} + /// **Note.** The implementation is a straight-forward /// summation of the signed areas of the individual /// polygons. In particular, `unsigned_area` is not @@ -262,6 +310,42 @@ where } } +pub fn unsigned_area_geometry<'a, T, G>(geom: &'a G) -> T +where + T: CoordFloat, + G: GeometryTrait<'a, T = T>, +{ + match geom.as_type() { + GeometryType::Point(g) => unsigned_area_point(g), + GeometryType::MultiPoint(g) => T::zero(), + GeometryType::LineString(g) => T::zero(), + GeometryType::MultiLineString(g) => T::zero(), + GeometryType::Polygon(g) => signed_area_polygon(g).abs(), + GeometryType::MultiPolygon(g) => todo!(), + GeometryType::GeometryCollection(g) => g.geometries().fold(T::zero(), |total, next| { + total + unsigned_area_geometry(&next) + }), + } +} + +pub fn signed_area_geometry<'a, T, G>(geom: &'a G) -> T +where + T: CoordFloat, + G: GeometryTrait<'a, T = T>, +{ + match geom.as_type() { + GeometryType::Point(g) => signed_area_point(g), + GeometryType::MultiPoint(g) => T::zero(), + GeometryType::LineString(g) => T::zero(), + GeometryType::MultiLineString(g) => T::zero(), + GeometryType::Polygon(g) => signed_area_polygon(g), + GeometryType::MultiPolygon(g) => todo!(), + GeometryType::GeometryCollection(g) => g.geometries().fold(T::zero(), |total, next| { + total + signed_area_geometry(&next) + }), + } +} + impl Area for Geometry where T: CoordFloat, From c3ae4d53d8cd99f1b72eb143e37e7ca7f6fbf1f7 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 23:51:36 -0400 Subject: [PATCH 14/15] Remove 'a lifetime on non-iterating trait methods --- geo-traits/src/geometry.rs | 14 +++++++------- geo-traits/src/geometry_collection.rs | 12 ++++++------ geo-traits/src/multi_line_string.rs | 12 ++++++------ geo-traits/src/multi_point.rs | 8 ++++---- geo-traits/src/multi_polygon.rs | 12 ++++++------ geo-traits/src/polygon.rs | 18 +++++++++--------- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/geo-traits/src/geometry.rs b/geo-traits/src/geometry.rs index 59bd92323..1c2395179 100644 --- a/geo-traits/src/geometry.rs +++ b/geo-traits/src/geometry.rs @@ -36,13 +36,13 @@ pub trait GeometryTrait<'a> { #[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>, + P: PointTrait, + L: LineStringTrait<'a>, + Y: PolygonTrait<'a>, + MP: MultiPointTrait<'a>, + ML: MultiLineStringTrait<'a>, + MY: MultiPolygonTrait<'a>, + GC: GeometryCollectionTrait<'a>, { Point(&'a P), LineString(&'a L), diff --git a/geo-traits/src/geometry_collection.rs b/geo-traits/src/geometry_collection.rs index 93c0cf17b..f6f5dd0ed 100644 --- a/geo-traits/src/geometry_collection.rs +++ b/geo-traits/src/geometry_collection.rs @@ -12,11 +12,11 @@ pub trait GeometryCollectionTrait<'a> { fn geometries(&'a self) -> Self::Iter; /// The number of geometries in this GeometryCollection - fn num_geometries(&'a self) -> usize; + fn num_geometries(&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; + fn geometry(&self, i: usize) -> Option; } impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for GeometryCollection { @@ -28,11 +28,11 @@ impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for GeometryCollection self.0.iter().cloned() } - fn num_geometries(&'a self) -> usize { + fn num_geometries(&self) -> usize { self.0.len() } - fn geometry(&'a self, i: usize) -> Option { + fn geometry(&self, i: usize) -> Option { self.0.get(i).cloned() } } @@ -46,11 +46,11 @@ impl<'a, T: CoordNum + 'a> GeometryCollectionTrait<'a> for &GeometryCollection usize { + fn num_geometries(&self) -> usize { self.0.len() } - fn geometry(&'a self, i: usize) -> Option { + fn geometry(&self, i: usize) -> Option { self.0.get(i).cloned() } } diff --git a/geo-traits/src/multi_line_string.rs b/geo-traits/src/multi_line_string.rs index 2868618e3..fa9e0b18b 100644 --- a/geo-traits/src/multi_line_string.rs +++ b/geo-traits/src/multi_line_string.rs @@ -12,11 +12,11 @@ pub trait MultiLineStringTrait<'a> { fn lines(&'a self) -> Self::Iter; /// The number of lines in this MultiLineString - fn num_lines(&'a self) -> usize; + fn num_lines(&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; + fn line(&self, i: usize) -> Option; } impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for MultiLineString { @@ -28,11 +28,11 @@ impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for MultiLineString { self.0.iter().cloned() } - fn num_lines(&'a self) -> usize { + fn num_lines(&self) -> usize { self.0.len() } - fn line(&'a self, i: usize) -> Option { + fn line(&self, i: usize) -> Option { self.0.get(i).cloned() } } @@ -46,11 +46,11 @@ impl<'a, T: CoordNum + 'a> MultiLineStringTrait<'a> for &MultiLineString { self.0.iter().cloned() } - fn num_lines(&'a self) -> usize { + fn num_lines(&self) -> usize { self.0.len() } - fn line(&'a self, i: usize) -> Option { + fn line(&self, i: usize) -> Option { self.0.get(i).cloned() } } diff --git a/geo-traits/src/multi_point.rs b/geo-traits/src/multi_point.rs index 0f3996374..798579ed5 100644 --- a/geo-traits/src/multi_point.rs +++ b/geo-traits/src/multi_point.rs @@ -12,11 +12,11 @@ pub trait MultiPointTrait<'a> { fn points(&'a self) -> Self::Iter; /// The number of points in this MultiPoint - fn num_points(&'a self) -> usize; + fn num_points(&self) -> usize; /// Access to a specified point in this MultiPoint /// Will return None if the provided index is out of bounds - fn point(&'a self, i: usize) -> Option; + fn point(&self, i: usize) -> Option; } impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for MultiPoint { @@ -32,7 +32,7 @@ impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for MultiPoint { self.0.len() } - fn point(&'a self, i: usize) -> Option { + fn point(&self, i: usize) -> Option { self.0.get(i).cloned() } } @@ -50,7 +50,7 @@ impl<'a, T: CoordNum + 'a> MultiPointTrait<'a> for &MultiPoint { self.0.len() } - fn point(&'a self, i: usize) -> Option { + fn point(&self, i: usize) -> Option { self.0.get(i).cloned() } } diff --git a/geo-traits/src/multi_polygon.rs b/geo-traits/src/multi_polygon.rs index 4d4461405..11d14dc5f 100644 --- a/geo-traits/src/multi_polygon.rs +++ b/geo-traits/src/multi_polygon.rs @@ -12,11 +12,11 @@ pub trait MultiPolygonTrait<'a> { fn polygons(&'a self) -> Self::Iter; /// The number of polygons in this MultiPolygon - fn num_polygons(&'a self) -> usize; + fn num_polygons(&self) -> usize; /// Access to a specified polygon in this MultiPolygon /// Will return None if the provided index is out of bounds - fn polygon(&'a self, i: usize) -> Option; + fn polygon(&self, i: usize) -> Option; } impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for MultiPolygon { @@ -28,11 +28,11 @@ impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for MultiPolygon { self.0.iter().cloned() } - fn num_polygons(&'a self) -> usize { + fn num_polygons(&self) -> usize { self.0.len() } - fn polygon(&'a self, i: usize) -> Option { + fn polygon(&self, i: usize) -> Option { self.0.get(i).cloned() } } @@ -46,11 +46,11 @@ impl<'a, T: CoordNum + 'a> MultiPolygonTrait<'a> for &MultiPolygon { self.0.iter().cloned() } - fn num_polygons(&'a self) -> usize { + fn num_polygons(&self) -> usize { self.0.len() } - fn polygon(&'a self, i: usize) -> Option { + fn polygon(&self, i: usize) -> Option { self.0.get(i).cloned() } } diff --git a/geo-traits/src/polygon.rs b/geo-traits/src/polygon.rs index 01e543e9d..e8a528a4e 100644 --- a/geo-traits/src/polygon.rs +++ b/geo-traits/src/polygon.rs @@ -9,17 +9,17 @@ pub trait PolygonTrait<'a> { type Iter: ExactSizeIterator; /// The exterior ring of the polygon - fn exterior(&'a self) -> Self::ItemType; + fn exterior(&self) -> Self::ItemType; /// An iterator of the interior rings of this Polygon fn interiors(&'a self) -> Self::Iter; /// The number of interior rings in this Polygon - fn num_interiors(&'a self) -> usize; + fn num_interiors(&self) -> usize; /// Access to a specified interior ring in this Polygon /// Will return None if the provided index is out of bounds - fn interior(&'a self, i: usize) -> Option; + fn interior(&self, i: usize) -> Option; } impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { @@ -27,7 +27,7 @@ impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { type ItemType = LineString; type Iter = Cloned>; - fn exterior(&'a self) -> Self::ItemType { + fn exterior(&self) -> Self::ItemType { Polygon::exterior(self).clone() } @@ -35,11 +35,11 @@ impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for Polygon { Polygon::interiors(self).iter().cloned() } - fn num_interiors(&'a self) -> usize { + fn num_interiors(&self) -> usize { Polygon::interiors(self).len() } - fn interior(&'a self, i: usize) -> Option { + fn interior(&self, i: usize) -> Option { Polygon::interiors(self).get(i).cloned() } } @@ -49,7 +49,7 @@ impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for &Polygon { type ItemType = LineString; type Iter = Cloned>; - fn exterior(&'a self) -> Self::ItemType { + fn exterior(&self) -> Self::ItemType { Polygon::exterior(self).clone() } @@ -57,11 +57,11 @@ impl<'a, T: CoordNum + 'a> PolygonTrait<'a> for &Polygon { Polygon::interiors(self).iter().cloned() } - fn num_interiors(&'a self) -> usize { + fn num_interiors(&self) -> usize { Polygon::interiors(self).len() } - fn interior(&'a self, i: usize) -> Option { + fn interior(&self, i: usize) -> Option { Polygon::interiors(self).get(i).cloned() } } From bfd1c6da619d8d87737aab6aa3892dc5c3afcd9c Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 26 Jun 2023 23:51:54 -0400 Subject: [PATCH 15/15] Get multi polygon methods to compile --- geo/src/algorithm/area.rs | 47 ++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index 9e3feeb58..10d8e2d89 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -186,14 +186,14 @@ where } } -pub fn unsigned_area_polygon<'a, T>(geom: &'a impl PolygonTrait<'a, T = T>) -> T +pub fn unsigned_area_polygon<'a, T>(geom: &impl PolygonTrait<'a, T = T>) -> T where T: CoordFloat, { get_linestring_area(&geom.exterior()).abs() } -pub fn signed_area_polygon<'a, T>(geom: &'a impl PolygonTrait<'a, T = T>) -> T +pub fn signed_area_polygon<'a, T>(geom: &impl PolygonTrait<'a, T = T>) -> T where T: CoordFloat, { @@ -203,14 +203,16 @@ where // result in computing the shoelace formula twice. let is_negative = area < T::zero(); - let area = geom.interiors().fold(area.abs(), |total, next| { - total - get_linestring_area(&next).abs() - }); + let mut total = area.abs(); + for interior_i in 0..geom.num_interiors() { + let interior_geom = geom.interior(interior_i).unwrap(); + total = total - get_linestring_area(&interior_geom).abs(); + } if is_negative { - -area + -total } else { - area + total } } @@ -240,21 +242,30 @@ where } } -pub fn unsigned_area_multi_polygon<'a, T>(geom: &'a impl MultiPolygonTrait<'a, T = T>) -> T +pub fn unsigned_area_multi_polygon<'a, T>(geom: &impl MultiPolygonTrait<'a, T = T>) -> T where T: CoordFloat, { - geom.polygons().fold(T::zero(), |total, next| { - total + unsigned_area_polygon(&next) - }) + let mut total = T::zero(); + for polygon_idx in 0..geom.num_polygons() { + let polygon = geom.polygon(polygon_idx).unwrap(); + total = total + signed_area_polygon(&polygon).abs(); + } + + total } -pub fn signed_area_multi_polygon<'a, T>(geom: &'a impl MultiPolygonTrait<'a, T = T>) -> T +pub fn signed_area_multi_polygon<'a, T>(geom: &impl MultiPolygonTrait<'a, T = T>) -> T where T: CoordFloat, { - geom.polygons() - .fold(T::zero(), |total, next| total + signed_area_polygon(&next)) + let mut total = T::zero(); + for polygon_idx in 0..geom.num_polygons() { + let polygon = geom.polygon(polygon_idx).unwrap(); + total = total + signed_area_polygon(&polygon); + } + + total } /// **Note.** The implementation is a straight-forward @@ -310,7 +321,7 @@ where } } -pub fn unsigned_area_geometry<'a, T, G>(geom: &'a G) -> T +pub fn unsigned_area_geometry<'a, T, G>(geom: &G) -> T where T: CoordFloat, G: GeometryTrait<'a, T = T>, @@ -340,9 +351,9 @@ where GeometryType::MultiLineString(g) => T::zero(), GeometryType::Polygon(g) => signed_area_polygon(g), GeometryType::MultiPolygon(g) => todo!(), - GeometryType::GeometryCollection(g) => g.geometries().fold(T::zero(), |total, next| { - total + signed_area_geometry(&next) - }), + GeometryType::GeometryCollection(g) => g + .geometries() + .fold(T::zero(), |total, next| total + signed_area_geometry(&next)), } }