From cfce345e1b3045762a93f4b4cdd9f5dc69f70ab2 Mon Sep 17 00:00:00 2001 From: Ravi Peters Date: Mon, 20 Jan 2025 18:08:52 +0100 Subject: [PATCH] Handle edge case when a multypolygon is created after GEOSSimplify --- apps/roofer-app/roofer-app.cpp | 1 + src/extra/misc/Vector2DOpsGEOS.cpp | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/apps/roofer-app/roofer-app.cpp b/apps/roofer-app/roofer-app.cpp index 9bdcc76e..eef1566c 100644 --- a/apps/roofer-app/roofer-app.cpp +++ b/apps/roofer-app/roofer-app.cpp @@ -970,6 +970,7 @@ int main(int argc, const char* argv[]) { } } sorting_running.store(false); + sorted_pending.notify_one(); logger.debug("[sorter] Finished sorter"); }); diff --git a/src/extra/misc/Vector2DOpsGEOS.cpp b/src/extra/misc/Vector2DOpsGEOS.cpp index c8d9fd9b..a413af2f 100644 --- a/src/extra/misc/Vector2DOpsGEOS.cpp +++ b/src/extra/misc/Vector2DOpsGEOS.cpp @@ -22,6 +22,7 @@ #include #include +#include <__config> #include #include @@ -48,6 +49,8 @@ namespace roofer::misc { } bool orient_polygon(GEOSGeometry*& g_polygon, ORIENTATION orientation) { const GEOSGeometry* g_ring = GEOSGetExteriorRing_r(gc, g_polygon); + if (g_ring == nullptr) + throw std::runtime_error("orient_polygon: unable to get exterior ring"); GEOSGeometry* g_ring_ = orient_ring(g_ring, orientation); bool reversed = false; if (!g_ring_) { @@ -212,19 +215,35 @@ namespace roofer::misc { to_geos_polygon(lr, g_polygon); if (GEOSisValid_r(gc, g_polygon) != 1) { - logger.info("feature not valid"); + logger.error("Encouterend feature that is not valid. WKT: {}", + GEOSGeomToWKT_r(gc, g_polygon)); GEOSGeom_destroy_r(gc, g_polygon); // if (output_failures) polygons_out.push_back(lr); - continue; + throw std::runtime_error("feature not valid"); } GEOSGeometry* simplified_geom = GEOSSimplify_r(gc, g_polygon, double(tolerance)); if (GEOSisValid_r(gc, simplified_geom) != 1) { - logger.info("feature not valid after simplify"); + logger.error( + "Encouterend feature that is not valid after simplify. WKT: {}", + GEOSGeomToWKT_r(gc, simplified_geom)); GEOSGeom_destroy_r(gc, g_polygon); + GEOSGeom_destroy_r(gc, simplified_geom); // if (output_failures) polygons_out.push_back(lr); - continue; + throw std::runtime_error("feature not valid after simplify"); + } + // dump simplified geometry to wkt + if (GEOSGetNumGeometries_r(gc, simplified_geom) != 1) { + logger.error( + "Encouterend feature that is a multi-geometry after simplify. " + "WKT: {}", + GEOSGeomToWKT_r(gc, simplified_geom)); + GEOSGeom_destroy_r(gc, g_polygon); + GEOSGeom_destroy_r(gc, simplified_geom); + // if (output_failures) polygons_out.push_back(lr); + throw std::runtime_error( + "feature has multiple geometries after simplify"); } if (orient_after_simplify) orient_polygon(simplified_geom, CCW);