feat: add raw layer at z15, exclude everything else from z15

This commit is contained in:
2026-01-05 14:49:46 +01:00
parent d7ac85672f
commit 3d8ea2d72a
18 changed files with 148 additions and 23 deletions

View File

@@ -14,6 +14,7 @@ public class ExtraLayers {
public static List<Layer> create(Translations translations, PlanetilerConfig config, Stats stats) {
return List.of(
// Create classes that extend Layer interface in the addons package, then instantiate them here
new Raw()
);
}
}

View File

@@ -0,0 +1,89 @@
package org.openmaptiles.addons;
import com.onthegomap.planetiler.FeatureCollector;
import com.onthegomap.planetiler.reader.SourceFeature;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.openmaptiles.Layer;
import org.openmaptiles.OpenMapTilesProfile;
public class Raw implements Layer, OpenMapTilesProfile.OsmAllProcessor {
public static List<String> TAG_WHITELIST = Arrays.asList("amenity", "shop", "name", "opening_hours", "email", "website", "phone", "internet_access", "wheelchair", "cuisine", "indoor_seating", "outdoor_seating", "takeaway", "drive_through");
public static List<String> TAG_PREFIX_WHITELIST = Arrays.asList("addr:", "contact:", "payment:", "wheelchair:", "fuel:", "internet_access:");
@Override
public String name() {
return "raw";
}
@Override
public void processAllOsm(SourceFeature feature, FeatureCollector features) {
boolean hasTag = false;
for (Map.Entry<String, Object> i : feature.tags().entrySet()) {
if (TAG_WHITELIST.contains(i.getKey())) {
hasTag = true;
break;
}
for (String prefix : TAG_PREFIX_WHITELIST) {
if(i.getKey().startsWith(prefix)) {
hasTag = true;
break;
}
}
}
if(!hasTag) return;
if(feature.canBePolygon()) {
FeatureCollector.Feature ft = features.polygon("raw")
.setBufferPixels(4)
.setMinZoom(15);
for (Map.Entry<String, Object> i : feature.tags().entrySet()) {
if (TAG_WHITELIST.contains(i.getKey())) {
ft.setAttr(i.getKey(), i.getValue());
}
for (String prefix : TAG_PREFIX_WHITELIST) {
if(i.getKey().startsWith(prefix)) {
ft.setAttr(i.getKey(), i.getValue());
break;
}
}
}
} else if(feature.canBeLine()) {
FeatureCollector.Feature ft = features.line("raw")
.setBufferPixels(4)
.setMinZoom(15);
for (Map.Entry<String, Object> i : feature.tags().entrySet()) {
if (TAG_WHITELIST.contains(i.getKey())) {
ft.setAttr(i.getKey(), i.getValue());
}
for (String prefix : TAG_PREFIX_WHITELIST) {
if(i.getKey().startsWith(prefix)) {
ft.setAttr(i.getKey(), i.getValue());
break;
}
}
}
} else if(feature.isPoint()) {
FeatureCollector.Feature ft = features.point("raw")
.setBufferPixels(4)
.setMinZoom(15);
for(Map.Entry<String, Object> i : feature.tags().entrySet()) {
if(TAG_WHITELIST.contains(i.getKey())) {
ft.setAttr(i.getKey(), i.getValue());
}
for (String prefix : TAG_PREFIX_WHITELIST) {
if(i.getKey().startsWith(prefix)) {
ft.setAttr(i.getKey(), i.getValue());
break;
}
}
}
}
}
}

View File

@@ -74,6 +74,7 @@ public class AerodromeLabel implements
features.centroid(LAYER_NAME)
.setBufferPixels(BUFFER_SIZE)
.setMinZoom(important ? 8 : 10)
.setMaxZoom(14)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.putAttrs(Utils.elevationTags(element.ele()))
.setAttr(Fields.IATA, nullIfEmpty(element.iata()))

View File

