fix buffer union unbuffer exceptions

jts-union-fix
Mike Barry 2023-11-07 06:14:38 -05:00
rodzic 8b5af48e43
commit 332b8a90a0
11 zmienionych plików z 36 dodań i 6 usunięć

Wyświetl plik

@ -29,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.geom.util.GeometryFixer;
import org.locationtech.jts.index.strtree.STRtree;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.buffer.BufferParameters;
@ -323,7 +324,7 @@ public class FeatureMerge {
// spinning for a very long time on very dense tiles.
// TODO use some heuristic to choose bufferUnbuffer vs. bufferUnionUnbuffer based on the number small
// polygons in the group?
merged = bufferUnionUnbuffer(buffer, polygonGroup);
merged = bufferUnionUnbuffer(buffer, polygonGroup, stats);
} else {
merged = buffer(buffer, GeoUtils.createGeometryCollection(polygonGroup));
}
@ -411,7 +412,7 @@ public class FeatureMerge {
* Merges nearby polygons by expanding each individual polygon by {@code buffer}, unioning them, and contracting the
* result.
*/
private static Geometry bufferUnionUnbuffer(double buffer, List<Geometry> polygonGroup) throws GeometryException {
static Geometry bufferUnionUnbuffer(double buffer, List<Geometry> polygonGroup, Stats stats) {
/*
* A simpler alternative that might initially appear faster would be:
*
@ -433,10 +434,11 @@ public class FeatureMerge {
try {
merged = union(merged);
} catch (TopologyException e) {
throw new GeometryException("buffer_union_failure", "Error unioning buffered polygons", e)
.addGeometryDetails("original", GeoUtils.createGeometryCollection(polygonGroup))
.addDetails(() -> "buffer: " + buffer)
.addGeometryDetails("buffered", GeoUtils.createGeometryCollection(buffered));
// buffer result is sometimes invalid, which makes union throw so fix
// it and try again (see #700)
stats.dataError("buffer_union_unbuffer_union_failed");
merged = GeometryFixer.fix(merged);
merged = union(merged);
}
merged = unbuffer(buffer, merged);
return merged;

Wyświetl plik

@ -10,7 +10,9 @@ import com.onthegomap.planetiler.collection.Hppc;
import com.onthegomap.planetiler.geo.GeometryException;
import com.onthegomap.planetiler.geo.GeometryType;
import com.onthegomap.planetiler.mbtiles.Mbtiles;
import com.onthegomap.planetiler.stats.Stats;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -20,11 +22,14 @@ import java.util.function.UnaryOperator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -853,4 +858,27 @@ class FeatureMergeTest {
)
);
}
@ParameterizedTest
@ValueSource(strings = {
"/issue_700/exception_1.wkb",
"/issue_700/exception_2.wkb",
"/issue_700/exception_3.wkb",
"/issue_700/exception_4.wkb",
"/issue_700/exception_5.wkb",
"/issue_700/exception_6.wkb",
"/issue_700/exception_7.wkb",
"/issue_700/exception_8.wkb",
"/issue_700/exception_9.wkb",
})
void testIssue700BufferUnionUnbufferFailure(String path) throws IOException, ParseException {
try (var is = getClass().getResource(path).openStream()) {
GeometryCollection collection = (GeometryCollection) new WKBReader().read(is.readAllBytes());
List<Geometry> geometries = new ArrayList<>();
for (int i = 0; i < collection.getNumGeometries(); i++) {
geometries.add(collection.getGeometryN(i));
}
FeatureMerge.bufferUnionUnbuffer(0.5, geometries, Stats.inMemory());
}
}
}

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.