From 39a2f62e88f0976109b4442cef1f77eec3442107 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 2 Nov 2024 13:35:33 -0700 Subject: [PATCH] WIP: add support for multipolygon --- geo-types/src/geometry/multi_polygon.rs | 39 +++++++++++++++++++++++++ geo/src/algorithm/bool_ops/mod.rs | 8 ++--- geo/src/algorithm/bool_ops/tests.rs | 14 +++++++-- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/geo-types/src/geometry/multi_polygon.rs b/geo-types/src/geometry/multi_polygon.rs index 8a0b7d2005..b42f926fa9 100644 --- a/geo-types/src/geometry/multi_polygon.rs +++ b/geo-types/src/geometry/multi_polygon.rs @@ -170,6 +170,45 @@ where } } +#[cfg(any( + feature = "rstar_0_8", + feature = "rstar_0_9", + feature = "rstar_0_10", + feature = "rstar_0_11", + feature = "rstar_0_12" +))] +macro_rules! impl_rstar_multi_polygon { + ($rstar:ident) => { + impl $rstar::RTreeObject for MultiPolygon + where + T: ::num_traits::Float + ::$rstar::RTreeNum, + { + type Envelope = ::$rstar::AABB<$crate::Point>; + + fn envelope(&self) -> Self::Envelope { + use ::$rstar::Envelope; + self.iter() + .map(|p| p.envelope()) + .fold(::$rstar::AABB::new_empty(), |a, b| a.merged(&b)) + } + } + }; +} +#[cfg(feature = "rstar_0_8")] +impl_rstar_multi_polygon!(rstar_0_8); + +#[cfg(feature = "rstar_0_9")] +impl_rstar_multi_polygon!(rstar_0_9); + +#[cfg(feature = "rstar_0_10")] +impl_rstar_multi_polygon!(rstar_0_10); + +#[cfg(feature = "rstar_0_11")] +impl_rstar_multi_polygon!(rstar_0_11); + +#[cfg(feature = "rstar_0_12")] +impl_rstar_multi_polygon!(rstar_0_12); + #[cfg(test)] mod test { use super::*; diff --git a/geo/src/algorithm/bool_ops/mod.rs b/geo/src/algorithm/bool_ops/mod.rs index 81d4b13081..c6e2dd0cbc 100644 --- a/geo/src/algorithm/bool_ops/mod.rs +++ b/geo/src/algorithm/bool_ops/mod.rs @@ -226,18 +226,18 @@ impl BooleanOps for MultiPolygon { } /// Allows the unary union operation to be performed on any container which can produce items of type `Polygon` -impl UnaryUnion for Container +impl UnaryUnion for BoppableCollection where T: BoolOpsNum, - Container: IntoIterator> + Clone, - Polygon: RTreeObject, + Boppable: BooleanOps + RTreeObject, + BoppableCollection: IntoIterator + Clone, { type Scalar = T; fn unary_union(&self) -> MultiPolygon { // these three functions drive the union operation let init = || MultiPolygon::::new(vec![]); - let fold = |mut accum: MultiPolygon, poly: &Polygon| -> MultiPolygon { + let fold = |mut accum: MultiPolygon, poly: &Boppable| -> MultiPolygon { accum = accum.union(poly); accum }; diff --git a/geo/src/algorithm/bool_ops/tests.rs b/geo/src/algorithm/bool_ops/tests.rs index d125bc3f68..8d6abd62b6 100644 --- a/geo/src/algorithm/bool_ops/tests.rs +++ b/geo/src/algorithm/bool_ops/tests.rs @@ -7,9 +7,17 @@ fn test_unary_union() { let poly2: Polygon = wkt!(POLYGON((210.0 290.0,204.07584923592933 288.2701221108328,212.24082541367974 285.47846008552216,210.0 290.0))); let poly3: Polygon = wkt!(POLYGON((211.0 292.0,204.07584923592933 288.2701221108328,212.24082541367974 285.47846008552216,210.0 290.0))); - let polys = vec![poly1, poly2, poly3]; - let res = polys.unary_union(); - assert_eq!(res.0.len(), 1); + let polys = vec![poly1.clone(), poly2.clone(), poly3.clone()]; + let poly_union = polys.unary_union(); + assert_eq!(poly_union.0.len(), 1); + + let multi_poly_1 = MultiPolygon::new(vec![poly1, poly2]); + let multi_poly_2 = MultiPolygon::new(vec![poly3]); + let multi_polys = vec![multi_poly_1, multi_poly_2]; + let multi_poly_union = multi_polys.unary_union(); + // FIXME: This should be 1, same as poly_union, right? + assert_eq!(multi_poly_union.0.len(), 1); + assert_eq!(poly_union, multi_poly_union); } #[test]