@@ -60,6 +60,7 @@ public class Aeroway implements
public void process(Tables.OsmAerowayPolygon element, FeatureCollector features) {
features.polygon(LAYER_NAME)
.setMinZoom(10)
.setMaxZoom(14)
.setMinPixelSize(2)
.setAttr(Fields.CLASS, element.aeroway())
.setAttr(Fields.REF, element.ref());
@@ -69,6 +70,7 @@ public class Aeroway implements
public void process(Tables.OsmAerowayLinestring element, FeatureCollector features) {
features.line(LAYER_NAME)
.setMinZoom(10)
.setMaxZoom(14)
.setAttr(Fields.CLASS, element.aeroway())
.setAttr(Fields.REF, element.ref());
}
@@ -77,6 +79,7 @@ public class Aeroway implements
public void process(Tables.OsmAerowayPoint element, FeatureCollector features) {
features.point(LAYER_NAME)
.setMinZoom(14)
.setMaxZoom(14)
.setAttr(Fields.CLASS, element.aeroway())
.setAttr(Fields.REF, element.ref());
}

View File

@@ -207,7 +207,7 @@ public class Boundary implements
};
if (info != null) {
features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setZoomRange(info.minzoom, info.maxzoom)
.setZoomRange(info.minzoom, Math.max(info.maxzoom, 14))
.setMinPixelSizeAtAllZooms(0)
.setAttr(Fields.ADMIN_LEVEL, info.adminLevel)
.setAttr(Fields.MARITIME, 0)
@@ -320,6 +320,7 @@ public class Boundary implements
.setAttr(Fields.MARITIME, maritime ? 1 : 0)
.setMinPixelSizeAtAllZooms(0)
.setMinZoom(minzoom)
.setMaxZoom(14)
.setAttr(Fields.CLAIMED_BY, claimedBy)
.setAttr(Fields.DISPUTED_NAME, editName(disputedName));
}
@@ -333,7 +334,8 @@ public class Boundary implements
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(OpenMapTilesSchema.Boundary.Fields.CLASS, element.boundary())
.setMinPixelSizeBelowZoom(13, 4) // for Z4: `sql_filter: area>power(ZRES3,2)`, etc.
.setMinZoom(4);
.setMinZoom(4)
.setMaxZoom(14);
}
@Override
@@ -362,7 +364,8 @@ public class Boundary implements
.setAttr(Fields.CLAIMED_BY, key.claimedBy)
.setAttr(Fields.DISPUTED_NAME, key.disputed ? editName(key.name) : null)
.setMinPixelSizeAtAllZooms(0)
.setMinZoom(key.minzoom);
.setMinZoom(key.minzoom)
.setMaxZoom(14);
if (key.adminLevel == 2 && !key.disputed) {
// only non-disputed admin 2 boundaries get to have adm0_{l,r}, at zoom 5 and more
newFeature

View File

@@ -161,6 +161,7 @@ public class Building implements
if (renderHeight < 3660 && renderMinHeight < 3660) {
var feature = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setMinZoom(13)
.setMaxZoom(14)
.setMinPixelSize(2)
.setAttrWithMinzoom(Fields.RENDER_HEIGHT, renderHeight, 14)
.setAttrWithMinzoom(Fields.RENDER_MIN_HEIGHT, renderMinHeight, 14)

View File

@@ -137,7 +137,8 @@ public class Housenumber implements
.setAttr(Fields.HOUSENUMBER, housenumber)
.setAttr(TEMP_PARTITION, partition)
.setAttr(TEMP_HAS_NAME, hasName)
.setMinZoom(14);
.setMinZoom(14)
.setMaxZoom(14);
}
@Override

View File

@@ -114,7 +114,7 @@ public class Landcover implements
features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setAttr(Fields.CLASS, clazz)
.setAttr(Fields.SUBCLASS, info.subclass)
.setZoomRange(info.minzoom, info.maxzoom);
.setZoomRange(info.minzoom, Math.max(info.maxzoom, 14));
}
}
}
@@ -131,7 +131,8 @@ public class Landcover implements
.setAttr(Fields.CLASS, clazz)
.setAttr(Fields.SUBCLASS, subclass)
.setNumPointsAttr(TEMP_NUM_POINTS_ATTR)
.setMinZoom(7);
.setMinZoom(7)
.setMaxZoom(14);
}
}

View File

@@ -120,7 +120,8 @@ public class Landuse implements
}
var feature = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setAttr(Fields.CLASS, clazz)
.setMinZoom(Z6_CLASSES.contains(clazz) ? 6 : 9);
.setMinZoom(Z6_CLASSES.contains(clazz) ? 6 : 9)
.setMaxZoom(14);
if (FieldValues.CLASS_RESIDENTIAL.equals(clazz)) {
feature
.setMinPixelSize(0.1)

View File

@@ -126,6 +126,7 @@ public class MountainPeak implements
(nullIfEmpty(element.name()) != null ? 10_000 : 0)
)
.setMinZoom(7)
.setMaxZoom(14)
// need to use a larger buffer size to allow enough points through to not cut off
// any label grid squares which could lead to inconsistent label ranks for a feature
// in adjacent tiles. postProcess() will remove anything outside the desired buffer.
@@ -150,6 +151,7 @@ public class MountainPeak implements
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setSortKey(rank)
.setMinZoom(13)
.setMaxZoom(14)
.setBufferPixels(100);
}

View File

@@ -100,7 +100,8 @@ public class Park implements
var outline = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setAttrWithMinzoom(Fields.CLASS, clazz, 5)
.setMinPixelSize(2)
.setMinZoom(4);
.setMinZoom(4)
.setMaxZoom(14);
// park name label point (if it has one)
if (element.name() != null) {
@@ -122,7 +123,7 @@ public class Park implements
.thenByTruesFirst(element.source().hasTag("wikipedia") || element.source().hasTag("wikidata"))
.thenByLog(area, 1d, SMALLEST_PARK_WORLD_AREA, 1 << (SORT_KEY_BITS - 2) - 1)
.get()
).setMinZoom(minzoom);
).setMinZoom(minzoom).setMaxZoom(14);
} catch (GeometryException e) {
e.log(stats, "omt_park_area", "Unable to get park area for " + element.source().id());
}

View File

@@ -247,6 +247,7 @@ public class Place implements
.setAttr(Fields.CLASS, FieldValues.CLASS_COUNTRY)
.setAttr(Fields.RANK, rank)
.setMinZoom(rank - 1)
.setMaxZoom(14)
.setSortKey(rank);
} catch (GeometryException e) {
e.log(stats, "omt_place_country",
@@ -274,6 +275,7 @@ public class Place implements
// TODO: This starts including every "state" point at z2, even before many countries show up.
// Instead we might want to set state min zooms based on rank from natural earth?
.setMinZoom(2)
.setMaxZoom(14)
.setSortKey(rank);
}
} catch (GeometryException e) {
@@ -294,6 +296,7 @@ public class Place implements
.setAttr(Fields.CLASS, "island")
.setAttr(Fields.RANK, rank)
.setMinZoom(minzoom)
.setMaxZoom(14)
.setSortKey(SortKey.orderByLog(area, 1d, MIN_ISLAND_WORLD_AREA).get());
} catch (GeometryException e) {
e.log(stats, "omt_place_island_poly",
@@ -307,7 +310,8 @@ public class Place implements
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(Fields.CLASS, "island")
.setAttr(Fields.RANK, 7)
.setMinZoom(12);
.setMinZoom(12)
.setMaxZoom(14);
}
@Override
@@ -355,6 +359,7 @@ public class Place implements
.setAttr(Fields.CLASS, element.place())
.setAttr(Fields.RANK, rank)
.setMinZoom(minzoom)
.setMaxZoom(14)
.setSortKey(getSortKey(rank, placeType, element.population(), element.name()))
.setPointLabelGridPixelSize(12, 128);
@@ -383,7 +388,8 @@ public class Place implements
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(OpenMapTilesSchema.Boundary.Fields.CLASS, element.boundary())
.setAttr(Fields.RANK, rank)
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
} catch (GeometryException e) {
e.log(stats, "omt_boundary_poly",
"Unable to get point for OSM boundary polygon " + element.source().id());

View File

@@ -321,7 +321,8 @@ public class Poi implements
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setPointLabelGridPixelSize(14, 64)
.setSortKey(rankOrder)
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
}
@Override

View File

