From 1b6618cb15918287b576948d65c6fdd6cd462aed Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 08:14:40 -0400 Subject: [PATCH 1/6] add detailed jts debugging info --- .../onthegomap/planetiler/FeatureMerge.java | 28 +++++++++++++++---- .../planetiler/collection/FeatureGroup.java | 2 +- .../planetiler/config/PlanetilerConfig.java | 6 ++-- .../planetiler/geo/GeometryException.java | 18 ++++++++++++ 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index d272cf11eb..650e69649f 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.function.Function; +import org.geotools.geometry.jts.WKTWriter2; import org.locationtech.jts.algorithm.Area; import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Envelope; @@ -28,6 +29,7 @@ import org.locationtech.jts.geom.LinearRing; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.Polygonal; +import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.index.strtree.STRtree; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; @@ -410,7 +412,7 @@ public static Collection> groupByAttrs( * Merges nearby polygons by expanding each individual polygon by {@code buffer}, unioning them, and contracting the * result. */ - private static Geometry bufferUnionUnbuffer(double buffer, List polygonGroup) { + private static Geometry bufferUnionUnbuffer(double buffer, List polygonGroup) throws GeometryException { /* * A simpler alternative that might initially appear faster would be: * @@ -424,11 +426,27 @@ private static Geometry bufferUnionUnbuffer(double buffer, List polygo * The following approach is slower most of the time, but faster on average because it does * not choke on dense nearby polygons: */ - for (int i = 0; i < polygonGroup.size(); i++) { - polygonGroup.set(i, buffer(buffer, polygonGroup.get(i))); + List buffered = new ArrayList<>(polygonGroup.size()); + for (Geometry geometry : polygonGroup) { + buffered.add(buffer(buffer, geometry)); + } + Geometry merged = GeoUtils.createGeometryCollection(buffered); + try { + merged = union(merged); + } catch (TopologyException e) { + throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e).addDetails(() -> { + var wktWriter = new WKTWriter2(); + return """ + Original polygons: %s + Buffer: %f + Buffered: %s + """.formatted( + wktWriter.write(GeoUtils.createGeometryCollection(polygonGroup)), + buffer, + wktWriter.write(GeoUtils.createGeometryCollection(buffered)) + ); + }); } - Geometry merged = GeoUtils.createGeometryCollection(polygonGroup); - merged = union(merged); merged = unbuffer(buffer, merged); return merged; } diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java index 058b3a4218..dfb3fa1141 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java @@ -488,7 +488,7 @@ private void postProcessAndAddLayerFeatures(VectorTile encoder, String layer, // log failures, only throwing when it's a fatal error if (e instanceof GeometryException geoe) { geoe.log(stats, "postprocess_layer", - "Caught error postprocessing features for " + layer + " layer on " + tileCoord); + "Caught error postprocessing features for " + layer + " layer on " + tileCoord, config.logJtsExceptions()); } else if (e instanceof Error err) { LOGGER.error("Caught fatal error postprocessing features {} {}", layer, tileCoord, e); throw err; diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/config/PlanetilerConfig.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/config/PlanetilerConfig.java index 0ca347041d..b9a1463024 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/config/PlanetilerConfig.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/config/PlanetilerConfig.java @@ -58,7 +58,8 @@ public record PlanetilerConfig( String debugUrlPattern, Path tmpDir, Path tileWeights, - double maxPointBuffer + double maxPointBuffer, + boolean logJtsExceptions ) { public static final int MIN_MINZOOM = 0; @@ -208,7 +209,8 @@ public static PlanetilerConfig from(Arguments arguments) { "Max tile pixels to include points outside tile bounds. Set to a lower value to reduce tile size for " + "clients that handle label collisions across tiles (most web and native clients). NOTE: Do not reduce if you need to support " + "raster tile rendering", - Double.POSITIVE_INFINITY) + Double.POSITIVE_INFINITY), + arguments.getBoolean("log_jts_exceptions", "Emit verbose details to debug JTS geometry errors", false) ); } diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java index 765bdc91d7..1e89224313 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java @@ -1,6 +1,7 @@ package com.onthegomap.planetiler.geo; import com.onthegomap.planetiler.stats.Stats; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +15,7 @@ public class GeometryException extends Exception { private final String stat; private final boolean nonFatal; + private Supplier detailsSupplier; /** * Constructs a new exception with a detailed error message caused by {@code cause}. @@ -51,6 +53,11 @@ public GeometryException(String stat, String message, boolean nonFatal) { this.nonFatal = nonFatal; } + public GeometryException addDetails(Supplier detailsSupplier) { + this.detailsSupplier = detailsSupplier; + return this; + } + /** Returns the unique code for this error condition to use for counting the number of occurrences in stats. */ public String stat() { return stat; @@ -72,6 +79,17 @@ void logMessage(String log) { assert nonFatal : log; // make unit tests fail if fatal } + + /** Logs the error but if {@code logDetails} is true, then also prints detailed debugging info. */ + public void log(Stats stats, String statPrefix, String logPrefix, boolean logDetails) { + if (logDetails && detailsSupplier != null) { + stats.dataError(statPrefix + "_" + stat()); + logMessage(logPrefix + ": " + getMessage() + "\n" + detailsSupplier.get()); + } else { + log(stats, statPrefix, logPrefix); + } + } + /** * An error that we expect to encounter often so should only be logged at {@code TRACE} level. */ From c8b998ce8768eff7c36d3f6aaf2a39b423116726 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 08:24:52 -0400 Subject: [PATCH 2/6] fixes --- .../java/com/onthegomap/planetiler/FeatureMerge.java | 4 ++-- .../onthegomap/planetiler/geo/GeometryException.java | 4 +++- .../com/onthegomap/planetiler/geo/GeoUtilsTest.java | 10 +++++----- .../custommap/validator/SchemaValidator.java | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index 650e69649f..f44195c312 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import org.geotools.geometry.jts.WKTWriter2; import org.locationtech.jts.algorithm.Area; import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Envelope; @@ -31,6 +30,7 @@ import org.locationtech.jts.geom.Polygonal; import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.index.strtree.STRtree; +import org.locationtech.jts.io.WKTWriter; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; import org.locationtech.jts.operation.linemerge.LineMerger; @@ -435,7 +435,7 @@ private static Geometry bufferUnionUnbuffer(double buffer, List polygo merged = union(merged); } catch (TopologyException e) { throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e).addDetails(() -> { - var wktWriter = new WKTWriter2(); + var wktWriter = new WKTWriter(); return """ Original polygons: %s Buffer: %f diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java index 1e89224313..71c005dc69 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java @@ -84,7 +84,9 @@ void logMessage(String log) { public void log(Stats stats, String statPrefix, String logPrefix, boolean logDetails) { if (logDetails && detailsSupplier != null) { stats.dataError(statPrefix + "_" + stat()); - logMessage(logPrefix + ": " + getMessage() + "\n" + detailsSupplier.get()); + String log = logPrefix + ": " + getMessage() + "\n" + detailsSupplier.get(); + LOGGER.warn(log, this); + assert nonFatal : log; // make unit tests fail if fatal } else { log(stats, statPrefix, logPrefix); } diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/geo/GeoUtilsTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/geo/GeoUtilsTest.java index 81cff04c3b..f1b528f9ac 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/geo/GeoUtilsTest.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/geo/GeoUtilsTest.java @@ -8,7 +8,6 @@ import com.onthegomap.planetiler.stats.Stats; import java.util.List; -import org.geotools.geometry.jts.WKTReader2; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -18,6 +17,7 @@ import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.util.AffineTransformation; import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; class GeoUtilsTest { @@ -367,7 +367,7 @@ void testCombineNested() { @Test void testSnapAndFixIssue511() throws ParseException, GeometryException { - var result = GeoUtils.snapAndFixPolygon(new WKTReader2().read( + var result = GeoUtils.snapAndFixPolygon(new WKTReader().read( """ MULTIPOLYGON (((198.83750000000003 46.07500000000004, 199.0625 46.375, 199.4375 46.0625, 199.5 46.43750000000001, 199.5625 46, 199.3125 45.5, 198.8912037037037 46.101851851851876, 198.83750000000003 46.07500000000004)), ((198.43750000000003 46.49999999999999, 198.5625 46.43750000000001, 198.6875 46.25, 198.1875 46.25, 198.43750000000003 46.49999999999999)), ((198.6875 46.25, 198.81249999999997 46.062500000000014, 198.6875 46.00000000000002, 198.6875 46.25)), ((196.55199579831933 46.29359243697479, 196.52255639097743 46.941259398496236, 196.5225563909774 46.941259398496236, 196.49999999999997 47.43750000000001, 196.875 47.125, 197 47.5625, 197.47880544905414 46.97729334004497, 197.51505401161464 46.998359569801956, 197.25 47.6875, 198.0625 47.6875, 198.5 46.625, 198.34375 46.546875, 198.34375000000003 46.54687499999999, 197.875 46.3125, 197.875 46.25, 197.875 46.0625, 197.82894736842107 46.20065789473683, 197.25 46.56250000000001, 197.3125 46.125, 196.9375 46.1875, 196.9375 46.21527777777778, 196.73250000000002 46.26083333333334, 196.5625 46.0625, 196.55199579831933 46.29359243697479)), ((196.35213414634146 45.8170731707317, 197.3402027027027 45.93108108108108, 197.875 45.99278846153846, 197.875 45.93750000000002, 197.93749999999997 45.99999999999999, 197.9375 46, 197.90625 45.96874999999999, 197.90625 45.96875, 196.75000000000006 44.81250000000007, 197.1875 45.4375, 196.3125 45.8125, 196.35213414634146 45.8170731707317)), ((195.875 46.124999999999986, 195.8125 46.5625, 196.5 46.31250000000001, 195.9375 46.4375, 195.875 46.124999999999986)), ((196.49999999999997 46.93749999999999, 196.125 46.875, 196.3125 47.125, 196.49999999999997 46.93749999999999))) """), @@ -377,7 +377,7 @@ void testSnapAndFixIssue511() throws ParseException, GeometryException { @Test void testSnapAndFixIssue546() throws GeometryException, ParseException { - var orig = new WKTReader2().read( + var orig = new WKTReader().read( """ POLYGON( ( @@ -404,7 +404,7 @@ void testSnapAndFixIssue546() throws GeometryException, ParseException { @Test void testSnapAndFixIssue546_2() throws GeometryException, ParseException { - var orig = new WKTReader2().read( + var orig = new WKTReader().read( """ POLYGON( ( @@ -423,7 +423,7 @@ void testSnapAndFixIssue546_2() throws GeometryException, ParseException { @Test void testSnapAndFixIssue546_3() throws GeometryException, ParseException { - var orig = new WKTReader2().read( + var orig = new WKTReader().read( """ POLYGON( ( diff --git a/planetiler-custommap/src/main/java/com/onthegomap/planetiler/custommap/validator/SchemaValidator.java b/planetiler-custommap/src/main/java/com/onthegomap/planetiler/custommap/validator/SchemaValidator.java index 431bda0c89..b112a189fb 100644 --- a/planetiler-custommap/src/main/java/com/onthegomap/planetiler/custommap/validator/SchemaValidator.java +++ b/planetiler-custommap/src/main/java/com/onthegomap/planetiler/custommap/validator/SchemaValidator.java @@ -29,9 +29,9 @@ import java.util.TreeSet; import java.util.stream.Stream; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.geotools.geometry.jts.WKTReader2; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; import org.snakeyaml.engine.v2.exceptions.YamlEngineException; /** Verifies that a profile maps input elements map to expected output vector tile features. */ @@ -164,7 +164,7 @@ private static Geometry parseGeometry(String geometry) { default -> geometry; }; try { - return new WKTReader2().read(wkt); + return new WKTReader().read(wkt); } catch (ParseException e) { throw new IllegalArgumentException(""" Bad geometry: "%s", must be "point" "line" "polygon" or a valid WKT string. From abac081bc8a861c2713757dbe3ce60e49006bd71 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 08:29:53 -0400 Subject: [PATCH 3/6] tweak --- .../com/onthegomap/planetiler/geo/GeometryException.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java index 71c005dc69..a3ec6bb02a 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java @@ -82,9 +82,12 @@ void logMessage(String log) { /** Logs the error but if {@code logDetails} is true, then also prints detailed debugging info. */ public void log(Stats stats, String statPrefix, String logPrefix, boolean logDetails) { - if (logDetails && detailsSupplier != null) { + if (logDetails) { stats.dataError(statPrefix + "_" + stat()); - String log = logPrefix + ": " + getMessage() + "\n" + detailsSupplier.get(); + String log = logPrefix + ": " + getMessage(); + if (detailsSupplier != null) { + log += "\n" + detailsSupplier.get(); + } LOGGER.warn(log, this); assert nonFatal : log; // make unit tests fail if fatal } else { From 732c789d3597d3fb2e27bc7fc7e77f0b3bedf1c3 Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 21:41:38 -0400 Subject: [PATCH 4/6] include wkt-encoded geometry --- .../com/onthegomap/planetiler/FeatureMerge.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index f44195c312..258345d82c 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -12,6 +12,7 @@ import com.onthegomap.planetiler.stats.DefaultStats; import com.onthegomap.planetiler.stats.Stats; import java.util.ArrayList; +import java.util.Base64; import java.util.BitSet; import java.util.Collection; import java.util.Comparator; @@ -30,6 +31,7 @@ import org.locationtech.jts.geom.Polygonal; import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.index.strtree.STRtree; +import org.locationtech.jts.io.WKBWriter; import org.locationtech.jts.io.WKTWriter; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; @@ -412,6 +414,7 @@ public static Collection> groupByAttrs( * Merges nearby polygons by expanding each individual polygon by {@code buffer}, unioning them, and contracting the * result. */ + @SuppressWarnings("java:S6203") private static Geometry bufferUnionUnbuffer(double buffer, List polygonGroup) throws GeometryException { /* * A simpler alternative that might initially appear faster would be: @@ -433,17 +436,27 @@ private static Geometry bufferUnionUnbuffer(double buffer, List polygo Geometry merged = GeoUtils.createGeometryCollection(buffered); try { merged = union(merged); + if (merged != null) + throw new TopologyException("e"); } catch (TopologyException e) { throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e).addDetails(() -> { + var base64 = Base64.getEncoder(); var wktWriter = new WKTWriter(); + var wkbWriter = new WKBWriter(); + var original = GeoUtils.createGeometryCollection(polygonGroup); + var bufferedGeoms = GeoUtils.createGeometryCollection(buffered); return """ Original polygons: %s + WKB: %s Buffer: %f Buffered: %s + WKB: %s """.formatted( wktWriter.write(GeoUtils.createGeometryCollection(polygonGroup)), + base64.encodeToString(wkbWriter.write(original)), buffer, - wktWriter.write(GeoUtils.createGeometryCollection(buffered)) + wktWriter.write(GeoUtils.createGeometryCollection(buffered)), + base64.encodeToString(wkbWriter.write(bufferedGeoms)) ); }); } From 8a23a2bfa74e480a719c4a75cc0599920e79e54c Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 22:01:21 -0400 Subject: [PATCH 5/6] tweaks --- .../onthegomap/planetiler/FeatureMerge.java | 29 +++------------ .../planetiler/geo/GeometryException.java | 35 +++++++++++++++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index 258345d82c..255708f58b 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -12,7 +12,6 @@ import com.onthegomap.planetiler.stats.DefaultStats; import com.onthegomap.planetiler.stats.Stats; import java.util.ArrayList; -import java.util.Base64; import java.util.BitSet; import java.util.Collection; import java.util.Comparator; @@ -31,8 +30,6 @@ import org.locationtech.jts.geom.Polygonal; import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.index.strtree.STRtree; -import org.locationtech.jts.io.WKBWriter; -import org.locationtech.jts.io.WKTWriter; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; import org.locationtech.jts.operation.linemerge.LineMerger; @@ -436,29 +433,11 @@ private static Geometry bufferUnionUnbuffer(double buffer, List polygo Geometry merged = GeoUtils.createGeometryCollection(buffered); try { merged = union(merged); - if (merged != null) - throw new TopologyException("e"); } catch (TopologyException e) { - throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e).addDetails(() -> { - var base64 = Base64.getEncoder(); - var wktWriter = new WKTWriter(); - var wkbWriter = new WKBWriter(); - var original = GeoUtils.createGeometryCollection(polygonGroup); - var bufferedGeoms = GeoUtils.createGeometryCollection(buffered); - return """ - Original polygons: %s - WKB: %s - Buffer: %f - Buffered: %s - WKB: %s - """.formatted( - wktWriter.write(GeoUtils.createGeometryCollection(polygonGroup)), - base64.encodeToString(wkbWriter.write(original)), - buffer, - wktWriter.write(GeoUtils.createGeometryCollection(buffered)), - base64.encodeToString(wkbWriter.write(bufferedGeoms)) - ); - }); + throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e) + .addGeometryDetails("original", GeoUtils.createGeometryCollection(polygonGroup)) + .addDetails(() -> "buffer: " + buffer) + .addGeometryDetails("buffered", GeoUtils.createGeometryCollection(buffered)); } merged = unbuffer(buffer, merged); return merged; diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java index a3ec6bb02a..9461b25014 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeometryException.java @@ -1,7 +1,12 @@ package com.onthegomap.planetiler.geo; import com.onthegomap.planetiler.stats.Stats; +import java.util.ArrayList; +import java.util.Base64; import java.util.function.Supplier; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKBWriter; +import org.locationtech.jts.io.WKTWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +20,7 @@ public class GeometryException extends Exception { private final String stat; private final boolean nonFatal; - private Supplier detailsSupplier; + private final ArrayList> detailsSuppliers = new ArrayList<>(); /** * Constructs a new exception with a detailed error message caused by {@code cause}. @@ -54,7 +59,7 @@ public GeometryException(String stat, String message, boolean nonFatal) { } public GeometryException addDetails(Supplier detailsSupplier) { - this.detailsSupplier = detailsSupplier; + this.detailsSuppliers.add(detailsSupplier); return this; } @@ -84,17 +89,33 @@ void logMessage(String log) { public void log(Stats stats, String statPrefix, String logPrefix, boolean logDetails) { if (logDetails) { stats.dataError(statPrefix + "_" + stat()); - String log = logPrefix + ": " + getMessage(); - if (detailsSupplier != null) { - log += "\n" + detailsSupplier.get(); + StringBuilder log = new StringBuilder(logPrefix + ": " + getMessage()); + for (var details : detailsSuppliers) { + log.append("\n").append(details.get()); } - LOGGER.warn(log, this); - assert nonFatal : log; // make unit tests fail if fatal + var str = log.toString(); + LOGGER.warn(str, this.getCause() == null ? this : this.getCause()); + assert nonFatal : log.toString(); // make unit tests fail if fatal } else { log(stats, statPrefix, logPrefix); } } + public GeometryException addGeometryDetails(String original, Geometry geometryCollection) { + return addDetails(() -> { + var wktWriter = new WKTWriter(); + var wkbWriter = new WKBWriter(); + var base64 = Base64.getEncoder(); + return """ + %s (wkt): %s + %s (wkb): %s + """.formatted( + original, wktWriter.write(geometryCollection), + original, base64.encodeToString(wkbWriter.write(geometryCollection)) + ).strip(); + }); + } + /** * An error that we expect to encounter often so should only be logged at {@code TRACE} level. */ From 3b1d4156d2343b1b8c893d0e87589a47df198fef Mon Sep 17 00:00:00 2001 From: Mike Barry Date: Mon, 30 Oct 2023 22:02:33 -0400 Subject: [PATCH 6/6] rm suppress --- .../src/main/java/com/onthegomap/planetiler/FeatureMerge.java | 1 - 1 file changed, 1 deletion(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index 255708f58b..2901907d19 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -411,7 +411,6 @@ public static Collection> groupByAttrs( * Merges nearby polygons by expanding each individual polygon by {@code buffer}, unioning them, and contracting the * result. */ - @SuppressWarnings("java:S6203") private static Geometry bufferUnionUnbuffer(double buffer, List polygonGroup) throws GeometryException { /* * A simpler alternative that might initially appear faster would be: