From 3bdd5d549a12a2155bffef37fd85e85dcfe1e344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Tue, 11 Jun 2024 12:37:25 +0200 Subject: [PATCH] allow obstacles to overlap the exterior edge of the triangulation (#53) --- src/input/triangulation.rs | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/input/triangulation.rs b/src/input/triangulation.rs index ce06df8..3bf769e 100644 --- a/src/input/triangulation.rs +++ b/src/input/triangulation.rs @@ -70,7 +70,7 @@ impl Triangulation { /// otherwise it will fail. #[cfg_attr(feature = "tracing", instrument(skip_all))] pub fn merge_overlapping_obstacles(&mut self) { - let (exterior, interiors) = + let (mut exterior, interiors) = std::mem::replace(&mut self.inner, GeoPolygon::new(LineString(vec![]), vec![])) .into_inner(); @@ -83,8 +83,8 @@ impl Triangulation { .map(|(i, _)| i) .collect::>(); - if intersecting.is_empty() { - not_intersecting.push(poly); + let to_keep = if intersecting.is_empty() { + poly } else { #[cfg(feature = "tracing")] let _merging_span = tracing::info_span!("merging polygons").entered(); @@ -97,9 +97,34 @@ impl Triangulation { .collect(), ); merged = merged.union(&GeoPolygon::new(poly, vec![]).into()); - not_intersecting.push(LineString( - merged.exterior_coords_iter().collect::>(), - )); + LineString(merged.exterior_coords_iter().collect::>()) + }; + + if to_keep.intersects(&exterior) { + let new_exterior = + GeoPolygon::new(exterior, vec![]).difference(&GeoPolygon::new(to_keep, vec![])); + // Keep the biggest of the new exterior polygons + if new_exterior.0.len() > 1 { + let mut biggest = 0; + let mut biggest_length = 0; + for (i, poly) in new_exterior.0.iter().enumerate() { + let exterior_length = poly.exterior_coords_iter().len(); + if exterior_length > biggest_length { + biggest = i; + biggest_length = exterior_length; + } + } + exterior = LineString( + new_exterior.0[biggest] + .exterior_coords_iter() + .collect::>(), + ); + } else { + exterior = + LineString(new_exterior.0[0].exterior_coords_iter().collect::>()); + } + } else { + not_intersecting.push(to_keep); } }