diff --git a/geo/src/algorithm/relate/geomgraph/edge_end_bundle_star.rs b/geo/src/algorithm/relate/geomgraph/edge_end_bundle_star.rs index 46d289d7b..fdf33a9ba 100644 --- a/geo/src/algorithm/relate/geomgraph/edge_end_bundle_star.rs +++ b/geo/src/algorithm/relate/geomgraph/edge_end_bundle_star.rs @@ -41,8 +41,8 @@ impl LabeledEdgeEndBundleStar { /// Compute a label for the star based on the labels of its EdgeEndBundles. fn compute_labeling(&mut self, graph_a: &GeometryGraph, graph_b: &GeometryGraph) { - self.propagate_side_labels(0); - self.propagate_side_labels(1); + self.propagate_side_labels(0, graph_a); + self.propagate_side_labels(1, graph_b); let mut has_dimensional_collapse_edge = [false, false]; for edge_end in self.edges.iter() { let label = edge_end.label(); @@ -83,7 +83,7 @@ impl LabeledEdgeEndBundleStar { debug!("edge_end_bundle_star: {:?}", self); } - fn propagate_side_labels(&mut self, geom_index: usize) { + fn propagate_side_labels(&mut self, geom_index: usize, geometry_graph: &GeometryGraph) { let mut start_position = None; for edge_ends in self.edge_end_bundles_iter() { @@ -109,7 +109,15 @@ impl LabeledEdgeEndBundleStar { let right_position = label.position(geom_index, Direction::Right); if let Some(right_position) = right_position { - debug_assert!(right_position == current_position, "side_location conflict with coordinate: {:?}, right_location: {:?}, current_location: {:?}", edge_ends.coordinate(), right_position, current_position); + #[cfg(debug_assertions)] + if right_position != current_position { + use crate::algorithm::Validation; + if geometry_graph.geometry().is_valid() { + debug_assert!(false, "topology position conflict with coordinate — this can happen with invalid geometries. coordinate: {:?}, right_location: {:?}, current_location: {:?}", edge_ends.coordinate(), right_position, current_position); + } else { + warn!("topology position conflict with coordinate — this can happen with invalid geometries. coordinate: {:?}, right_location: {:?}, current_location: {:?}", edge_ends.coordinate(), right_position, current_position); + } + } assert!(left_position.is_some(), "found single null side"); current_position = left_position.unwrap(); } else { diff --git a/geo/src/algorithm/validation/geometry.rs b/geo/src/algorithm/validation/geometry.rs index be3982cc1..d3f21fef7 100644 --- a/geo/src/algorithm/validation/geometry.rs +++ b/geo/src/algorithm/validation/geometry.rs @@ -6,6 +6,7 @@ use super::{ }; use crate::{GeoFloat, Geometry}; +use crate::geometry_cow::GeometryCow; use std::fmt; /// A [`Geometry`] is valid if it's inner variant is valid. @@ -83,3 +84,46 @@ impl Validation for Geometry { Ok(()) } } + +impl Validation for GeometryCow<'_, F> { + type Error = InvalidGeometry; + + fn visit_validation( + &self, + mut handle_validation_error: Box Result<(), T> + '_>, + ) -> Result<(), T> { + match self { + GeometryCow::Point(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidPoint(err)) + }))?, + GeometryCow::Line(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidLine(err)) + }))?, + GeometryCow::LineString(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidLineString(err)) + }))?, + GeometryCow::Polygon(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidPolygon(err)) + }))?, + GeometryCow::MultiPoint(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidMultiPoint(err)) + }))?, + GeometryCow::MultiLineString(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidMultiLineString(err)) + }))?, + GeometryCow::MultiPolygon(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidMultiPolygon(err)) + }))?, + GeometryCow::GeometryCollection(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidGeometryCollection(err)) + }))?, + GeometryCow::Rect(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidRect(err)) + }))?, + GeometryCow::Triangle(g) => g.visit_validation(Box::new(|err| { + handle_validation_error(InvalidGeometry::InvalidTriangle(err)) + }))?, + } + Ok(()) + } +}