diff --git a/src/main/java/org/openmaptiles/generated/OpenMapTilesSchema.java b/src/main/java/org/openmaptiles/generated/OpenMapTilesSchema.java
index 03014fce..676b5a46 100644
--- a/src/main/java/org/openmaptiles/generated/OpenMapTilesSchema.java
+++ b/src/main/java/org/openmaptiles/generated/OpenMapTilesSchema.java
@@ -209,13 +209,20 @@ default String name() {
/** Attribute names for map elements in the waterway layer. */
final class Fields {
/**
- * The OSM name
value of the waterway. The
- * name
field may be empty for NaturalEarth data or at lower zoom levels.
+ * The OSM name
value of the waterway.
+ * Language-specific values are in name:xx
. The name
field may be empty for NaturalEarth
+ * data or at lower zoom levels.
*/
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
@@ -546,9 +553,15 @@ default String name() {
/** Attribute names for map elements in the mountain_peak layer. */
final class Fields {
- /** The OSM name
value of the peak. */
+ /**
+ * The OSM name
value of the peak.
+ * Language-specific values are in name:xx
.
+ */
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
/** German name name:de
if available, otherwise name
or name:en
. */
public static final String NAME_DE = "name_de";
@@ -606,10 +619,6 @@ final class FieldMappings {
* boundary=protected_area
, or
* leisure=nature_reserve
.
- * This layer also includes boundaries for indigenous lands tagged with boundary=aboriginal_lands
.
- * Indigenous boundaries are not parks, but they are included in this layer for technical reasons related to data
- * processing. These boundaries represent areas with special legal and administrative status for indigenous peoples.
*
* Generated from
* park.yaml
@@ -627,27 +636,29 @@ default String name() {
final class Fields {
/**
* Use the class to differentiate between different kinds of features in the parks
- * layer, for example between parks and non-parks. The class for boundary=protected_area
parks is the
- * lower-case of the
+ * layer. The class for boundary=protected_area
parks is the lower-case of the
* protection_title
value with
* blanks replaced by _
. national_park
is the class of
* protection_title=National Park
and boundary=national_park
.
* nature_reserve
is the class of protection_title=Nature Reserve
and
* leisure=nature_reserve
. The class for other
* protection_title
values is
- * similarly assigned. The class for boundary=aboriginal_lands
is aboriginal_lands
.
+ * similarly assigned.
*/
public static final String CLASS = "class";
/**
* The OSM name
value of the park (point
- * features only).
+ * features only). Language-specific values are in name:xx
.
*/
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
(point features only). */
+ /**
+ * English name name:en
if available, otherwise name
(point features only). This is
+ * deprecated and will be removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
/**
* German name name:de
if available, otherwise name
or name:en
(point
- * features only).
+ * features only). This is deprecated and will be removed in a future release in favor of name:de
.
*/
public static final String NAME_DE = "name_de";
/** Rank of the park within one tile, starting at 1 that is the most important park (point features only). */
@@ -663,7 +674,7 @@ final class FieldMappings {
}
}
/**
- * Contains administrative boundaries as linestrings. Until z4
+ * Contains administrative boundaries as linestrings and aboriginal lands as polygons. Until z4
* Natural Earth data is used after which OSM boundaries
* (boundary=administrative
) are
@@ -686,6 +697,15 @@ default String name() {
/** Attribute names for map elements in the boundary layer. */
final class Fields {
+ /**
+ * Use the class to differentiate between different kinds of boundaries. The class for
+ * boundary=aboriginal_lands
is aboriginal_lands
.
+ */
+ public static final String CLASS = "class";
+ /**
+ * The OSM name
value (area features only).
+ */
+ public static final String NAME = "name";
/**
* OSM admin_level
* indicating the level of importance of this boundary. The admin_level
corresponds to the lowest
@@ -1236,11 +1256,18 @@ default String name() {
final class Fields {
/**
* The OSM name
value of the water body.
+ * Language-specific values are in name:xx
.
*/
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
@@ -1309,9 +1336,15 @@ final class Fields {
* of the highway.
*/
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
* The OSM ref
tag of the motorway or its
@@ -1432,18 +1465,54 @@ final class Fields {
*
*/
public static final String INDOOR = "indoor";
- /** 1st route concurrency. */
- public static final String ROUTE_1 = "route_1";
- /** 2nd route concurrency. */
- public static final String ROUTE_2 = "route_2";
- /** 3rd route concurrency. */
- public static final String ROUTE_3 = "route_3";
- /** 4th route concurrency. */
- public static final String ROUTE_4 = "route_4";
- /** 5th route concurrency. */
- public static final String ROUTE_5 = "route_5";
- /** 6th route concurrency. */
- public static final String ROUTE_6 = "route_6";
+ /** 1st route concurrency network. */
+ public static final String ROUTE_1_NETWORK = "route_1_network";
+ /** 1st route concurrency ref. */
+ public static final String ROUTE_1_REF = "route_1_ref";
+ /** 1st route concurrency name. */
+ public static final String ROUTE_1_NAME = "route_1_name";
+ /** 1st route concurrency colour. */
+ public static final String ROUTE_1_COLOUR = "route_1_colour";
+ /** 2nd route concurrency network. */
+ public static final String ROUTE_2_NETWORK = "route_2_network";
+ /** 2nd route concurrency ref. */
+ public static final String ROUTE_2_REF = "route_2_ref";
+ /** 2nd route concurrency name. */
+ public static final String ROUTE_2_NAME = "route_2_name";
+ /** 2nd route concurrency colour. */
+ public static final String ROUTE_2_COLOUR = "route_2_colour";
+ /** 3rd route concurrency network. */
+ public static final String ROUTE_3_NETWORK = "route_3_network";
+ /** 3rd route concurrency ref. */
+ public static final String ROUTE_3_REF = "route_3_ref";
+ /** 3rd route concurrency name. */
+ public static final String ROUTE_3_NAME = "route_3_name";
+ /** 3rd route concurrency colour. */
+ public static final String ROUTE_3_COLOUR = "route_3_colour";
+ /** 4th route concurrency network. */
+ public static final String ROUTE_4_NETWORK = "route_4_network";
+ /** 4th route concurrency ref. */
+ public static final String ROUTE_4_REF = "route_4_ref";
+ /** 4th route concurrency name. */
+ public static final String ROUTE_4_NAME = "route_4_name";
+ /** 4th route concurrency colour. */
+ public static final String ROUTE_4_COLOUR = "route_4_colour";
+ /** 5th route concurrency network. */
+ public static final String ROUTE_5_NETWORK = "route_5_network";
+ /** 5th route concurrency ref. */
+ public static final String ROUTE_5_REF = "route_5_ref";
+ /** 5th route concurrency name. */
+ public static final String ROUTE_5_NAME = "route_5_name";
+ /** 5th route concurrency colour. */
+ public static final String ROUTE_5_COLOUR = "route_5_colour";
+ /** 6th route concurrency network. */
+ public static final String ROUTE_6_NETWORK = "route_6_network";
+ /** 6th route concurrency ref. */
+ public static final String ROUTE_6_REF = "route_6_ref";
+ /** 6th route concurrency name. */
+ public static final String ROUTE_6_NAME = "route_6_name";
+ /** 6th route concurrency colour. */
+ public static final String ROUTE_6_COLOUR = "route_6_colour";
}
/** Attribute values for map elements in the transportation_name layer. */
final class FieldValues {
@@ -1534,11 +1603,20 @@ default String name() {
/** Attribute names for map elements in the place layer. */
final class Fields {
- /** The OSM name
value of the POI. */
+ /**
+ * The OSM name
value of the place.
+ * Language-specific values are in name:xx
.
+ */
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
@@ -1561,7 +1639,8 @@ final class Fields {
* Original value of the place
tag.
* Distinguish between continents, countries, states, islands and places like settlements or smaller entities. Use
* class to separately style the different places and build a text hierarchy according to their
- * importance.
+ * importance. For places derived from boundaries, the original value of the
+ * boundary
tag.
*
* allowed values:
*
@@ -1579,6 +1658,7 @@ final class Fields {
* - "neighbourhood"
*
- "isolated_dwelling"
*
- "island"
+ *
- "aboriginal_lands"
*
*/
public static final String CLASS = "class";
@@ -1617,8 +1697,10 @@ final class FieldValues {
public static final String CLASS_NEIGHBOURHOOD = "neighbourhood";
public static final String CLASS_ISOLATED_DWELLING = "isolated_dwelling";
public static final String CLASS_ISLAND = "island";
- public static final Set CLASS_VALUES = Set.of("continent", "country", "state", "province", "city", "town",
- "village", "hamlet", "borough", "suburb", "quarter", "neighbourhood", "isolated_dwelling", "island");
+ public static final String CLASS_ABORIGINAL_LANDS = "aboriginal_lands";
+ public static final Set CLASS_VALUES =
+ Set.of("continent", "country", "state", "province", "city", "town", "village", "hamlet", "borough", "suburb",
+ "quarter", "neighbourhood", "isolated_dwelling", "island", "aboriginal_lands");
}
/** Complex mappings to generate attribute values from OSM element tags in the place layer. */
final class FieldMappings {
@@ -1677,11 +1759,20 @@ default String name() {
/** Attribute names for map elements in the poi layer. */
final class Fields {
- /** The OSM name
value of the POI. */
+ /**
+ * The OSM name
value of the POI.
+ * Language-specific values are in name:xx
.
+ */
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
@@ -1835,12 +1926,13 @@ final class FieldMappings {
public static final MultiExpression Class = MultiExpression.of(List.of(
MultiExpression.entry("shop",
matchAny("subclass", "accessories", "antiques", "beauty", "bed", "boutique", "camera", "carpet", "charity",
- "chemist", "coffee", "computer", "convenience", "copyshop", "cosmetics", "garden_centre", "doityourself",
- "erotic", "electronics", "fabric", "florist", "frozen_food", "furniture", "video_games", "video", "general",
- "gift", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk",
- "locksmith", "lamps", "mall", "massage", "motorcycle", "mobile_phone", "newsagent", "optician", "outdoor",
- "paint", "perfumery", "perfume", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "tailor",
- "tattoo", "ticket", "tobacco", "toys", "travel_agency", "watches", "weapons", "wholesale")),
+ "chemist", "chocolate", "coffee", "computer", "convenience", "confectionery", "copyshop", "cosmetics",
+ "garden_centre", "doityourself", "erotic", "electronics", "fabric", "florist", "frozen_food", "furniture",
+ "video_games", "video", "general", "gift", "hardware", "hearing_aids", "hifi", "interior_decoration",
+ "jewelry", "kiosk", "locksmith", "lamps", "mall", "massage", "motorcycle", "mobile_phone", "newsagent",
+ "optician", "outdoor", "paint", "perfumery", "perfume", "pet", "photo", "second_hand", "shoes", "sports",
+ "stationery", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "watches", "weapons",
+ "wholesale")),
MultiExpression.entry("office",
matchAny("subclass", "accountant", "advertising_agency", "architect", "association", "bail_bond_agent",
"charity", "company", "construction_company", "consulting", "cooperative", "courier", "coworking",
@@ -1872,7 +1964,7 @@ final class FieldMappings {
MultiExpression.entry("lodging",
matchAny("subclass", "hotel", "motel", "bed_and_breakfast", "guest_house", "hostel", "chalet", "alpine_hut",
"dormitory")),
- MultiExpression.entry("ice_cream", matchAny("subclass", "chocolate", "confectionery")),
+ MultiExpression.entry("ice_cream", matchAny("subclass", "ice_cream")),
MultiExpression.entry("post", matchAny("subclass", "post_box", "post_office", "parcel_locker")),
MultiExpression.entry("cafe", matchAny("subclass", "cafe")),
MultiExpression.entry("school", matchAny("subclass", "school", "kindergarten")),
@@ -1911,11 +2003,20 @@ default String name() {
/** Attribute names for map elements in the aerodrome_label layer. */
final class Fields {
- /** The OSM name
value of the aerodrome. */
+ /**
+ * The OSM name
value of the aerodrome.
+ * Language-specific values are in name:xx
.
+ */
public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
+ /**
+ * English name name:en
if available, otherwise name
. This is deprecated and will be
+ * removed in a future release in favor of name:en
.
+ */
public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
+ /**
+ * German name name:de
if available, otherwise name
or name:en
. This is
+ * deprecated and will be removed in a future release in favor of name:de
.
+ */
public static final String NAME_DE = "name_de";
/**
diff --git a/src/main/java/org/openmaptiles/generated/Tables.java b/src/main/java/org/openmaptiles/generated/Tables.java
index 1d2458ed..88fa4ec2 100644
--- a/src/main/java/org/openmaptiles/generated/Tables.java
+++ b/src/main/java/org/openmaptiles/generated/Tables.java
@@ -248,8 +248,9 @@ public OsmParkPolygon(SourceFeature source, String mappingKey) {
}
/** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(matchAny("leisure", "nature_reserve"),
- matchAny("boundary", "national_park", "protected_area", "aboriginal_lands")), matchType("polygon"));
+ public static final Expression MAPPING =
+ and(or(matchAny("leisure", "nature_reserve"), matchAny("boundary", "national_park", "protected_area")),
+ matchType("polygon"));
/**
* Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
@@ -259,6 +260,25 @@ public interface Handler {
void process(OsmParkPolygon element, FeatureCollector features);
}
}
+ /** An OSM element that would appear in the {@code osm_boundary_polygon} table generated by imposm3. */
+ public record OsmBoundaryPolygon(@Override String name, @Override String boundary, @Override SourceFeature source)
+ implements Row, WithName, WithBoundary, WithSource {
+ public OsmBoundaryPolygon(SourceFeature source, String mappingKey) {
+ this(source.getString("name"), source.getString("boundary"), source);
+ }
+
+ /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
+ public static final Expression MAPPING =
+ and(matchAny("boundary", "aboriginal_lands"), matchAny("type", "boundary"), matchType("polygon"));
+
+ /**
+ * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
+ * {@link OsmBoundaryPolygon}.
+ */
+ public interface Handler {
+ void process(OsmBoundaryPolygon element, FeatureCollector features);
+ }
+ }
/** An OSM element that would appear in the {@code osm_aeroway_polygon} table generated by imposm3. */
public record OsmAerowayPolygon(@Override String ref, @Override String aeroway, @Override SourceFeature source)
implements Row, WithRef, WithAeroway, WithSource {
@@ -320,24 +340,23 @@ public interface Handler {
public record OsmHighwayLinestring(@Override String highway, @Override String construction,
@Override String tracktype, @Override String ref, @Override String network, @Override int zOrder,
@Override long layer, @Override long level, @Override boolean indoor, @Override String name,
- @Override String nameEn, @Override String nameDe, @Override String shortName, @Override boolean isTunnel,
- @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord, @Override int isOneway,
- @Override boolean isArea, @Override String service, @Override String access, @Override boolean toll,
- @Override String usage, @Override String publicTransport, @Override String manMade, @Override String bicycle,
- @Override String foot, @Override String horse, @Override String mtbScale, @Override String sacScale,
- @Override String surface, @Override boolean expressway, @Override SourceFeature source)
+ @Override String nameEn, @Override String nameDe, @Override boolean isTunnel, @Override boolean isBridge,
+ @Override boolean isRamp, @Override boolean isFord, @Override int isOneway, @Override boolean isArea,
+ @Override String service, @Override String access, @Override boolean toll, @Override String usage,
+ @Override String publicTransport, @Override String manMade, @Override String bicycle, @Override String foot,
+ @Override String horse, @Override String mtbScale, @Override String sacScale, @Override String surface,
+ @Override boolean expressway, @Override SourceFeature source)
implements Row, WithHighway, WithConstruction, WithTracktype, WithRef, WithNetwork, WithZOrder, WithLayer,
- WithLevel, WithIndoor, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel, WithIsBridge, WithIsRamp,
- WithIsFord, WithIsOneway, WithIsArea, WithService, WithAccess, WithToll, WithUsage, WithPublicTransport,
- WithManMade, WithBicycle, WithFoot, WithHorse, WithMtbScale, WithSacScale, WithSurface, WithExpressway, WithSource {
+ WithLevel, WithIndoor, WithName, WithNameEn, WithNameDe, WithIsTunnel, WithIsBridge, WithIsRamp, WithIsFord,
+ WithIsOneway, WithIsArea, WithService, WithAccess, WithToll, WithUsage, WithPublicTransport, WithManMade,
+ WithBicycle, WithFoot, WithHorse, WithMtbScale, WithSacScale, WithSurface, WithExpressway, WithSource {
public OsmHighwayLinestring(SourceFeature source, String mappingKey) {
this(source.getString("highway"), source.getString("construction"), source.getString("tracktype"),
source.getString("ref"), source.getString("network"), source.getWayZorder(), source.getLong("layer"),
source.getLong("level"), source.getBoolean("indoor"), source.getString("name"), source.getString("name:en"),
- source.getString("name:de"), source.getString("short_name"), source.getBoolean("tunnel"),
- source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
- source.getString("access"), source.getBoolean("toll"), source.getString("usage"),
+ source.getString("name:de"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
+ source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"),
+ source.getString("service"), source.getString("access"), source.getBoolean("toll"), source.getString("usage"),
source.getString("public_transport"), source.getString("man_made"), source.getString("bicycle"),
source.getString("foot"), source.getString("horse"), source.getString("mtb:scale"),
source.getString("sac_scale"), source.getString("surface"), source.getBoolean("expressway"), source);
@@ -363,17 +382,17 @@ public interface Handler {
/** An OSM element that would appear in the {@code osm_railway_linestring} table generated by imposm3. */
public record OsmRailwayLinestring(@Override String railway, @Override String ref, @Override String network,
@Override int zOrder, @Override long layer, @Override long level, @Override boolean indoor, @Override String name,
- @Override String nameEn, @Override String nameDe, @Override String shortName, @Override boolean isTunnel,
- @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord, @Override boolean isArea,
- @Override String service, @Override String usage, @Override SourceFeature source) implements Row, WithRailway,
- WithRef, WithNetwork, WithZOrder, WithLayer, WithLevel, WithIndoor, WithName, WithNameEn, WithNameDe, WithShortName,
- WithIsTunnel, WithIsBridge, WithIsRamp, WithIsFord, WithIsArea, WithService, WithUsage, WithSource {
+ @Override String nameEn, @Override String nameDe, @Override boolean isTunnel, @Override boolean isBridge,
+ @Override boolean isRamp, @Override boolean isFord, @Override boolean isArea, @Override String service,
+ @Override String usage, @Override SourceFeature source) implements Row, WithRailway, WithRef, WithNetwork,
+ WithZOrder, WithLayer, WithLevel, WithIndoor, WithName, WithNameEn, WithNameDe, WithIsTunnel, WithIsBridge,
+ WithIsRamp, WithIsFord, WithIsArea, WithService, WithUsage, WithSource {
public OsmRailwayLinestring(SourceFeature source, String mappingKey) {
this(source.getString("railway"), source.getString("ref"), source.getString("network"), source.getWayZorder(),
source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getBoolean("area"), source.getString("service"), source.getString("usage"), source);
+ source.getString("name:en"), source.getString("name:de"), source.getBoolean("tunnel"),
+ source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getBoolean("area"),
+ source.getString("service"), source.getString("usage"), source);
}
/** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
@@ -391,16 +410,15 @@ public interface Handler {
}
/** An OSM element that would appear in the {@code osm_aerialway_linestring} table generated by imposm3. */
public record OsmAerialwayLinestring(@Override String aerialway, @Override int zOrder, @Override long layer,
- @Override String name, @Override String nameEn, @Override String nameDe, @Override String shortName,
- @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord,
- @Override int isOneway, @Override boolean isArea, @Override String service, @Override String usage,
- @Override SourceFeature source)
- implements Row, WithAerialway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel,
- WithIsBridge, WithIsRamp, WithIsFord, WithIsOneway, WithIsArea, WithService, WithUsage, WithSource {
+ @Override String name, @Override String nameEn, @Override String nameDe, @Override boolean isTunnel,
+ @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord, @Override int isOneway,
+ @Override boolean isArea, @Override String service, @Override String usage, @Override SourceFeature source)
+ implements Row, WithAerialway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithIsTunnel, WithIsBridge,
+ WithIsRamp, WithIsFord, WithIsOneway, WithIsArea, WithService, WithUsage, WithSource {
public OsmAerialwayLinestring(SourceFeature source, String mappingKey) {
this(source.getString("aerialway"), source.getWayZorder(), source.getLong("layer"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
+ source.getString("name:en"), source.getString("name:de"), source.getBoolean("tunnel"),
+ source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
source.getString("usage"), source);
}
@@ -419,16 +437,16 @@ public interface Handler {
}
/** An OSM element that would appear in the {@code osm_shipway_linestring} table generated by imposm3. */
public record OsmShipwayLinestring(@Override String shipway, @Override int zOrder, @Override long layer,
- @Override String name, @Override String nameEn, @Override String nameDe, @Override String shortName,
- @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord,
- @Override boolean isArea, @Override String service, @Override String usage, @Override SourceFeature source)
- implements Row, WithShipway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel,
- WithIsBridge, WithIsRamp, WithIsFord, WithIsArea, WithService, WithUsage, WithSource {
+ @Override String name, @Override String nameEn, @Override String nameDe, @Override boolean isTunnel,
+ @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord, @Override boolean isArea,
+ @Override String service, @Override String usage, @Override SourceFeature source)
+ implements Row, WithShipway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithIsTunnel, WithIsBridge,
+ WithIsRamp, WithIsFord, WithIsArea, WithService, WithUsage, WithSource {
public OsmShipwayLinestring(SourceFeature source, String mappingKey) {
this(source.getString("route"), source.getWayZorder(), source.getLong("layer"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getBoolean("area"), source.getString("service"), source.getString("usage"), source);
+ source.getString("name:en"), source.getString("name:de"), source.getBoolean("tunnel"),
+ source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getBoolean("area"),
+ source.getString("service"), source.getString("usage"), source);
}
/** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
@@ -1236,11 +1254,6 @@ public interface WithShipway {
String shipway();
}
- /** Rows with a String shortName attribute. */
- public interface WithShortName {
- String shortName();
- }
-
/** Rows with a SourceFeature source attribute. */
public interface WithSource {
SourceFeature source();
@@ -1331,6 +1344,8 @@ public interface WithZOrder {
OsmMountainLinestring.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmParkPolygon.class, OsmParkPolygon::new),
OsmParkPolygon.MAPPING),
+ MultiExpression.entry(new RowClassAndConstructor(OsmBoundaryPolygon.class, OsmBoundaryPolygon::new),
+ OsmBoundaryPolygon.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmAerowayPolygon.class, OsmAerowayPolygon::new),
OsmAerowayPolygon.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmAerowayLinestring.class, OsmAerowayLinestring::new),
@@ -1406,6 +1421,10 @@ public static Map, List>> generateDis
result.computeIfAbsent(OsmParkPolygon.class, cls -> new ArrayList<>())
.add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
}
+ if (handler instanceof OsmBoundaryPolygon.Handler typedHandler) {
+ result.computeIfAbsent(OsmBoundaryPolygon.class, cls -> new ArrayList<>())
+ .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
+ }
if (handler instanceof OsmAerowayPolygon.Handler typedHandler) {
result.computeIfAbsent(OsmAerowayPolygon.class, cls -> new ArrayList<>())
.add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
diff --git a/src/main/java/org/openmaptiles/layers/Boundary.java b/src/main/java/org/openmaptiles/layers/Boundary.java
index 83f7f62e..99a29977 100644
--- a/src/main/java/org/openmaptiles/layers/Boundary.java
+++ b/src/main/java/org/openmaptiles/layers/Boundary.java
@@ -79,6 +79,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
import org.locationtech.jts.operation.polygonize.Polygonizer;
import org.openmaptiles.OpenMapTilesProfile;
import org.openmaptiles.generated.OpenMapTilesSchema;
+import org.openmaptiles.generated.Tables;
+import org.openmaptiles.util.OmtLanguageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -95,6 +97,7 @@ public class Boundary implements
OpenMapTilesProfile.NaturalEarthProcessor,
OpenMapTilesProfile.OsmRelationPreprocessor,
OpenMapTilesProfile.OsmAllProcessor,
+ Tables.OsmBoundaryPolygon.Handler,
OpenMapTilesProfile.FeaturePostProcessor,
OpenMapTilesProfile.FinishHandler {
@@ -127,6 +130,7 @@ public class Boundary implements
private final Map> regionGeometries = new HashMap<>();
private final Map> boundariesToMerge = new HashMap<>();
private final PlanetilerConfig config;
+ private final Translations translations;
public Boundary(Translations translations, PlanetilerConfig config, Stats stats) {
this.config = config;
@@ -141,6 +145,7 @@ public Boundary(Translations translations, PlanetilerConfig config, Stats stats)
false
);
this.stats = stats;
+ this.translations = translations;
}
private static boolean isDisputed(Map tags) {
@@ -306,6 +311,15 @@ public void processAllOsm(SourceFeature feature, FeatureCollector features) {
}
}
+ @Override
+ public void process(Tables.OsmBoundaryPolygon element, FeatureCollector features) {
+ features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
+ .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);
+ }
+
@Override
public void finish(String sourceName, FeatureCollector.Factory featureCollectors,
Consumer emit) {
diff --git a/src/main/java/org/openmaptiles/layers/Park.java b/src/main/java/org/openmaptiles/layers/Park.java
index 026f1f62..648df0f3 100644
--- a/src/main/java/org/openmaptiles/layers/Park.java
+++ b/src/main/java/org/openmaptiles/layers/Park.java
@@ -91,20 +91,15 @@ public Park(Translations translations, PlanetilerConfig config, Stats stats) {
@Override
public void process(Tables.OsmParkPolygon element, FeatureCollector features) {
- String clazz;
- if ("aboriginal_lands".equals(element.boundary())) {
- clazz = "aboriginal_lands";
- } else {
- String protectionTitle = element.protectionTitle();
- if (protectionTitle != null) {
- protectionTitle = protectionTitle.replace(' ', '_').toLowerCase(Locale.ROOT);
- }
- clazz = coalesce(
- nullIfEmpty(protectionTitle),
- nullIfEmpty(element.boundary()),
- nullIfEmpty(element.leisure())
- );
+ String protectionTitle = element.protectionTitle();
+ if (protectionTitle != null) {
+ protectionTitle = protectionTitle.replace(' ', '_').toLowerCase(Locale.ROOT);
}
+ String clazz = coalesce(
+ nullIfEmpty(protectionTitle),
+ nullIfEmpty(element.boundary()),
+ nullIfEmpty(element.leisure())
+ );
// park shape
var outline = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
diff --git a/src/main/java/org/openmaptiles/layers/Place.java b/src/main/java/org/openmaptiles/layers/Place.java
index ed1e5221..f764d15f 100644
--- a/src/main/java/org/openmaptiles/layers/Place.java
+++ b/src/main/java/org/openmaptiles/layers/Place.java
@@ -88,6 +88,7 @@ public class Place implements
Tables.OsmIslandPoint.Handler,
Tables.OsmIslandPolygon.Handler,
Tables.OsmCityPoint.Handler,
+ Tables.OsmBoundaryPolygon.Handler,
OpenMapTilesProfile.FeaturePostProcessor {
/*
@@ -96,8 +97,10 @@ public class Place implements
* and minimum zoom level to use for those points.
*/
- private static final TreeMap ISLAND_AREA_RANKS = new TreeMap<>(Map.of(
- Double.MAX_VALUE, 3,
+ private static final TreeMap AREA_RANKS = new TreeMap<>(Map.of(
+ Double.MAX_VALUE, 1,
+ squareMetersToWorldArea(640_000_000), 2,
+ squareMetersToWorldArea(160_000_000), 3,
squareMetersToWorldArea(40_000_000), 4,
squareMetersToWorldArea(15_000_000), 5,
squareMetersToWorldArea(1_000_000), 6
@@ -282,7 +285,7 @@ public void process(Tables.OsmStatePoint element, FeatureCollector features) {
public void process(Tables.OsmIslandPolygon element, FeatureCollector features) {
try {
double area = element.source().area();
- int rank = ISLAND_AREA_RANKS.ceilingEntry(area).getValue();
+ int rank = AREA_RANKS.ceilingEntry(area).getValue();
int minzoom = rank <= 3 ? 8 : rank <= 4 ? 9 : 10;
features.pointOnSurface(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
@@ -369,6 +372,23 @@ public void process(Tables.OsmCityPoint element, FeatureCollector features) {
}
}
+ @Override
+ public void process(Tables.OsmBoundaryPolygon element, FeatureCollector features) {
+ try {
+ int rank = AREA_RANKS.ceilingEntry(element.source().area()).getValue();
+ int minzoom = rank <= 4 ? rank + 5 : 10;
+
+ features.pointOnSurface(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
+ .putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
+ .setAttr(OpenMapTilesSchema.Boundary.Fields.CLASS, element.boundary())
+ .setAttr(Fields.RANK, rank)
+ .setMinZoom(minzoom);
+ } catch (GeometryException e) {
+ e.log(stats, "omt_boundary_poly",
+ "Unable to get point for OSM boundary polygon " + element.source().id());
+ }
+ }
+
@Override
public List postProcess(int zoom, List items) {
// infer the rank field from ordering of the place labels with each label grid square
diff --git a/src/main/java/org/openmaptiles/layers/Poi.java b/src/main/java/org/openmaptiles/layers/Poi.java
index b2b9aba1..e511cc50 100644
--- a/src/main/java/org/openmaptiles/layers/Poi.java
+++ b/src/main/java/org/openmaptiles/layers/Poi.java
@@ -139,6 +139,11 @@ static int poiClassRank(String clazz) {
}
private String poiClass(String subclass, String mappingKey) {
+ // Special case subclass collision between office=university and amenity=university
+ if ("amenity".equals(mappingKey) && "university".equals(subclass)) {
+ return FieldValues.CLASS_COLLEGE;
+ }
+
subclass = coalesce(subclass, "");
return classMapping.getOrElse(Map.of(
"subclass", subclass,
diff --git a/src/main/java/org/openmaptiles/layers/Transportation.java b/src/main/java/org/openmaptiles/layers/Transportation.java
index 4aa898ef..ba828a44 100644
--- a/src/main/java/org/openmaptiles/layers/Transportation.java
+++ b/src/main/java/org/openmaptiles/layers/Transportation.java
@@ -142,7 +142,9 @@ public class Transportation implements
private static final Set TRUNK_AS_MOTORWAY_BY_NETWORK = Set.of(
RouteNetwork.CA_TRANSCANADA,
RouteNetwork.CA_PROVINCIAL_ARTERIAL,
- RouteNetwork.US_INTERSTATE
+ RouteNetwork.US_INTERSTATE,
+ RouteNetwork.E_ROAD,
+ RouteNetwork.A_ROAD
);
private static final Set CA_AB_PRIMARY_AS_ARTERIAL_BY_REF = Set.of(
"2", "3", "4"
@@ -290,8 +292,15 @@ public List preprocessOsmRelation(OsmElement.Relation relation)
RouteNetwork networkType = null;
String network = relation.getString("network");
String ref = relation.getString("ref");
-
- if ("US:I".equals(network)) {
+ String name = nullIfEmpty(relation.getString("name"));
+ String colour = coalesce(
+ nullIfEmpty(relation.getString("colour")), nullIfEmpty(relation.getString("ref:colour")));
+
+ if ("e-road".equals(network)) {
+ networkType = RouteNetwork.E_ROAD;
+ } else if ("AsianHighway".equals(network)) {
+ networkType = RouteNetwork.A_ROAD;
+ } else if ("US:I".equals(network)) {
networkType = RouteNetwork.US_INTERSTATE;
} else if ("US:US".equals(network)) {
networkType = RouteNetwork.US_HIGHWAY;
@@ -328,7 +337,8 @@ public List preprocessOsmRelation(OsmElement.Relation relation)
};
if (network != null || rank < 3) {
- return List.of(new RouteRelation(coalesce(ref, ""), network, networkType, (byte) rank, relation.id()));
+ return List
+ .of(new RouteRelation(coalesce(ref, ""), network, name, colour, networkType, (byte) rank, relation.id()));
}
}
return null;
@@ -366,6 +376,7 @@ List getRouteRelations(Tables.OsmHighwayLinestring element) {
};
result.add(new RouteRelation(refMatcher.group(),
networkType == null ? null : networkType.network,
+ null, null,
networkType, (byte) -1, 0));
}
} catch (GeometryException e) {
@@ -391,7 +402,9 @@ List getRouteRelations(Tables.OsmHighwayLinestring element) {
case "trunk", "primary" -> RouteNetwork.IE_NATIONAL;
default -> RouteNetwork.IE_REGIONAL;
};
- result.add(new RouteRelation(refMatcher.group(), networkType.network, networkType, (byte) -1, 0));
+ result.add(new RouteRelation(refMatcher.group(),
+ networkType.network, null, null,
+ networkType, (byte) -1, 0));
}
} catch (GeometryException e) {
e.log(stats, "omt_transportation_name_ie_test",
@@ -406,7 +419,7 @@ List getRouteRelations(Tables.OsmHighwayLinestring element) {
RouteRelation getRouteRelation(Tables.OsmHighwayLinestring element) {
List all = getRouteRelations(element);
- return all.isEmpty() ? null : all.get(0);
+ return all.isEmpty() ? null : all.getFirst();
}
@Override
@@ -436,6 +449,8 @@ public void process(Tables.OsmHighwayLinestring element, FeatureCollector featur
Integer rampAboveZ12 = (highwayRamp || element.isRamp()) ? 1 : null;
Integer rampBelowZ12 = highwayRamp ? 1 : null;
+ boolean expressway = element.expressway() && !"motorway".equals(highway) && !(element.isRamp() || highwayRamp);
+
FeatureCollector.Feature feature = features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
// main attributes at all zoom levels (used for grouping <= z8)
.setAttr(Fields.CLASS, highwayClass)
@@ -443,7 +458,7 @@ public void process(Tables.OsmHighwayLinestring element, FeatureCollector featur
.setAttr(Fields.NETWORK, networkType != null ? networkType.name : null)
.setAttrWithMinSize(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()), 4, 4, 12)
// z8+
- .setAttrWithMinzoom(Fields.EXPRESSWAY, element.expressway() && !"motorway".equals(highway) ? 1 : null, 8)
+ .setAttrWithMinzoom(Fields.EXPRESSWAY, expressway ? 1 : null, 8)
// z9+
.setAttrWithMinSize(Fields.LAYER, nullIfLong(element.layer(), 0), 4, 9, 12)
.setAttrWithMinzoom(Fields.BICYCLE, nullIfEmpty(element.bicycle()), 9)
@@ -643,7 +658,9 @@ enum RouteNetwork {
GB_PRIMARY("gb-primary", "omt-gb-primary"),
IE_MOTORWAY("ie-motorway", "omt-ie-motorway"),
IE_NATIONAL("ie-national", "omt-ie-national"),
- IE_REGIONAL("ie-regional", "omt-ie-regional");
+ IE_REGIONAL("ie-regional", "omt-ie-regional"),
+ E_ROAD("e-road", null),
+ A_ROAD("a-road", null);
final String name;
final String network;
@@ -658,6 +675,8 @@ enum RouteNetwork {
record RouteRelation(
String ref,
String network,
+ String name,
+ String colour,
RouteNetwork networkType,
byte rank,
@Override long id
@@ -669,6 +688,8 @@ public long estimateMemoryUsageBytes() {
MemoryEstimator.estimateSize(rank) +
POINTER_BYTES + estimateSize(ref) +
POINTER_BYTES + estimateSize(network) +
+ POINTER_BYTES + estimateSize(name) +
+ POINTER_BYTES + estimateSize(colour) +
POINTER_BYTES + // networkType
MemoryEstimator.estimateSizeLong(id);
}
diff --git a/src/main/java/org/openmaptiles/layers/TransportationName.java b/src/main/java/org/openmaptiles/layers/TransportationName.java
index 4e8fefd8..2ac9f400 100644
--- a/src/main/java/org/openmaptiles/layers/TransportationName.java
+++ b/src/main/java/org/openmaptiles/layers/TransportationName.java
@@ -113,6 +113,11 @@ public class TransportationName implements
.put(9, 8_000)
.put(10, 4_000)
.put(11, 2_000);
+ private static final ZoomFunction BUFFER_PIXEL_OVERRIDES =
+ ZoomFunction.fromMaxZoomThresholds(Map.of(
+ 13, 256,
+ 6, 256
+ ));
private final boolean brunnel;
private final boolean sizeForShield;
private final boolean limitMerge;
@@ -255,7 +260,7 @@ public void process(Tables.OsmHighwayLinestring element, FeatureCollector featur
FeatureCollector.Feature feature = features.line(LAYER_NAME)
.setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
+ .setBufferPixelOverrides(BUFFER_PIXEL_OVERRIDES)
// TODO abbreviate road names - can't port osml10n because it is AGPL
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(Fields.REF, ref)
@@ -269,12 +274,20 @@ public void process(Tables.OsmHighwayLinestring element, FeatureCollector featur
.setSortKey(element.zOrder())
.setMinZoom(minzoom);
- // populate route_1, route_2, ... route_n tags and remove duplicates
+ // populate route_1_, route_2_, ... route_n_ tags and remove duplicates
Set routes = new HashSet<>();
for (var route : relations) {
- String routeString = route.network() + "=" + coalesce(route.ref(), "");
+ String routeString = route.network() + "=" +
+ coalesce(route.ref(), "") + "=" +
+ coalesce(route.name(), "") + "=" +
+ coalesce(route.colour(), "");
if (routes.add(routeString)) {
- feature.setAttr("route_" + routes.size(), routeString);
+ String keyPrefix = "route_" + routes.size() + "_";
+
+ feature.setAttr(keyPrefix + "network", route.network());
+ feature.setAttr(keyPrefix + "ref", nullIfEmpty(route.ref()));
+ feature.setAttr(keyPrefix + "name", route.name());
+ feature.setAttr(keyPrefix + "colour", route.colour());
}
}
@@ -308,7 +321,7 @@ public void process(Tables.OsmAerialwayLinestring element, FeatureCollector feat
if (!nullOrEmpty(element.name())) {
features.line(LAYER_NAME)
.setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
+ .setBufferPixelOverrides(BUFFER_PIXEL_OVERRIDES)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(Fields.CLASS, "aerialway")
.setAttr(Fields.SUBCLASS, element.aerialway())
@@ -323,7 +336,7 @@ public void process(Tables.OsmShipwayLinestring element, FeatureCollector featur
if (!nullOrEmpty(element.name())) {
features.line(LAYER_NAME)
.setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
+ .setBufferPixelOverrides(BUFFER_PIXEL_OVERRIDES)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(Fields.CLASS, element.shipway())
.setMinPixelSize(0)
diff --git a/src/main/java/org/openmaptiles/layers/WaterName.java b/src/main/java/org/openmaptiles/layers/WaterName.java
index cebaeffe..cd3a1a8b 100644
--- a/src/main/java/org/openmaptiles/layers/WaterName.java
+++ b/src/main/java/org/openmaptiles/layers/WaterName.java
@@ -83,11 +83,13 @@ public class WaterName implements
private static final Logger LOGGER = LoggerFactory.getLogger(WaterName.class);
private static final Set SEA_OR_OCEAN_PLACE = Set.of("sea", "ocean");
+ private static final double IMPORTANT_MARINE_REGIONS_JOIN_DISTANCE =
+ GeoUtils.metersToPixelAtEquator(0, 50_000) / 256d;
private final Translations translations;
// need to synchronize updates from multiple threads
private final LongObjectMap lakeCenterlines = Hppc.newLongObjectHashMap();
// may be updated concurrently by multiple threads
- private final ConcurrentSkipListMap importantMarinePoints = new ConcurrentSkipListMap<>();
+ private final ConcurrentSkipListMap importantMarinePoints = new ConcurrentSkipListMap<>();
private final Stats stats;
public WaterName(Translations translations, PlanetilerConfig config, Stats stats) {
@@ -133,11 +135,49 @@ public void processNaturalEarth(String table, SourceFeature feature, FeatureColl
Integer scalerank = Parse.parseIntOrNull(feature.getTag("scalerank"));
if (name != null && scalerank != null) {
name = name.replaceAll("\\s+", " ").trim().toLowerCase();
- importantMarinePoints.put(name, scalerank);
+ try {
+ importantMarinePoints.put(name, new NaturalEarthRegion(feature.worldGeometry(), scalerank));
+ } catch (GeometryException e) {
+ e.log(stats, "ne_marine_polys",
+ "Error getting geometry for natural earth feature " + table + " " + feature.getTag("ogc_fid"));
+ }
}
}
}
+ private NaturalEarthRegion getImportantMarineRegion(Tables.OsmMarinePoint element) {
+ var source = element.source();
+ String name = element.name().toLowerCase();
+ NaturalEarthRegion result = importantMarinePoints.get(name);
+ if (result == null) {
+ result = importantMarinePoints.get(source.getString("name:en", "").toLowerCase());
+ }
+ if (result == null) {
+ result = importantMarinePoints.get(source.getString("name:es", "").toLowerCase());
+ }
+ if (result == null) {
+ Map.Entry next = importantMarinePoints.ceilingEntry(name);
+ if (next != null && next.getKey().startsWith(name)) {
+ result = next.getValue();
+ }
+ }
+
+ if (result == null) {
+ return null;
+ }
+ try {
+ double distance = result.geometry.distance(source.worldGeometry());
+ if (distance <= IMPORTANT_MARINE_REGIONS_JOIN_DISTANCE) {
+ return result;
+ }
+ } catch (GeometryException e) {
+ e.log(stats, "osm_marine_point",
+ "Error getting geometry for OSM marine point " + element.source().id());
+ }
+
+ return null;
+ }
+
@Override
public void process(Tables.OsmMarinePoint element, FeatureCollector features) {
if (!element.name().isBlank()) {
@@ -148,29 +188,14 @@ public void process(Tables.OsmMarinePoint element, FeatureCollector features) {
var source = element.source();
// use name from OSM, but get min zoom from natural earth based on fuzzy name match...
Integer rank = Parse.parseIntOrNull(source.getTag("rank"));
- String name = element.name().toLowerCase();
- Integer nerank;
- if ((nerank = importantMarinePoints.get(name)) != null) {
- rank = nerank;
- } else if ((nerank = importantMarinePoints.get(source.getString("name:en", "").toLowerCase())) != null) {
- rank = nerank;
- } else if ((nerank = importantMarinePoints.get(source.getString("name:es", "").toLowerCase())) != null) {
- rank = nerank;
- } else {
- Map.Entry next = importantMarinePoints.ceilingEntry(name);
- if (next != null && next.getKey().startsWith(name)) {
- rank = next.getValue();
- }
+ NaturalEarthRegion neRegion = getImportantMarineRegion(element);
+ if (neRegion != null) {
+ rank = neRegion.scalerank;
}
int minZoom;
if ("ocean".equals(element.place())) {
minZoom = 0;
} else if (rank != null) {
- // FIXME: While this looks like matching properly stuff in https://github.com/openmaptiles/openmaptiles/pull/1457/files#diff-201daa1c61c99073fe3280d440c9feca5ed2236b251ad454caa14cc203f952d1R74 ,
- // it includes not just https://www.openstreetmap.org/relation/13360255 but also https://www.openstreetmap.org/node/1385157299 (and some others).
- // Hence check how that OpenMapTiles code works for "James Bay" and:
- // a) if same as here then, fix there and then here
- // b) if OK (while here NOK), fix only here
minZoom = rank;
} else if ("bay".equals(element.natural())) {
minZoom = 13;
@@ -220,4 +245,9 @@ public void process(Tables.OsmWaterPolygon element, FeatureCollector features) {
.setMinZoom(minzoom);
}
}
+
+ private record NaturalEarthRegion(
+ Geometry geometry,
+ int scalerank
+ ) {}
}
diff --git a/src/test/java/org/openmaptiles/layers/BoundaryTest.java b/src/test/java/org/openmaptiles/layers/BoundaryTest.java
index 931371b8..95e56d09 100644
--- a/src/test/java/org/openmaptiles/layers/BoundaryTest.java
+++ b/src/test/java/org/openmaptiles/layers/BoundaryTest.java
@@ -714,4 +714,26 @@ void testOsmBoundariesOnly() {
assertFeatures(14, List.of(Map.of("_minzoom", 1)),
processOsmOnly(lineFeatureWithRelation(profile.preprocessOsmRelation(relation), Map.of())));
}
+
+ @Test
+ void testIndigenousLand() {
+ assertFeatures(0, List.of(Map.of(
+ "_layer", "boundary",
+ "class", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "name_en", "Seminole Nation",
+ "name:latin", "Seminole Nation",
+
+ "_type", "polygon",
+ "_minzoom", 4
+ ), Map.of(
+ "_layer", "place"
+ )), process(polygonFeatureWithArea(1,
+ Map.of(
+ "type", "boundary",
+ "boundary", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "name:en", "Seminole Nation"
+ ))));
+ }
}
diff --git a/src/test/java/org/openmaptiles/layers/ParkTest.java b/src/test/java/org/openmaptiles/layers/ParkTest.java
index 2383a136..a393b211 100644
--- a/src/test/java/org/openmaptiles/layers/ParkTest.java
+++ b/src/test/java/org/openmaptiles/layers/ParkTest.java
@@ -45,30 +45,6 @@ void testNationalPark() {
))));
}
- @Test
- void testAbotiginalLand() {
- assertFeatures(13, List.of(Map.of(
- "_layer", "park",
- "_type", "polygon",
- "class", "aboriginal_lands",
- "name", "Hualapai Tribe",
- "_minpixelsize", 2d,
- "_minzoom", 4,
- "_maxzoom", 14
- ), Map.of(
- "_layer", "park",
- "_type", "point",
- "class", "aboriginal_lands",
- "name", "Hualapai Tribe",
- "_minzoom", 5,
- "_maxzoom", 14
- )), process(polygonFeature(Map.of(
- "boundary", "aboriginal_lands",
- "name", "Hualapai Tribe",
- "protection_title", "National Park"
- ))));
- }
-
@Test
void testSmallerPark() {
double z11area = Math.pow((GeoUtils.metersToPixelAtEquator(0, Math.sqrt(70_000)) / 256d), 2) * Math.pow(2, 20 - 11);
diff --git a/src/test/java/org/openmaptiles/layers/PlaceTest.java b/src/test/java/org/openmaptiles/layers/PlaceTest.java
index d12a6e46..02873f69 100644
--- a/src/test/java/org/openmaptiles/layers/PlaceTest.java
+++ b/src/test/java/org/openmaptiles/layers/PlaceTest.java
@@ -258,7 +258,7 @@ void testIslandPolygon() {
"name", "Nantucket",
"name_en", "Nantucket",
"name:latin", "Nantucket",
- "rank", 3,
+ "rank", 1,
"_type", "point",
"_minzoom", 8
@@ -287,6 +287,49 @@ void testIslandPolygon() {
))));
}
+ @Test
+ void testIndigenousLand() {
+ assertFeatures(0, List.of(Map.of(
+ "_layer", "place",
+ "class", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "name_en", "Seminole Nation",
+ "name:latin", "Seminole Nation",
+ "rank", 1,
+
+ "_type", "point",
+ "_minzoom", 6
+ ), Map.of(
+ "_layer", "boundary"
+ )), process(polygonFeatureWithArea(1,
+ Map.of(
+ "type", "boundary",
+ "boundary", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "name:en", "Seminole Nation"
+ ))));
+
+ double rank2area = Math.pow(GeoUtils.metersToPixelAtEquator(0, Math.sqrt(640_000_000 - 1)) / 256d, 2);
+
+ assertFeatures(0, List.of(Map.of(
+ "_layer", "place",
+ "class", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "rank", 2,
+
+ "_type", "point",
+ "_minzoom", 7
+ ), Map.of(
+ "_layer", "boundary"
+ )), process(polygonFeatureWithArea(rank2area,
+ Map.of(
+ "type", "boundary",
+ "boundary", "aboriginal_lands",
+ "name", "Seminole Nation",
+ "name:en", "Seminole Nation"
+ ))));
+ }
+
@Test
void testPlaceSortKeyRanking() {
int[] sortKeys = new int[]{
diff --git a/src/test/java/org/openmaptiles/layers/TransportationTest.java b/src/test/java/org/openmaptiles/layers/TransportationTest.java
index fe32a98f..2210aa65 100644
--- a/src/test/java/org/openmaptiles/layers/TransportationTest.java
+++ b/src/test/java/org/openmaptiles/layers/TransportationTest.java
@@ -3,6 +3,7 @@
import static com.onthegomap.planetiler.TestUtils.newLineString;
import static com.onthegomap.planetiler.TestUtils.newPoint;
import static com.onthegomap.planetiler.TestUtils.rectangle;
+import static java.util.Map.entry;
import static org.junit.jupiter.api.Assertions.assertFalse;
import com.onthegomap.planetiler.FeatureCollector;
@@ -280,17 +281,18 @@ void testInterstateMotorway() {
"horse", "no",
"brunnel", "bridge",
"_minzoom", 4
- ), Map.of(
- "_layer", "transportation_name",
- "class", "motorway",
- "name", "Massachusetts Turnpike",
- "name_en", "Massachusetts Turnpike",
- "ref", "90",
- "ref_length", 2,
- "network", "us-interstate",
- "route_1", "US:I=90",
- "brunnel", "",
- "_minzoom", 6
+ ), Map.ofEntries(
+ entry("_layer", "transportation_name"),
+ entry("class", "motorway"),
+ entry("name", "Massachusetts Turnpike"),
+ entry("name_en", "Massachusetts Turnpike"),
+ entry("ref", "90"),
+ entry("ref_length", 2),
+ entry("network", "us-interstate"),
+ entry("route_1_network", "US:I"),
+ entry("route_1_ref", "90"),
+ entry("brunnel", ""),
+ entry("_minzoom", 6)
)), features);
assertFeatures(8, List.of(Map.of(
@@ -304,17 +306,18 @@ void testInterstateMotorway() {
"horse", "",
"brunnel", "bridge",
"_minzoom", 4
- ), Map.of(
- "_layer", "transportation_name",
- "class", "motorway",
- "name", "Massachusetts Turnpike",
- "name_en", "Massachusetts Turnpike",
- "ref", "90",
- "ref_length", 2,
- "network", "us-interstate",
- "route_1", "US:I=90",
- "brunnel", "",
- "_minzoom", 6
+ ), Map.ofEntries(
+ entry("_layer", "transportation_name"),
+ entry("class", "motorway"),
+ entry("name", "Massachusetts Turnpike"),
+ entry("name_en", "Massachusetts Turnpike"),
+ entry("ref", "90"),
+ entry("ref_length", 2),
+ entry("network", "us-interstate"),
+ entry("route_1_network", "US:I"),
+ entry("route_1_ref", "90"),
+ entry("brunnel", ""),
+ entry("_minzoom", 6)
)), features);
}
@@ -326,7 +329,7 @@ void testDuplicateRoute() {
rel1.setTag("network", "US:OK");
rel1.setTag("ref", "104");
rel1.setTag("direction", "north");
- var rel2 = new OsmElement.Relation(2);
+ var rel2 = new OsmElement.Relation(1);
rel2.setTag("type", "route");
rel2.setTag("route", "road");
rel2.setTag("network", "US:OK");
@@ -357,8 +360,10 @@ void testDuplicateRoute() {
"ref", "104",
"ref_length", 3,
"network", "us-state",
- "route_1", "US:OK=104",
- "route_2", "",
+ "route_1_network", "US:OK",
+ "route_1_ref", "104",
+ "route_2_network", "",
+ "route_2_ref", "",
"_minzoom", 8
)), features);
}
@@ -372,7 +377,7 @@ void testRouteWithoutNetworkType() {
rel1.setTag("ref", "NJTP");
rel1.setTag("name", "New Jersey Turnpike (mainline)");
- var rel2 = new OsmElement.Relation(1);
+ var rel2 = new OsmElement.Relation(2);
rel2.setTag("type", "route");
rel2.setTag("route", "road");
rel2.setTag("network", "US:I");
@@ -400,8 +405,55 @@ void testRouteWithoutNetworkType() {
"name", "New Jersey Turnpike",
"ref", "95",
"ref_length", 2,
- "route_1", "US:I=95",
- "route_2", "US:NJ:NJTP=NJTP",
+ "route_1_network", "US:I",
+ "route_1_ref", "95",
+ "route_2_network", "US:NJ:NJTP",
+ "route_2_ref", "NJTP",
+ "_minzoom", 6
+ )), rendered);
+ }
+
+ @Test
+ void testRouteWithColour() {
+ var rel1 = new OsmElement.Relation(1);
+ rel1.setTag("type", "route");
+ rel1.setTag("route", "road");
+ rel1.setTag("network", "US:NJ:NJTP");
+ rel1.setTag("ref", "NJTP");
+ rel1.setTag("name", "New Jersey Turnpike (mainline)");
+ rel1.setTag("colour", "#FFFFFF");
+ rel1.setTag("ref:colour", "#888888");
+
+ var rel2 = new OsmElement.Relation(2);
+ rel2.setTag("type", "route");
+ rel2.setTag("route", "road");
+ rel2.setTag("network", "US:I");
+ rel2.setTag("ref", "95");
+ rel2.setTag("name", "I 95 (NJ)");
+ rel2.setTag("ref:colour", "#000000");
+
+ FeatureCollector rendered = process(lineFeatureWithRelation(
+ Stream.concat(
+ profile.preprocessOsmRelation(rel1).stream(),
+ profile.preprocessOsmRelation(rel2).stream()
+ ).toList(),
+ Map.of(
+ "highway", "motorway",
+ "name", "New Jersey Turnpike",
+ "ref", "I 95;NJTP"
+ )));
+
+ assertFeatures(13, List.of(mapOf(
+ "_layer", "transportation",
+ "class", "motorway",
+ "_minzoom", 4
+ ), Map.of(
+ "_layer", "transportation_name",
+ "class", "motorway",
+ "route_1_network", "US:I",
+ "route_1_colour", "#000000",
+ "route_2_network", "US:NJ:NJTP",
+ "route_2_colour", "#FFFFFF",
"_minzoom", 6
)), rendered);
}
@@ -411,7 +463,7 @@ void testSegmentWithManyRoutes() {
List relations = new ArrayList<>();
for (int route = 1; route <= 16; route++) {
int num = (route + 1) / 2; // to make dups
- var rel = new OsmElement.Relation(route);
+ var rel = new OsmElement.Relation(num);
rel.setTag("type", "route");
rel.setTag("route", "road");
rel.setTag("network", "US:I");
@@ -434,15 +486,24 @@ void testSegmentWithManyRoutes() {
"_minzoom", 4
), mapOf(
"_layer", "transportation_name",
- "route_1", "US:I=1",
- "route_2", "US:I=2",
- "route_3", "US:I=3",
- "route_4", "US:I=4",
- "route_5", "US:I=5",
- "route_6", "US:I=6",
- "route_7", "US:I=7",
- "route_8", "US:I=8",
- "route_9", ""
+ "route_1_network", "US:I",
+ "route_1_ref", "1",
+ "route_2_network", "US:I",
+ "route_2_ref", "2",
+ "route_3_network", "US:I",
+ "route_3_ref", "3",
+ "route_4_network", "US:I",
+ "route_4_ref", "4",
+ "route_5_network", "US:I",
+ "route_5_ref", "5",
+ "route_6_network", "US:I",
+ "route_6_ref", "6",
+ "route_7_network", "US:I",
+ "route_7_ref", "7",
+ "route_8_network", "US:I",
+ "route_8_ref", "8",
+ "route_9_network", "",
+ "route_9_ref", ""
)), rendered);
}
@@ -519,10 +580,12 @@ void testPolishHighwayIssue165() {
"_layer", "transportation_name",
"class", "trunk",
"name", "",
- "ref", "S7",
- "ref_length", 2,
- "route_1", "e-road=E 28",
- "route_2", "e-road=E 77"
+ "ref", "E 28",
+ "ref_length", 4,
+ "route_1_network", "e-road",
+ "route_1_ref", "E 28",
+ "route_2_network", "e-road",
+ "route_2_ref", "E 77"
)), rendered);
}
@@ -601,7 +664,8 @@ void testInterstateMotorwayWithoutWayInfo() {
"ref_length", 2,
"network", "us-interstate",
"brunnel", "",
- "route_1", "US:I=90",
+ "route_1_network", "US:I",
+ "route_1_ref", "90",
"_minzoom", 6
)), features);
}
@@ -839,17 +903,19 @@ void testUSAndStateHighway() {
"ramp", "",
"network", "us-highway",
"_minzoom", 7
- ), Map.of(
- "_layer", "transportation_name",
- "class", "primary",
- "name", "Memorial Drive",
- "name_en", "Memorial Drive",
- "ref", "3",
- "ref_length", 1,
- "network", "us-highway",
- "route_1", "US:US=3",
- "route_2", "US:MA=2",
- "_minzoom", 12
+ ), Map.ofEntries(
+ entry("_layer", "transportation_name"),
+ entry("class", "primary"),
+ entry("name", "Memorial Drive"),
+ entry("name_en", "Memorial Drive"),
+ entry("ref", "3"),
+ entry("ref_length", 1),
+ entry("network", "us-highway"),
+ entry("route_1_network", "US:US"),
+ entry("route_1_ref", "3"),
+ entry("route_2_network", "US:MA"),
+ entry("route_2_ref", "2"),
+ entry("_minzoom", 12)
)), process(lineFeatureWithRelation(
Stream.concat(
profile.preprocessOsmRelation(relUS).stream(),
@@ -869,8 +935,10 @@ void testUSAndStateHighway() {
), Map.of(
"_layer", "transportation_name",
"class", "primary",
- "route_1", "US:US=3",
- "route_2", "US:MA=2",
+ "route_1_network", "US:US",
+ "route_1_ref", "3",
+ "route_2_network", "US:MA",
+ "route_2_ref", "2",
"ref", "3",
"network", "us-highway"
)), process(lineFeatureWithRelation(
@@ -2041,4 +2109,58 @@ void testIssue58() {
"name:en", "Ayalon South"
)), result);
}
+
+ @Test
+ void testARoad() {
+ var rel = new OsmElement.Relation(1);
+ rel.setTag("type", "route");
+ rel.setTag("route", "road");
+ rel.setTag("network", "AsianHighway");
+ rel.setTag("ref", "AH11");
+
+ FeatureCollector features = process(lineFeatureWithRelation(
+ profile.preprocessOsmRelation(rel),
+ Map.of(
+ "highway", "trunk"
+ )));
+
+ assertFeatures(13, List.of(Map.of(
+ "_layer", "transportation",
+ "class", "trunk",
+ "network", "a-road",
+ "_minzoom", 4
+ ), Map.of(
+ "_layer", "transportation_name",
+ "class", "trunk",
+ "ref", "AH11",
+ "network", "a-road"
+ )), features);
+ }
+
+ @Test
+ void testERoad() {
+ var rel = new OsmElement.Relation(1);
+ rel.setTag("type", "route");
+ rel.setTag("route", "road");
+ rel.setTag("network", "e-road");
+ rel.setTag("ref", "E 50");
+
+ FeatureCollector features = process(lineFeatureWithRelation(
+ profile.preprocessOsmRelation(rel),
+ Map.of(
+ "highway", "motorway"
+ )));
+
+ assertFeatures(13, List.of(Map.of(
+ "_layer", "transportation",
+ "class", "motorway",
+ "network", "e-road",
+ "_minzoom", 4
+ ), Map.of(
+ "_layer", "transportation_name",
+ "class", "motorway",
+ "ref", "E 50",
+ "network", "e-road"
+ )), features);
+ }
}