@@ -519,7 +519,8 @@ public class Transportation implements
.setAttrWithMinzoom(Fields.SURFACE, surface(coalesce(element.surface(), element.tracktype())), 12)
.setMinPixelSize(0) // merge during post-processing, then limit by size
.setSortKey(element.zOrder())
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
if (isFootwayOrSteps(highway)) {
feature
@@ -616,7 +617,8 @@ public class Transportation implements
.setAttrWithMinzoom(Fields.LAYER, nullIfLong(element.layer(), 0), 9)
.setSortKey(element.zOrder())
.setMinPixelSize(0) // merge during post-processing, then limit by size
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
}
}
@@ -632,7 +634,8 @@ public class Transportation implements
.setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
.setSortKey(element.zOrder())
.setMinPixelSize(0) // merge during post-processing, then limit by size
.setMinZoom(12);
.setMinZoom(12)
.setMaxZoom(14);
}
@Override
@@ -647,6 +650,7 @@ public class Transportation implements
.setSortKey(element.zOrder())
.setMinPixelSize(0) // merge during post-processing, then limit by size
.setMinZoom(4)
.setMaxZoom(14)
.setMinPixelSizeBelowZoom(10, 32); // `sql_filter: ST_Length(...)` used in OpenMapTiles translates to 32px
}
@@ -665,7 +669,8 @@ public class Transportation implements
.setAttr(Fields.BRUNNEL, brunnel("bridge".equals(manMade), false, false))
.setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
.setSortKey(element.zOrder())
.setMinZoom(13);
.setMinZoom(13)
.setMaxZoom(14);
}
}
}

View File

@@ -204,7 +204,8 @@ public class TransportationName implements
.setAttr(Fields.SUBCLASS, subclass)
.setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
.setSortKeyDescending(element.zOrder())
.setMinZoom(10);
.setMinZoom(10)
.setMaxZoom(14);
}
}
}
@@ -267,7 +268,8 @@ public class TransportationName implements
.setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, null, highway))
.setMinPixelSize(0)
.setSortKey(element.zOrder())
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
// populate route_1_<something>, route_2_<something>, ... route_n_<something> tags and remove duplicates
Set<String> routes = new HashSet<>();
@@ -322,7 +324,8 @@ public class TransportationName implements
.setAttr(Fields.SUBCLASS, element.aerialway())
.setMinPixelSize(0)
.setSortKey(element.zOrder())
.setMinZoom(12);
.setMinZoom(12)
.setMaxZoom(14);
}
}
@@ -336,7 +339,8 @@ public class TransportationName implements
.setAttr(Fields.CLASS, element.shipway())
.setMinPixelSize(0)
.setSortKey(element.zOrder())
.setMinZoom(12);
.setMinZoom(12)
.setMaxZoom(14);
}
}

View File

@@ -166,7 +166,8 @@ public class Water implements
features.polygon(LAYER_NAME)
.setBufferPixels(BUFFER_SIZE)
.setAttr(Fields.CLASS, FieldValues.CLASS_OCEAN)
.setMinZoom(6);
.setMinZoom(6)
.setMaxZoom(14);
}
@Override
@@ -177,6 +178,7 @@ public class Water implements
.setBufferPixels(BUFFER_SIZE)
.setMinPixelSizeBelowZoom(11, 2)
.setMinZoom(6)
.setMaxZoom(14)
.setAttr(Fields.ID, element.source().id())
.setAttr(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0)
.setAttrWithMinzoom(Fields.BRUNNEL, Utils.brunnel(element.isBridge(), element.isTunnel()), 12)

View File

@@ -210,7 +210,8 @@ public class WaterName implements
.putAttrs(OmtLanguageUtils.getNames(source.tags(), translations))
.setAttr(Fields.CLASS, clazz)
.setAttr(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0)
.setMinZoom(minZoom);
.setMinZoom(minZoom)
.setMaxZoom(14);
}
}
@@ -258,7 +259,8 @@ public class WaterName implements
.setBufferPixels(BUFFER_SIZE)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0)
.setMinZoom(minzoom);
.setMinZoom(minzoom)
.setMaxZoom(14);
return output;
}

View File

@@ -195,6 +195,7 @@ public class Waterway implements
.setAttr(Fields.CLASS, element.waterway())
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setMinZoom(minzoom)
.setMaxZoom(14)
// details only at higher zoom levels so that named rivers can be merged more aggressively
.setAttrWithMinzoom(Fields.BRUNNEL, Utils.brunnel(element.isBridge(), element.isTunnel()), 12)
.setAttrWithMinzoom(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0, 12)