diff --git a/README.md b/README.md index 9dd8026435..d5db2357dc 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ download regularly-updated tilesets. using [JTS geometry utilities](https://github.com/locationtech/jts) - Merge nearby lines or polygons with the same tags before emitting vector tiles - Automatically fixes self-intersecting polygons -- Built-in basemap profile based on [OpenMapTiles](https://openmaptiles.org/) v3.13 +- Built-in basemap profile based on [OpenMapTiles](https://openmaptiles.org/) v3.13.1 - Optionally download additional name translations for elements from Wikidata - Export real-time stats to a [prometheus push gateway](https://github.com/prometheus/pushgateway) using `--pushgateway=http://user:password@ip` argument (and a [grafana dashboard](grafana.json) for viewing) diff --git a/planetiler-basemap/README.md b/planetiler-basemap/README.md index c940b6d435..ec23b5d176 100644 --- a/planetiler-basemap/README.md +++ b/planetiler-basemap/README.md @@ -1,6 +1,6 @@ # Planetiler Basemap Profile -This basemap profile is based on [OpenMapTiles](https://github.com/openmaptiles/openmaptiles) v3.13. +This basemap profile is based on [OpenMapTiles](https://github.com/openmaptiles/openmaptiles) v3.13.1. See [README.md](../README.md) in the parent directory for instructions on how to run. ## Differences from OpenMapTiles @@ -11,6 +11,9 @@ See [README.md](../README.md) in the parent directory for instructions on how to lines, to revert this behavior set `--transportation-name-brunnel=true` - `rank` field on `mountain_peak` linestrings only has 3 levels (1: has wikipedia page and name, 2: has name, 3: no name or wikipedia page or name) +- `rank` field on `mountain_peak` linestrings only has 3 levels (1: has wikipedia page and name, 2: has name, 3: no name + or wikipedia page or name) +- `id` field on `water` polygons is only populated for openstreetmap lakes, not natural earth lakes at lower zoom levels ## Code Layout @@ -41,7 +44,7 @@ To run `Generate.java`, use [scripts/regenerate-openmaptiles.sh](../scripts/rege OpenMapTiles release tag: ```bash -./scripts/regenerate-openmaptiles.sh v3.13 +./scripts/regenerate-openmaptiles.sh v3.13.1 ``` Then follow the instructions it prints for reformatting generated code. @@ -49,7 +52,7 @@ Then follow the instructions it prints for reformatting generated code. If you want to regenerate from a different repository than the default openmaptiles, you can specify the url like this: ```bash -./scripts/regenerate-openmaptiles.sh v3.13 https://raw.githubusercontent.com/openmaptiles/openmaptiles/ +./scripts/regenerate-openmaptiles.sh v3.13.1 https://raw.githubusercontent.com/openmaptiles/openmaptiles/ ``` ## License and Attribution diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java index 9366af47fa..f6f7fbb4fa 100644 --- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java +++ b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java @@ -128,7 +128,7 @@ static JsonNode parseYaml(String string) { public static void main(String[] args) throws IOException { Arguments arguments = Arguments.fromArgsOrConfigFile(args); PlanetilerConfig planetilerConfig = PlanetilerConfig.from(arguments); - String tag = arguments.getString("tag", "openmaptiles tag to use", "v3.13"); + String tag = arguments.getString("tag", "openmaptiles tag to use", "v3.13.1"); String baseUrl = arguments.getString("base-url", "the url used to download the openmaptiles.yml", "https://raw.githubusercontent.com/openmaptiles/openmaptiles/"); String base = baseUrl + tag + "/"; diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java index f366f7e415..dc20317fb0 100644 --- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java +++ b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java @@ -49,14 +49,14 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE /** * All vector tile layer definitions, attributes, and allowed values generated from the - * OpenMapTiles vector tile schema - * v3.13. + * OpenMapTiles vector tile schema + * v3.13.1. */ @SuppressWarnings("unused") public class OpenMapTilesSchema { public static final String NAME = "OpenMapTiles"; public static final String DESCRIPTION = "A tileset showcasing all layers in OpenMapTiles. https://openmaptiles.org"; - public static final String VERSION = "3.13.0"; + public static final String VERSION = "3.13.1"; public static final String ATTRIBUTION = "© OpenMapTiles © OpenStreetMap contributors"; public static final List LANGUAGES = List.of("am", "ar", "az", "be", "bg", "br", "bs", "ca", "co", "cs", "cy", @@ -96,7 +96,7 @@ public static List createInstances(Translations translations, PlanetilerC * boundaries show up. So you might not be able to use border styling for ocean water features. * * Generated from - * water.yaml + * water.yaml */ public interface Water extends Layer { double BUFFER_SIZE = 4.0; @@ -109,6 +109,12 @@ default String name() { /** Attribute names for map elements in the water layer. */ final class Fields { + /** + * From zoom 6 are taken OSM IDs. Up to zoom 5 there are used Natural Earth lakes, where are propagated the OSM + * IDs insted of Natural Earth IDs. For smaller area then planet, NE lakes keep their Natural Earth IDs. + */ + public static final String ID = "id"; + /** * All water polygons from OpenStreetMapData have the class * ocean. Water bodies with the @@ -116,7 +122,9 @@ final class Fields { * water=river tag are classified as * river. Wet and dry docks tagged * waterway=dock are classified as - * a dock. All other water bodies are classified as lake. + * a dock. Swimming pools tagged + * leisure=swimming_pool + * are classified as a swimming_pool All other water bodies are classified as lake. *

* allowed values: *

*/ public static final String CLASS = "class"; @@ -157,7 +166,8 @@ final class FieldValues { public static final String CLASS_RIVER = "river"; public static final String CLASS_LAKE = "lake"; public static final String CLASS_OCEAN = "ocean"; - public static final Set CLASS_VALUES = Set.of("dock", "river", "lake", "ocean"); + public static final String CLASS_SWIMMING_POOL = "swimming_pool"; + public static final Set CLASS_VALUES = Set.of("dock", "river", "lake", "ocean", "swimming_pool"); public static final String BRUNNEL_BRIDGE = "bridge"; public static final String BRUNNEL_TUNNEL = "tunnel"; public static final Set BRUNNEL_VALUES = Set.of("bridge", "tunnel"); @@ -167,7 +177,8 @@ final class FieldMappings { public static final MultiExpression Class = MultiExpression.of(List.of(MultiExpression.entry("dock", matchAny("waterway", "dock")), MultiExpression.entry("river", or(matchAny("water", "river"), matchAny("waterway", "riverbank"))), - MultiExpression.entry("lake", matchAny("waterway", "")), MultiExpression.entry("ocean", FALSE))); + MultiExpression.entry("lake", FALSE), MultiExpression.entry("ocean", FALSE), + MultiExpression.entry("swimming_pool", matchAny("leisure", "swimming_pool")))); } } /** @@ -178,7 +189,7 @@ final class FieldMappings { * field applied. Waterways do not have a subclass field. * * Generated from - * waterway.yaml + * waterway.yaml */ public interface Waterway extends Layer { double BUFFER_SIZE = 4.0; @@ -263,7 +274,7 @@ final class FieldMappings { * layer is to style wood (class=wood) and grass (class=grass) areas. * * Generated from landcover.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/landcover/landcover.yaml">landcover.yaml */ public interface Landcover extends Layer { double BUFFER_SIZE = 4.0; @@ -418,7 +429,7 @@ final class FieldMappings { * residential (urban) areas and at higher zoom levels mostly OSM landuse tags. * * Generated from - * landuse.yaml + * landuse.yaml */ public interface Landuse extends Layer { double BUFFER_SIZE = 4.0; @@ -512,7 +523,7 @@ final class FieldMappings { * Natural peaks * * Generated from mountain_peak.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/mountain_peak/mountain_peak.yaml">mountain_peak.yaml */ public interface MountainPeak extends Layer { double BUFFER_SIZE = 64.0; @@ -533,12 +544,13 @@ final class Fields { public static final String NAME_DE = "name_de"; /** - * Use the class to differentiate between mountain peak and volcano. + * Use the class to differentiate between natural objects. *

* allowed values: *

    *
  • "peak" *
  • "volcano" + *
  • "saddle" *
  • "ridge" *
  • "cliff" *
  • "arete" @@ -567,10 +579,11 @@ final class Fields { final class FieldValues { public static final String CLASS_PEAK = "peak"; public static final String CLASS_VOLCANO = "volcano"; + public static final String CLASS_SADDLE = "saddle"; public static final String CLASS_RIDGE = "ridge"; public static final String CLASS_CLIFF = "cliff"; public static final String CLASS_ARETE = "arete"; - public static final Set CLASS_VALUES = Set.of("peak", "volcano", "ridge", "cliff", "arete"); + public static final Set CLASS_VALUES = Set.of("peak", "volcano", "saddle", "ridge", "cliff", "arete"); } /** Complex mappings to generate attribute values from OSM element tags in the mountain_peak layer. */ final class FieldMappings { @@ -585,7 +598,7 @@ final class FieldMappings { * leisure=nature_reserve. * * Generated from - * park.yaml + * park.yaml */ public interface Park extends Layer { double BUFFER_SIZE = 4.0; @@ -645,7 +658,7 @@ final class FieldMappings { * but for most styles it makes sense to just style admin_level=2 and admin_level=4. * * Generated from - * boundary.yaml + * boundary.yaml */ public interface Boundary extends Layer { double BUFFER_SIZE = 4.0; @@ -746,7 +759,7 @@ final class FieldMappings { * in the aeroway layer. * * Generated from - * aeroway.yaml + * aeroway.yaml */ public interface Aeroway extends Layer { double BUFFER_SIZE = 4.0; @@ -806,7 +819,7 @@ final class FieldMappings { * features like plazas. * * Generated from transportation.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/transportation/transportation.yaml">transportation.yaml */ public interface Transportation extends Layer { double BUFFER_SIZE = 4.0; @@ -825,7 +838,8 @@ final class Fields { * construction, * railway, * aerialway, - * route tag (for shipping ways), or + * route tag (for shipping ways), + * busway, or * man_made. *

    * allowed values: @@ -910,7 +924,6 @@ final class Fields { *

    * allowed values: *

      - *
    • 0 *
    • 1 *
    • -1 *
    @@ -922,7 +935,6 @@ final class Fields { *

    * allowed values: *

      - *
    • 0 *
    • 1 *
    */ @@ -1138,11 +1150,11 @@ final class FieldMappings { } /** * All OSM Buildings. All building tags are imported - * (building= ). The buildings are not yet - * ready for 3D rendering support and any help to improve this is welcomed. + * (building= ). Only buildings with tag + * location:underground are excluded. * * Generated from - * building.yaml + * building.yaml */ public interface Building extends Layer { double BUFFER_SIZE = 4.0; @@ -1155,15 +1167,10 @@ default String name() { /** Attribute names for map elements in the building layer. */ final class Fields { - /** - * An approximated height from levels and height of the building or building:part after the method of Paul Norman - * in OSM Clear. For future 3D rendering of buildings. - */ + /** An approximated height from levels and height of the building or building:part. */ public static final String RENDER_HEIGHT = "render_height"; /** - * An approximated height from levels and height of the bottom of the building or building:part after the method - * of Paul Norman in OSM Clear. For future 3D rendering of - * buildings. + * An approximated height from minimum levels or minimum height of the bottom of the building or building:part. */ public static final String RENDER_MIN_HEIGHT = "render_min_height"; /** Colour */ @@ -1185,11 +1192,11 @@ final class FieldMappings { } /** * Lake center lines for labelling lake bodies. This is based of the - * osm-lakelines project which derives nice centerlines + * osm-lakelines project which derives nice centerlines * from OSM water bodies. Only the most important lakes contain labels. * * Generated from water_name.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/water_name/water_name.yaml">water_name.yaml */ public interface WaterName extends Layer { double BUFFER_SIZE = 256.0; @@ -1212,11 +1219,13 @@ final class Fields { public static final String NAME_DE = "name_de"; /** - * At the moment only lake since no ocean parts are labelled. Reserved for future use. + * Distinguish between lake, ocean and sea. *

    * allowed values: *

      *
    • "lake" + *
    • "sea" + *
    • "ocean" *
    */ public static final String CLASS = "class"; @@ -1236,7 +1245,9 @@ final class Fields { /** Attribute values for map elements in the water_name layer. */ final class FieldValues { public static final String CLASS_LAKE = "lake"; - public static final Set CLASS_VALUES = Set.of("lake"); + public static final String CLASS_SEA = "sea"; + public static final String CLASS_OCEAN = "ocean"; + public static final Set CLASS_VALUES = Set.of("lake", "sea", "ocean"); } /** Complex mappings to generate attribute values from OSM element tags in the water_name layer. */ final class FieldMappings { @@ -1250,7 +1261,7 @@ final class FieldMappings { * while for other roads you should use name. * * Generated from transportation_name.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/transportation_name/transportation_name.yaml">transportation_name.yaml */ public interface TransportationName extends Layer { double BUFFER_SIZE = 8.0; @@ -1460,13 +1471,14 @@ final class FieldMappings { } /** * The place layer consists out of countries, - * states and - * cities. Apart from the roads this is also one of the - * more important layers to create a beautiful map. We suggest you use different font styles and sizes to create a - * text hierarchy. + * states, + * cities and + * islands. Apart from the roads this is also one + * of the more important layers to create a beautiful map. We suggest you use different font styles and sizes to + * create a text hierarchy. * * Generated from - * place.yaml + * place.yaml */ public interface Place extends Layer { double BUFFER_SIZE = 256.0; @@ -1501,7 +1513,7 @@ final class Fields { /** * Original value of the place tag. - * Distinguish between continents, countries, states and places like settlements or smaller entities. Use + * 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. *

    @@ -1519,6 +1531,7 @@ final class Fields { *

  • "quarter" *
  • "neighbourhood" *
  • "isolated_dwelling" + *
  • "island" *
*/ public static final String CLASS = "class"; @@ -1530,7 +1543,7 @@ final class Fields { public static final String ISO_A2 = "iso_a2"; /** * Countries, states and the most important cities all have a rank to boost their importance on - * the map. The rank field for counries and states ranges from 1 to 6 + * the map. The rank field for countries and states ranges from 1 to 6 * while the rank field for cities ranges from 1 to 10 for the most * important cities and continues from 10 serially based on the local importance of the city (derived * from population and city class). You can use the rank to limit density of labels or improve @@ -1555,8 +1568,9 @@ final class FieldValues { public static final String CLASS_QUARTER = "quarter"; 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", "suburb", "quarter", "neighbourhood", "isolated_dwelling"); + "village", "hamlet", "suburb", "quarter", "neighbourhood", "isolated_dwelling", "island"); } /** Complex mappings to generate attribute values from OSM element tags in the place layer. */ final class FieldMappings { @@ -1569,7 +1583,7 @@ final class FieldMappings { * housenumber. * * Generated from housenumber.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/housenumber/housenumber.yaml">housenumber.yaml */ public interface Housenumber extends Layer { double BUFFER_SIZE = 8.0; @@ -1598,7 +1612,7 @@ final class FieldMappings { * Points of interests containing a of a variety * of OpenStreetMap tags. Mostly contains amenities, sport, shop and tourist POIs. * - * Generated from poi.yaml + * Generated from poi.yaml */ public interface Poi extends Layer { double BUFFER_SIZE = 64.0; @@ -1659,6 +1673,7 @@ final class Fields { *
  • clothing_store *
  • swimming *
  • castle + *
  • atm * */ public static final String CLASS = "class"; @@ -1677,7 +1692,8 @@ final class Fields { * tourism, * aerialway, * building, - * highway or + * highway, + * office or * waterway tag. Use this to do more * precise styling. */ @@ -1752,10 +1768,11 @@ final class FieldValues { public static final String CLASS_CLOTHING_STORE = "clothing_store"; public static final String CLASS_SWIMMING = "swimming"; public static final String CLASS_CASTLE = "castle"; + public static final String CLASS_ATM = "atm"; public static final Set CLASS_VALUES = Set.of("shop", "town_hall", "golf", "fast_food", "park", "bus", "railway", "aerialway", "entrance", "campsite", "laundry", "grocery", "library", "college", "lodging", "ice_cream", "post", "cafe", "school", "alcohol_shop", "bar", "harbor", "car", "hospital", "cemetery", - "attraction", "beer", "music", "stadium", "art_gallery", "clothing_store", "swimming", "castle"); + "attraction", "beer", "music", "stadium", "art_gallery", "clothing_store", "swimming", "castle", "atm"); } /** Complex mappings to generate attribute values from OSM element tags in the poi layer. */ final class FieldMappings { @@ -1806,14 +1823,15 @@ final class FieldMappings { MultiExpression.entry("art_gallery", matchAny("subclass", "art", "artwork", "gallery", "arts_centre")), MultiExpression.entry("clothing_store", matchAny("subclass", "bag", "clothes")), MultiExpression.entry("swimming", matchAny("subclass", "swimming_area", "swimming")), - MultiExpression.entry("castle", matchAny("subclass", "castle", "ruins")))); + MultiExpression.entry("castle", matchAny("subclass", "castle", "ruins")), + MultiExpression.entry("atm", matchAny("subclass", "atm")))); } } /** * Aerodrome labels * * Generated from aerodrome_label.yaml + * "https://github.com/openmaptiles/openmaptiles/blob/v3.13.1/layers/aerodrome_label/aerodrome_label.yaml">aerodrome_label.yaml */ public interface AerodromeLabel extends Layer { double BUFFER_SIZE = 64.0; diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java index dbaecf62be..f60caff40a 100644 --- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java +++ b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java @@ -50,7 +50,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE /** * OSM element parsers generated from the imposm3 table definitions - * in the OpenMapTiles vector tile + * in the OpenMapTiles vector tile * schema. * * These filter and parse the raw OSM key/value attribute pairs on tags into records with fields that match the columns @@ -94,15 +94,15 @@ public record RowHandlerAndClass ( ) {} /** An OSM element that would appear in the {@code osm_water_polygon} table generated by imposm3. */ public record OsmWaterPolygon(@Override String name, @Override String nameEn, @Override String nameDe, - @Override String natural, @Override String landuse, @Override String waterway, @Override String water, - @Override boolean isIntermittent, @Override boolean isTunnel, @Override boolean isBridge, + @Override String natural, @Override String landuse, @Override String waterway, @Override String leisure, + @Override String water, @Override boolean isIntermittent, @Override boolean isTunnel, @Override boolean isBridge, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, WithNatural, WithLanduse, - WithWaterway, WithWater, WithIsIntermittent, WithIsTunnel, WithIsBridge, WithSource { + WithWaterway, WithLeisure, WithWater, WithIsIntermittent, WithIsTunnel, WithIsBridge, WithSource { public OsmWaterPolygon(SourceFeature source, String mappingKey) { this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("natural"), source.getString("landuse"), source.getString("waterway"), - source.getString("water"), source.getBoolean("intermittent"), source.getBoolean("tunnel"), - source.getBoolean("bridge"), source); + source.getString("leisure"), source.getString("water"), source.getBoolean("intermittent"), + source.getBoolean("tunnel"), source.getBoolean("bridge"), source); } /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */ @@ -405,8 +405,8 @@ public OsmAerialwayLinestring(SourceFeature source, String mappingKey) { } /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */ - public static final Expression MAPPING = - and(matchAny("aerialway", "cable_car", "gondola"), matchType("linestring")); + public static final Expression MAPPING = and(matchAny("aerialway", "chair_lift", "drag_lift", "platter", "t-bar", + "gondola", "cable_car", "j-bar", "mixed_lift"), matchType("linestring")); /** * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as @@ -691,20 +691,21 @@ public interface Handler { public record OsmPoiPoint(@Override String name, @Override String nameEn, @Override String nameDe, @Override String subclass, @Override String mappingKey, @Override String station, @Override String funicular, @Override String information, @Override String uicRef, @Override String religion, @Override long level, - @Override boolean indoor, @Override long layer, @Override String sport, @Override SourceFeature source) - implements Row, WithName, WithNameEn, WithNameDe, WithSubclass, WithMappingKey, WithStation, WithFunicular, - WithInformation, WithUicRef, WithReligion, WithLevel, WithIndoor, WithLayer, WithSport, WithSource { + @Override boolean indoor, @Override long layer, @Override String sport, @Override String operator, + @Override String network, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, + WithSubclass, WithMappingKey, WithStation, WithFunicular, WithInformation, WithUicRef, WithReligion, WithLevel, + WithIndoor, WithLayer, WithSport, WithOperator, WithNetwork, WithSource { public OsmPoiPoint(SourceFeature source, String mappingKey) { this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString(mappingKey), mappingKey, source.getString("station"), source.getString("funicular"), source.getString("information"), source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"), - source); + source.getString("operator"), source.getString("network"), source); } /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */ public static final Expression MAPPING = and(or(matchAny("aerialway", "station"), - matchAny("amenity", "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", + matchAny("amenity", "arts_centre", "atm", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "drinking_water", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", @@ -758,20 +759,21 @@ public interface Handler { public record OsmPoiPolygon(@Override String name, @Override String nameEn, @Override String nameDe, @Override String subclass, @Override String mappingKey, @Override String station, @Override String funicular, @Override String information, @Override String uicRef, @Override String religion, @Override long level, - @Override boolean indoor, @Override long layer, @Override String sport, @Override SourceFeature source) - implements Row, WithName, WithNameEn, WithNameDe, WithSubclass, WithMappingKey, WithStation, WithFunicular, - WithInformation, WithUicRef, WithReligion, WithLevel, WithIndoor, WithLayer, WithSport, WithSource { + @Override boolean indoor, @Override long layer, @Override String sport, @Override String operator, + @Override String network, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, + WithSubclass, WithMappingKey, WithStation, WithFunicular, WithInformation, WithUicRef, WithReligion, WithLevel, + WithIndoor, WithLayer, WithSport, WithOperator, WithNetwork, WithSource { public OsmPoiPolygon(SourceFeature source, String mappingKey) { this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString(mappingKey), mappingKey, source.getString("station"), source.getString("funicular"), source.getString("information"), source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"), - source); + source.getString("operator"), source.getString("network"), source); } /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */ public static final Expression MAPPING = and(or(matchAny("aerialway", "station"), - matchAny("amenity", "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", + matchAny("amenity", "arts_centre", "atm", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "drinking_water", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", @@ -1144,6 +1146,11 @@ public interface WithNetwork { String network(); } + /** Rows with a String operator attribute. */ + public interface WithOperator { + String operator(); + } + /** Rows with a String osmcSymbol attribute. */ public interface WithOsmcSymbol { String osmcSymbol(); diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java index 546deb021d..5b41aa2bb8 100644 --- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java +++ b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java @@ -43,8 +43,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import com.carrotsearch.hppc.LongIntMap; import com.onthegomap.planetiler.FeatureCollector; +import com.onthegomap.planetiler.ForwardingProfile; import com.onthegomap.planetiler.VectorTile; -import com.onthegomap.planetiler.basemap.BasemapProfile; import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema; import com.onthegomap.planetiler.basemap.generated.Tables; import com.onthegomap.planetiler.basemap.util.LanguageUtils; @@ -68,7 +68,7 @@ public class Poi implements OpenMapTilesSchema.Poi, Tables.OsmPoiPoint.Handler, Tables.OsmPoiPolygon.Handler, - BasemapProfile.FeaturePostProcessor { + ForwardingProfile.FeaturePostProcessor { /* * process() creates the raw POI feature from OSM elements and postProcess() @@ -136,7 +136,7 @@ public void process(Tables.OsmPoiPolygon element, FeatureCollector features) { setupPoiFeature(element, features.centroidIfConvex(LAYER_NAME)); } - private void setupPoiFeature( + private void setupPoiFeature( T element, FeatureCollector.Feature output) { String rawSubclass = element.subclass(); if ("station".equals(rawSubclass) && "subway".equals(element.station())) { @@ -146,6 +146,16 @@ private nullIfEmpty(element.information()); case "place_of_worship" -> nullIfEmpty(element.religion()); @@ -154,7 +164,7 @@ private new WaterInfo(2, 4, FieldValues.CLASS_OCEAN); case "ne_10m_ocean" -> new WaterInfo(5, 5, FieldValues.CLASS_OCEAN); + // TODO: get OSM ID from low-zoom natural earth lakes case "ne_110m_lakes" -> new WaterInfo(0, 1, FieldValues.CLASS_LAKE); case "ne_50m_lakes" -> new WaterInfo(2, 3, FieldValues.CLASS_LAKE); case "ne_10m_lakes" -> new WaterInfo(4, 5, FieldValues.CLASS_LAKE); @@ -109,6 +110,7 @@ public void process(Tables.OsmWaterPolygon element, FeatureCollector features) { .setBufferPixels(BUFFER_SIZE) .setMinPixelSizeBelowZoom(11, 2) .setMinZoom(6) + .setAttr(Fields.ID, element.source().id()) .setAttr(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0) .setAttrWithMinzoom(Fields.BRUNNEL, Utils.brunnel(element.isBridge(), element.isTunnel()), 12) .setAttr(Fields.CLASS, clazz); diff --git a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/PoiTest.java b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/PoiTest.java index 82dedb1e46..ea45126eea 100644 --- a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/PoiTest.java +++ b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/PoiTest.java @@ -207,4 +207,34 @@ void testLocksmith() { "name", "The Locksmith" )))); } + + @Test + void testAtm() { + List> expected = List.of(Map.of( + "_layer", "poi", + "class", "atm", + "subclass", "atm", + "name", "ATM name" + )); + // prefer name, otherwise fall back to operator, or else network + assertFeatures(14, expected, process(pointFeature(Map.of( + "amenity", "atm", + "name", "ATM name" + )))); + assertFeatures(14, expected, process(pointFeature(Map.of( + "amenity", "atm", + "name", "ATM name", + "operator", "ATM operator", + "network", "ATM network" + )))); + assertFeatures(14, expected, process(pointFeature(Map.of( + "amenity", "atm", + "operator", "ATM name", + "network", "ATM network" + )))); + assertFeatures(14, expected, process(pointFeature(Map.of( + "amenity", "atm", + "network", "ATM name" + )))); + } } diff --git a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/TransportationTest.java b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/TransportationTest.java index 613f80b43d..5fe007ea34 100644 --- a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/TransportationTest.java +++ b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/TransportationTest.java @@ -19,6 +19,8 @@ import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; class TransportationTest extends AbstractLayerTest { @@ -1061,12 +1063,13 @@ void testNarrowGauge() { )))); } - @Test - void testAerialway() { + @ParameterizedTest + @ValueSource(strings = {"gondola", "chair_lift", "j-bar", "mixed_lift"}) + void testAerialway(String aerialway) { assertFeatures(12, List.of(Map.of( "_layer", "transportation", "class", "aerialway", - "subclass", "gondola", + "subclass", aerialway, "_minzoom", 12, "_maxzoom", 14, @@ -1074,19 +1077,19 @@ void testAerialway() { ), Map.of( "_layer", "transportation_name", "class", "aerialway", - "subclass", "gondola", + "subclass", aerialway, "name", "Summit Gondola", "_minzoom", 12, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( - "aerialway", "gondola", + "aerialway", aerialway, "name", "Summit Gondola" )))); assertFeatures(10, List.of(), process(polygonFeature(Map.of( - "aerialway", "gondola", + "aerialway", aerialway, "name", "Summit Gondola" )))); } diff --git a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/WaterTest.java b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/WaterTest.java index 2347a3f3f6..30e9f16416 100644 --- a/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/WaterTest.java +++ b/planetiler-basemap/src/test/java/com/onthegomap/planetiler/basemap/layers/WaterTest.java @@ -5,7 +5,9 @@ import static com.onthegomap.planetiler.basemap.BasemapProfile.OSM_SOURCE; import static com.onthegomap.planetiler.basemap.BasemapProfile.WATER_POLYGON_SOURCE; +import com.onthegomap.planetiler.geo.GeoUtils; import com.onthegomap.planetiler.reader.SimpleFeature; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -88,6 +90,28 @@ void testWaterOsmWaterPolygon() { ))); } + @Test + void testWaterOsmId() { + long id = 123; + assertFeatures(14, List.of(Map.of( + "class", "lake", + "id", id, + "_layer", "water", + "_type", "polygon", + "_minzoom", 6, + "_maxzoom", 14 + )), process(SimpleFeature.create( + GeoUtils.worldToLatLonCoords(rectangle(0, Math.sqrt(1))), + new HashMap<>(Map.of( + "natural", "water", + "water", "reservoir" + )), + OSM_SOURCE, + null, + id + ))); + } + @Test void testWater() { assertFeatures(14, List.of(Map.of( @@ -103,7 +127,7 @@ void testWater() { assertFeatures(14, List.of( Map.of("_layer", "poi"), Map.of( - "class", "lake", + "class", "swimming_pool", "_layer", "water", "_type", "polygon", diff --git a/scripts/regenerate-openmaptiles.sh b/scripts/regenerate-openmaptiles.sh index 3a4c59b61a..3d87e0ad0c 100755 --- a/scripts/regenerate-openmaptiles.sh +++ b/scripts/regenerate-openmaptiles.sh @@ -4,7 +4,7 @@ set -o errexit set -o pipefail set -o nounset -TAG="${1:-"v3.13"}" +TAG="${1:-"v3.13.1"}" echo "tag=${TAG}" BASE_URL="${2:-"https://raw.githubusercontent.com/openmaptiles/openmaptiles/"}"