Skip to content

Commit e6f1c41

Browse files
authored
Make fill tiles respect buffer size (#1100)
1 parent 6d6cd37 commit e6f1c41

File tree

5 files changed

+39
-18
lines changed

5 files changed

+39
-18
lines changed

planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java

+18
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,24 @@ public static int countGeometries(VectorTileProto.Tile.Feature feature) {
463463
return result;
464464
}
465465

466+
/**
467+
* Returns the encoded geometry for a polygon that fills an entire tile plus {@code buffer} pixels as a shortcut to
468+
* avoid needing to create an extra JTS geometry for encoding.
469+
*/
470+
public static VectorGeometry encodeFill(double buffer) {
471+
int min = (int) Math.round(EXTENT * buffer / 256d);
472+
int width = EXTENT + min + min;
473+
return new VectorGeometry(new int[]{
474+
CommandEncoder.commandAndLength(Command.MOVE_TO, 1),
475+
zigZagEncode(-min), zigZagEncode(-min),
476+
CommandEncoder.commandAndLength(Command.LINE_TO, 3),
477+
zigZagEncode(width), 0,
478+
0, zigZagEncode(width),
479+
zigZagEncode(-width), 0,
480+
CommandEncoder.commandAndLength(Command.CLOSE_PATH, 1)
481+
}, GeometryType.POLYGON, 0);
482+
}
483+
466484
/**
467485
* Adds features in a layer to this tile.
468486
*

planetiler-core/src/main/java/com/onthegomap/planetiler/render/FeatureRenderer.java

+3-12
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.locationtech.jts.geom.Point;
2929
import org.locationtech.jts.geom.Polygon;
3030
import org.locationtech.jts.geom.Polygonal;
31-
import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
3231
import org.locationtech.jts.geom.util.AffineTransformation;
3332
import org.slf4j.Logger;
3433
import org.slf4j.LoggerFactory;
@@ -39,14 +38,6 @@
3938
*/
4039
public class FeatureRenderer implements Consumer<FeatureCollector.Feature>, Closeable {
4140
private static final Logger LOGGER = LoggerFactory.getLogger(FeatureRenderer.class);
42-
private static final VectorTile.VectorGeometry FILL = VectorTile.encodeGeometry(GeoUtils.JTS_FACTORY
43-
.createPolygon(GeoUtils.JTS_FACTORY.createLinearRing(new PackedCoordinateSequence.Double(new double[]{
44-
-5, -5,
45-
261, -5,
46-
261, 261,
47-
-5, 261,
48-
-5, -5
49-
}, 2, 0))));
5041
private final PlanetilerConfig config;
5142
private final Consumer<RenderedFeature> consumer;
5243
private final Stats stats;
@@ -282,13 +273,13 @@ private void writeTileFeatures(int zoom, long id, FeatureCollector.Feature featu
282273
// polygons that span multiple tiles contain detail about the outer edges separate from the filled tiles, so emit
283274
// filled tiles now
284275
if (feature.isPolygon()) {
285-
emitted += emitFilledTiles(id, feature, sliced);
276+
emitted += emitFilledTiles(zoom, id, feature, sliced);
286277
}
287278

288279
stats.emittedFeatures(zoom, feature.getLayer(), emitted);
289280
}
290281

291-
private int emitFilledTiles(long id, FeatureCollector.Feature feature, TiledGeometry sliced) {
282+
private int emitFilledTiles(int zoom, long id, FeatureCollector.Feature feature, TiledGeometry sliced) {
292283
Optional<RenderedFeature.Group> groupInfo = Optional.empty();
293284
/*
294285
* 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
298289
VectorTile.Feature vectorTileFeature = new VectorTile.Feature(
299290
feature.getLayer(),
300291
id,
301-
FILL,
292+
VectorTile.encodeFill(feature.getBufferPixelsAtZoom(zoom)),
302293
feature.getAttrsAtZoom(sliced.zoomLevel())
303294
);
304295

planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ void testPolygonWithHoleSpanningMultipleTiles(boolean anyGeom) throws Exception
770770
), Map.of())
771771
)),
772772
newTileEntry(Z14_TILES / 2 + 2, Z14_TILES / 2 + 1, 14, List.of(
773-
feature(newPolygon(tileFill(5), List.of()), Map.of())
773+
feature(newPolygon(tileFill(4), List.of()), Map.of())
774774
)),
775775
newTileEntry(Z14_TILES / 2 + 3, Z14_TILES / 2 + 1, 14, List.of(
776776
feature(tileLeft(4), Map.of())
@@ -814,7 +814,7 @@ void testZ15Fill() throws Exception {
814814
);
815815

816816
assertEquals(List.of(
817-
feature(newPolygon(tileFill(5)), Map.of())
817+
feature(newPolygon(tileFill(4)), Map.of())
818818
), results.tiles.get(TileCoord.ofXYZ(Z15_TILES / 2, Z15_TILES / 2, 15)));
819819
}
820820

@@ -832,7 +832,7 @@ void testFullWorldPolygon() throws Exception {
832832

833833
assertEquals(5461, results.tiles.size());
834834
// spot-check one filled tile
835-
assertEquals(List.of(rectangle(-5, 256 + 5).norm()), results.tiles.get(TileCoord.ofXYZ(
835+
assertEquals(List.of(rectangle(-4, 256 + 4).norm()), results.tiles.get(TileCoord.ofXYZ(
836836
Z4_TILES / 2, Z4_TILES / 2, 4
837837
)).stream().map(d -> d.geometry().geom().norm()).toList());
838838
}
@@ -2449,7 +2449,7 @@ private PlanetilerResults runForCompactTest(boolean compactDbEnabled) throws Exc
24492449
),
24502450
(in, features) -> features.polygon("layer")
24512451
.setZoomRange(0, 2)
2452-
.setBufferPixels(0)
2452+
.setBufferPixels(1)
24532453
);
24542454
}
24552455

planetiler-core/src/test/java/com/onthegomap/planetiler/VectorTileTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,18 @@ void firstCoordinateOfPolygon(double x, double y) {
692692
}
693693
}
694694

695+
@ParameterizedTest
696+
@CsvSource({
697+
"0, 0, 256",
698+
"1, -1, 257",
699+
"10, -10, 266",
700+
})
701+
void testFill(double buffer, double min, double max) throws GeometryException {
702+
var geom = VectorTile.encodeFill(buffer);
703+
assertSameGeometry(rectangle(min, max), geom.decode());
704+
assertArrayEquals(VectorTile.encodeGeometry(rectangle(min, max)).commands(), geom.commands());
705+
}
706+
695707
private static void assertArrayEquals(int[] a, int[] b) {
696708
assertEquals(
697709
IntStream.of(a).boxed().toList(),

planetiler-core/src/test/java/com/onthegomap/planetiler/render/FeatureRendererTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ void testFill() {
814814
tileRight(1)
815815
),
816816
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
817-
newPolygon(tileFill(5), List.of()) // <<<<---- the filled tile!
817+
newPolygon(tileFill(1), List.of()) // <<<<---- the filled tile!
818818
),
819819
TileCoord.ofXYZ(Z14_TILES / 2 + 1, Z14_TILES / 2, 14), List.of(
820820
tileLeft(1)
@@ -1173,7 +1173,7 @@ void testNestedMultipolygonFill() {
11731173
var rendered = renderGeometry(feature);
11741174
var innerTile = rendered.get(TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14));
11751175
assertEquals(1, innerTile.size());
1176-
assertEquals(new TestUtils.NormGeometry(rectangle(-5, 256 + 5)),
1176+
assertEquals(new TestUtils.NormGeometry(rectangle(-1, 256 + 1)),
11771177
new TestUtils.NormGeometry(innerTile.iterator().next()));
11781178
}
11791179

0 commit comments

Comments
 (0)