Skip to content

Commit 4df8646

Browse files
authored
Fix area thresholds using floating point division (#620)
Landuse post-processing and the shared Area name-stripping threshold used scaled area formulas such as: 400 / (4096 * 4096) * (256 * 256) 30000 / (4096 * 4096) * (256 * 256) In Java these are evaluated with integer arithmetic because every operand is an integer literal. A one-line JShell check shows the bug: printf 'System.out.println(400 / (4096 * 4096) * (256 * 256));\nSystem.out.println(30000 / (4096 * 4096) * (256 * 256));\n/exit\n' | jshell -q jshell> 0 jshell> 0 The fixed expressions force floating point division by making the numerator a double literal: printf 'System.out.println(400d / (4096 * 4096) * (256 * 256));\nSystem.out.println(30000d / (4096 * 4096) * (256 * 256));\n/exit\n' | jshell -q jshell> 1.5625 jshell> 117.1875 The visible production effect today is in Landuse: the min-area filter at z<15 was disabled because the computed minArea was 0. The Area.java change fixes the same latent integer arithmetic in the shared name-stripping threshold, but current callers do not emit name tags through that branch, so it produced no visible Saarland PMTiles delta in this comparison. git blame traces both bad expressions to commit 1c38928 (Brandon Liu, 2023-03-28 21:26:42 +0800, "finish port of area logic"). That same commit added Buildings.java calling Area.filterArea(items, 0), so the shared name-stripping threshold has been zero since Area.filterArea was introduced. Add a Landuse regression test at z14 so a sub-threshold polygon is dropped while a larger polygon survives. This exercises the coordinate-space threshold directly and would fail if the formula regressed to integer division. Saarland PMTiles comparison against origin/main using saarland-latest.osm.pbf: - landuse archive: 16,101,245 bytes before, 16,073,949 bytes after (-27,296) - landuse decoded features: 219,609 before, 218,167 after (-1,442) - landuse feature deltas by zoom: z8 -15, z9 -29, z10 -97, z11 -174, z12 -273, z13 -420, z14 -434; z6, z7, and z15 unchanged - buildings archive: 20,368,010 bytes before and after, identical SHA256 - buildings decoded features: 1,007,114 before and after Verification: mvn -q -Dtest=LanduseTest test, mvn -q package, mvn -q spotless:check, git diff --check, and before/after Saarland PMTiles scans. AI assistance: this change was prepared with help from OpenAI Codex.
1 parent df2e4e2 commit 4df8646

3 files changed

Lines changed: 21 additions & 4 deletions

File tree

tiles/src/main/java/com/protomaps/basemap/layers/Landuse.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,11 @@ public String name() {
314314
public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> items) throws GeometryException {
315315
if (zoom == 15)
316316
return items;
317-
int minArea = 400 / (4096 * 4096) * (256 * 256);
317+
double minArea = 400d / (4096 * 4096) * (256 * 256);
318318
if (zoom == 6)
319-
minArea = 600 / (4096 * 4096) * (256 * 256);
319+
minArea = 600d / (4096 * 4096) * (256 * 256);
320320
else if (zoom <= 5)
321-
minArea = 800 / (4096 * 4096) * (256 * 256);
321+
minArea = 800d / (4096 * 4096) * (256 * 256);
322322
items = Area.filterArea(items, minArea);
323323

324324
// We only care about park boundaries inside groups of adjacent parks at higher zooms when they are labeled

tiles/src/main/java/com/protomaps/basemap/postprocess/Area.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static List<VectorTile.Feature> filterArea(List<VectorTile.Feature> items
2020
if (minArea > 0 && area < minArea) {
2121
// do nothing
2222
} else {
23-
if (minArea < 30000 / (4096 * 4096) * (256 * 256)) {
23+
if (minArea < 30000d / (4096 * 4096) * (256 * 256)) {
2424
Set<String> keys = new HashSet<>(item.tags().keySet());
2525
for (String key : keys) {
2626
if (key.equals("name") || key.startsWith("name:")) {

tiles/src/test/java/com/protomaps/basemap/layers/LanduseTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.protomaps.basemap.layers;
22

33
import static com.onthegomap.planetiler.TestUtils.newPolygon;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
45

56
import com.onthegomap.planetiler.FeatureCollector;
7+
import com.onthegomap.planetiler.VectorTile;
8+
import com.onthegomap.planetiler.geo.GeometryException;
69
import com.onthegomap.planetiler.reader.SimpleFeature;
710
import java.util.HashMap;
811
import java.util.List;
@@ -580,4 +583,18 @@ void testNationalPark() {
580583
"protection_title", "National Park")
581584
);
582585
}
586+
587+
@Test
588+
void postProcessFiltersSmallPolygonsBelowZoom15() throws GeometryException {
589+
var small = new VectorTile.Feature("landuse", 1,
590+
VectorTile.encodeGeometry(newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0)),
591+
new HashMap<>(Map.of("kind", "park")));
592+
var large = new VectorTile.Feature("landuse", 2,
593+
VectorTile.encodeGeometry(newPolygon(0, 0, 2, 0, 2, 2, 0, 2, 0, 0)),
594+
new HashMap<>(Map.of("kind", "park")));
595+
596+
var result = new Landuse().postProcess(14, List.of(small, large));
597+
598+
assertEquals(List.of(large), result);
599+
}
583600
}

0 commit comments

Comments
 (0)