From 58907f7698fef78a9c5769909165ae82bb5d3c72 Mon Sep 17 00:00:00 2001 From: Mike Barry <msb5014@gmail.com> Date: Wed, 13 Nov 2024 06:42:43 -0500 Subject: [PATCH 1/2] make fill tiles respect buffer size --- .../com/onthegomap/planetiler/VectorTile.java | 18 ++++++++++++++++++ .../planetiler/render/FeatureRenderer.java | 15 +++------------ .../onthegomap/planetiler/VectorTileTest.java | 12 ++++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java index 452ee6e269..b72e416851 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java @@ -463,6 +463,24 @@ public static int countGeometries(VectorTileProto.Tile.Feature feature) { return result; } + /** + * Returns the encoded geometry for a polygon that fills an entire tile plus {@code buffer} pixels as a shortcut to + * avoid needing to create an extra JTS geometry for encoding. + */ + public static VectorGeometry encodeFill(double buffer) { + int min = (int) Math.round(EXTENT * buffer / 256d); + int width = EXTENT + min + min; + return new VectorGeometry(new int[]{ + CommandEncoder.commandAndLength(Command.MOVE_TO, 1), + zigZagEncode(-min), zigZagEncode(-min), + CommandEncoder.commandAndLength(Command.LINE_TO, 3), + zigZagEncode(width), 0, + 0, zigZagEncode(width), + zigZagEncode(-width), 0, + CommandEncoder.commandAndLength(Command.CLOSE_PATH, 1) + }, GeometryType.POLYGON, 0); + } + /** * Adds features in a layer to this tile. * diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/render/FeatureRenderer.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/render/FeatureRenderer.java index 422f2271c2..95df944180 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/render/FeatureRenderer.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/render/FeatureRenderer.java @@ -28,7 +28,6 @@ import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.Polygonal; -import org.locationtech.jts.geom.impl.PackedCoordinateSequence; import org.locationtech.jts.geom.util.AffineTransformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,14 +38,6 @@ */ public class FeatureRenderer implements Consumer<FeatureCollector.Feature>, Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(FeatureRenderer.class); - private static final VectorTile.VectorGeometry FILL = VectorTile.encodeGeometry(GeoUtils.JTS_FACTORY - .createPolygon(GeoUtils.JTS_FACTORY.createLinearRing(new PackedCoordinateSequence.Double(new double[]{ - -5, -5, - 261, -5, - 261, 261, - -5, 261, - -5, -5 - }, 2, 0)))); private final PlanetilerConfig config; private final Consumer<RenderedFeature> consumer; private final Stats stats; @@ -282,13 +273,13 @@ private void writeTileFeatures(int zoom, long id, FeatureCollector.Feature featu // polygons that span multiple tiles contain detail about the outer edges separate from the filled tiles, so emit // filled tiles now if (feature.isPolygon()) { - emitted += emitFilledTiles(id, feature, sliced); + emitted += emitFilledTiles(zoom, id, feature, sliced); } stats.emittedFeatures(zoom, feature.getLayer(), emitted); } - private int emitFilledTiles(long id, FeatureCollector.Feature feature, TiledGeometry sliced) { + private int emitFilledTiles(int zoom, long id, FeatureCollector.Feature feature, TiledGeometry sliced) { Optional<RenderedFeature.Group> groupInfo = Optional.empty(); /* * Optimization: large input polygons that generate many filled interior tiles (i.e. the ocean), the encoder avoids @@ -298,7 +289,7 @@ private int emitFilledTiles(long id, FeatureCollector.Feature feature, TiledGeom VectorTile.Feature vectorTileFeature = new VectorTile.Feature( feature.getLayer(), id, - FILL, + VectorTile.encodeFill(feature.getBufferPixelsAtZoom(zoom)), feature.getAttrsAtZoom(sliced.zoomLevel()) ); diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/VectorTileTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/VectorTileTest.java index 203ac7e41d..d3f9346958 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/VectorTileTest.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/VectorTileTest.java @@ -692,6 +692,18 @@ void firstCoordinateOfPolygon(double x, double y) { } } + @ParameterizedTest + @CsvSource({ + "0, 0, 256", + "1, -1, 257", + "10, -10, 266", + }) + void testFill(double buffer, double min, double max) throws GeometryException { + var geom = VectorTile.encodeFill(buffer); + assertSameGeometry(rectangle(min, max), geom.decode()); + assertArrayEquals(VectorTile.encodeGeometry(rectangle(min, max)).commands(), geom.commands()); + } + private static void assertArrayEquals(int[] a, int[] b) { assertEquals( IntStream.of(a).boxed().toList(), From 389ff39f6083072891c3bb1ec38b79f2583a9c7d Mon Sep 17 00:00:00 2001 From: Mike Barry <msb5014@gmail.com> Date: Wed, 13 Nov 2024 06:49:35 -0500 Subject: [PATCH 2/2] fix tests --- .../java/com/onthegomap/planetiler/PlanetilerTests.java | 8 ++++---- .../onthegomap/planetiler/render/FeatureRendererTest.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java index eb9fb3c303..044822d71d 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java @@ -770,7 +770,7 @@ void testPolygonWithHoleSpanningMultipleTiles(boolean anyGeom) throws Exception ), Map.of()) )), newTileEntry(Z14_TILES / 2 + 2, Z14_TILES / 2 + 1, 14, List.of( - feature(newPolygon(tileFill(5), List.of()), Map.of()) + feature(newPolygon(tileFill(4), List.of()), Map.of()) )), newTileEntry(Z14_TILES / 2 + 3, Z14_TILES / 2 + 1, 14, List.of( feature(tileLeft(4), Map.of()) @@ -814,7 +814,7 @@ void testZ15Fill() throws Exception { ); assertEquals(List.of( - feature(newPolygon(tileFill(5)), Map.of()) + feature(newPolygon(tileFill(4)), Map.of()) ), results.tiles.get(TileCoord.ofXYZ(Z15_TILES / 2, Z15_TILES / 2, 15))); } @@ -832,7 +832,7 @@ void testFullWorldPolygon() throws Exception { assertEquals(5461, results.tiles.size()); // spot-check one filled tile - assertEquals(List.of(rectangle(-5, 256 + 5).norm()), results.tiles.get(TileCoord.ofXYZ( + assertEquals(List.of(rectangle(-4, 256 + 4).norm()), results.tiles.get(TileCoord.ofXYZ( Z4_TILES / 2, Z4_TILES / 2, 4 )).stream().map(d -> d.geometry().geom().norm()).toList()); } @@ -2449,7 +2449,7 @@ private PlanetilerResults runForCompactTest(boolean compactDbEnabled) throws Exc ), (in, features) -> features.polygon("layer") .setZoomRange(0, 2) - .setBufferPixels(0) + .setBufferPixels(1) ); } diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/render/FeatureRendererTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/render/FeatureRendererTest.java index 315b03c4e9..a1a3dab4dd 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/render/FeatureRendererTest.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/render/FeatureRendererTest.java @@ -814,7 +814,7 @@ void testFill() { tileRight(1) ), TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of( - newPolygon(tileFill(5), List.of()) // <<<<---- the filled tile! + newPolygon(tileFill(1), List.of()) // <<<<---- the filled tile! ), TileCoord.ofXYZ(Z14_TILES / 2 + 1, Z14_TILES / 2, 14), List.of( tileLeft(1) @@ -1173,7 +1173,7 @@ void testNestedMultipolygonFill() { var rendered = renderGeometry(feature); var innerTile = rendered.get(TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14)); assertEquals(1, innerTile.size()); - assertEquals(new TestUtils.NormGeometry(rectangle(-5, 256 + 5)), + assertEquals(new TestUtils.NormGeometry(rectangle(-1, 256 + 1)), new TestUtils.NormGeometry(innerTile.iterator().next())); }