diff --git a/tiles/src/main/java/com/protomaps/basemap/feature/FeatureId.java b/tiles/src/main/java/com/protomaps/basemap/feature/FeatureId.java index 15527d0e..0f29dfce 100644 --- a/tiles/src/main/java/com/protomaps/basemap/feature/FeatureId.java +++ b/tiles/src/main/java/com/protomaps/basemap/feature/FeatureId.java @@ -8,7 +8,15 @@ public class FeatureId { private FeatureId() {} - public static long create(SourceFeature sf) { + // uses 44 bits for the Feature ID, + // 2 bits for class (OSM node/way/relation or Not OSM) + // 6 bits for the layer id + + public static long encode(int layerId) { + return (layerId << 46); + } + + public static long encode(int layerId, SourceFeature sf) { if (sf instanceof OsmSourceFeature osmFeature) { long elemType; var element = osmFeature.originalElement(); @@ -19,8 +27,8 @@ public static long create(SourceFeature sf) { } else { elemType = 0x1; } - return (elemType << 44) | element.id(); + return (layerId << 46) | (elemType << 44) | element.id(); } - return sf.id(); + return (layerId << 46) | sf.id(); } } diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Boundaries.java b/tiles/src/main/java/com/protomaps/basemap/layers/Boundaries.java index c4e89bd8..745f5a9f 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Boundaries.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Boundaries.java @@ -16,6 +16,8 @@ public class Boundaries implements ForwardingProfile.OsmRelationPreprocessor, ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 0; + @Override public String name() { return "boundaries"; @@ -214,7 +216,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { if (!kind.isEmpty()) { var line = features.line(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) .setAttr("kind_detail", minAdminLevel.getAsInt()) diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Buildings.java b/tiles/src/main/java/com/protomaps/basemap/layers/Buildings.java index 1347e098..c9cd40e5 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Buildings.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Buildings.java @@ -23,6 +23,8 @@ public class Buildings implements ForwardingProfile.LayerPostProcesser { static final String HEIGHT_KEY = "height"; static final String MIN_HEIGHT_KEY = "min_height"; + final int LAYER_ID = 1; + @Override public String name() { return "buildings"; @@ -78,7 +80,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feature = features.polygon(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) // Core OSM tags for different kinds of places @@ -108,7 +110,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } if (housenumberFeature != null) { housenumberFeature - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("addr_housenumber", sf.getString("addr:housenumber")) .setAttr("addr_street", sf.getString("addr:street")) .setAttr("kind", "address") diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Earth.java b/tiles/src/main/java/com/protomaps/basemap/layers/Earth.java index d367f545..7001d5c6 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Earth.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Earth.java @@ -12,6 +12,8 @@ import org.locationtech.jts.geom.Point; public class Earth implements ForwardingProfile.LayerPostProcesser { + + final int LAYER_ID = 2; @Override public String name() { return "earth"; @@ -20,7 +22,7 @@ public String name() { public void processPreparedOsm(SourceFeature ignoredSf, FeatureCollector features) { features.polygon(this.name()) .setAttr("kind", "earth") - .setId(0) + .setId(FeatureId.encode(LAYER_ID)) .setZoomRange(6, 15).setBufferPixels(8); } @@ -54,7 +56,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { if (sf.canBeLine() && !sf.canBePolygon() && sf.hasTag("natural", "cliff")) { int minZoom = 12; var feat = features.line(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("min_zoom", minZoom + 1) .setAttr("kind", "cliff") .setZoomRange(minZoom, 15); diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Landcover.java b/tiles/src/main/java/com/protomaps/basemap/layers/Landcover.java index 5e0205af..6d00d47d 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Landcover.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Landcover.java @@ -10,6 +10,7 @@ import java.util.Map; public class Landcover implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 3; static final Map kindMapping = Map.of("urban", "urban_area", "crop", "farmland", "grass", "grassland", "trees", "forest", "snow", "glacier", "shrub", "scrub"); @@ -25,7 +26,7 @@ public void processLandcover(SourceFeature sf, FeatureCollector features) { Integer sortKey = sortKeyMapping.getOrDefault(daylightClass, 6); features.polygon(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("kind", kind) .setZoomRange(0, 7) .setSortKey(sortKey) diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Landuse.java b/tiles/src/main/java/com/protomaps/basemap/layers/Landuse.java index f24a7acf..38eea95a 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Landuse.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Landuse.java @@ -11,6 +11,7 @@ import java.util.List; public class Landuse implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 4; public void processOsm(SourceFeature sf, FeatureCollector features) { if (sf.canBePolygon() && (sf.hasTag("aeroway", "aerodrome", "runway") || @@ -151,7 +152,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } features.polygon(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) .setAttr("sort_rank", 189) diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Places.java b/tiles/src/main/java/com/protomaps/basemap/layers/Places.java index 7b046038..bf282983 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Places.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Places.java @@ -16,6 +16,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class Places implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 5; private NaturalEarthDb naturalEarthDb; @@ -266,7 +267,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feat = features.point(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) .setAttr("kind_detail", place) diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Pois.java b/tiles/src/main/java/com/protomaps/basemap/layers/Pois.java index 7b5f41e7..cc5b5ddc 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Pois.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Pois.java @@ -15,6 +15,7 @@ import java.util.List; public class Pois implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 6; private QrankDb qrankDb; @@ -443,7 +444,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { var polyLabelPosition = features.pointOnSurface(this.name()) // all POIs should receive their IDs at all zooms // (there is no merging of POIs like with lines and polygons in other layers) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) // While other layers don't need min_zoom, POIs do for more predictable client-side label collisions @@ -485,7 +486,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { var pointFeature = features.point(this.name()) // all POIs should receive their IDs at all zooms // (there is no merging of POIs like with lines and polygons in other layers) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) // Core Tilezen schema properties .setAttr("kind", kind) // While other layers don't need min_zoom, POIs do for more predictable client-side label collisions diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Roads.java b/tiles/src/main/java/com/protomaps/basemap/layers/Roads.java index 164b3112..9ff5e63b 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Roads.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Roads.java @@ -18,6 +18,7 @@ import java.util.*; public class Roads implements ForwardingProfile.LayerPostProcessor, ForwardingProfile.OsmRelationPreprocessor { + final int LAYER_ID = 7; private CountryCoder countryCoder; @@ -190,7 +191,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feat = features.line("roads") - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("kind", kind) // To power better client label collisions .setAttr("min_zoom", minZoom + 1) @@ -294,7 +295,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feature = features.line(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("kind", kind) // Used for client-side label collisions .setAttr("min_zoom", minZoom + 1) diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Transit.java b/tiles/src/main/java/com/protomaps/basemap/layers/Transit.java index 906ef50b..b80512d7 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Transit.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Transit.java @@ -7,6 +7,7 @@ import java.util.List; public class Transit implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 8; @Override public String name() { diff --git a/tiles/src/main/java/com/protomaps/basemap/layers/Water.java b/tiles/src/main/java/com/protomaps/basemap/layers/Water.java index cadc377d..85c56fcf 100644 --- a/tiles/src/main/java/com/protomaps/basemap/layers/Water.java +++ b/tiles/src/main/java/com/protomaps/basemap/layers/Water.java @@ -14,6 +14,7 @@ import java.util.List; public class Water implements ForwardingProfile.LayerPostProcesser { + final int LAYER_ID = 9; private static final double WORLD_AREA_FOR_70K_SQUARE_METERS = Math.pow(GeoUtils.metersToPixelAtEquator(0, Math.sqrt(70_000)) / 256d, 2); @@ -25,7 +26,7 @@ public String name() { public void processPreparedOsm(SourceFeature ignoredSf, FeatureCollector features) { features.polygon(this.name()) - .setId(0) + .setId(FeatureId.encode(LAYER_ID)) .setAttr("kind", "ocean") .setAttr("sort_rank", 200) .setZoomRange(6, 15).setBufferPixels(8); @@ -200,7 +201,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feat = features.line(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("kind", kind) // Used for client-side label collisions .setAttr("min_zoom", minZoom + 1) @@ -249,7 +250,7 @@ public void processOsm(SourceFeature sf, FeatureCollector features) { } var feat = features.point(this.name()) - .setId(FeatureId.create(sf)) + .setId(FeatureId.encode(LAYER_ID, sf)) .setAttr("kind", kind) // Used for client-side label collisions .setAttr("min_zoom", minZoom + 1)