diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 396ec898..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,325 +0,0 @@ -# Changelog - -## [3.0.0] - 2024-01-15 - -3.0 is a major release that significantly reduces tilemaker's memory footprint and improves running time. Note that it has __breaking changes__ in the way you write your Lua scripts (`way:Layer` becomes simply `Layer`, and so on). - -### Added -- PMTiles output (@systemed) -- C++ tilemaker-server for quick prototyping (@bdon) -- GeoJSON supported as an alternative to shapefiles (@systemed) -- Support nodes in relations and relation roles (@cldellow) -- Nested relations support (@systemed/@cldellow) -- `LayerAsCentroid` can use positions from relation child nodes (@cldellow) -- Add polylabel algorithm to `LayerAsCentroid` (@cldellow) -- Filter input .pbf by way keys (@cldellow) -- GeoJSON writer for debugging (@systemed) -- Warn about PBFs with large blocks (@cldellow) -- Unit tests for various features (@cldellow) -- `RestartRelations()` to reset relation iterator (@systemed) -- Per-layer, zoom-dependent feature_limit (@systemed after an original by @keichan34) -- Report OSM ID on Lua processing error (@systemed) -- Docker OOM killer warning (@Firefishy) -- Push Docker image to Github package (@JinIgarashi) -- Support `type=boundary` relations as native multipolygons (@systemed) - -### Changed -- __BREAKING__: Lua calls use the global namespace, so `Layer` instead of `way:Layer` etc. (@cldellow) -- __BREAKING__: Mapsplit (.msf) support removed (@systemed) -- Widespread speed improvements (@cldellow, @systemed) -- Reduced memory consumption (@cldellow) -- protobuf dependency removed: protozero/vtzero used instead (@cldellow) -- Better Lua detection in Makefile (@systemed) -- z-order is now a lossy float: compile-time flag not needed (@systemed) -- --input and --output parameter names no longer required explicitly (@systemed) -- Docker image improvements (@Booligoosh) - -### Fixed -- Improved polygon correction (@systemed) -- Add missing attributes to OMT layers (@Nakaner) -- Use different OSM tags for OMT subclasses (@Nakaner) -- Add access and mtb_scale attributes to OMT (@dschep) -- Fix CMake build on Arch Linux (@holzgeist) - - -## [2.4.0] - 2023-03-28 - -### Added -- Option to reverse object sort order (@Nakaner, @systemed) -- Compile-time option to use floats for ZOrder (@Nakaner, @systemed) -- Advisory note if user tries to generate tiles at z16+ (@systemed) - -### Changed -- Faster tile clipping (@systemed based on code by @mourner) -- Use rtree to index large polygons (@systemed, @kleunen) - -### Fixed -- Update use of access in OpenMapTiles-compatible schema (@dschep) -- Align path/track transportation classes with OpenMapTiles (@dschep) -- Add missing paved/unpaved values as per OpenMapTiles (@dschep) - - -## [2.3.0] - 2023-03-08 - -### Added -- Send project name to init_function (@systemed) -- Remove zero-width spikes after simplification (@systemed) -- Remove multipolygon inners below filter area size (@systemed) - -### Changed -- Move centroid and "no indexed layer" errors to verbose mode only (@systemed) -- Report missing layers consistently (@akx) -- Update Ruby server to Rack 3 (@typebrook) -- Move mmap shutdown to end of PBF reading (@systemed) - -### Fixed -- Use std::ofstream instead of boost::filesystem (@milovanderlinden) -- Scale geometries before simplifying to avoid reintroducing self-intersections (@systemed) -- Fix manpage in makefiles (@xamanu) -- Intersect multipolygons part-by-part with clipping box to fix Boost.Geometry issue (@systemed) -- Windows issues (@roundby) -- Add libatomic for rare architectures (@xamanu) -- Ignore nodes in ways with --skip-integrity (@systemed) -- Correctly mask IDs for output with include_ids (@systemed) - - -## [2.2.0] - 2022-03-11 - -### Added -- Calculate center and write to metadata (@yuiseki) -- Option to use high-resolution geometries at max zoom (@systemed) -- Output slow geometries and allow user interrupt (@systemed, @billysan) -- Support osmium locations-on-ways format (@systemed) -- CORS support in server.rb (@Kimiru) - -### Changed -- Faster multipolygon combining (@systemed) -- Faster multilinestring combining (@systemed) - -### Fixed -- Correctly store and write points from .shp (@systemed) -- Relation scan is now thread-safe (@systemed) -- Remove unused variable in OMT profile (@leonardehrenfried) - - -## [2.1.0] - 2022-02-11 - -### Added -- Relation support via new Lua functions (@systemed) -- Restore --compact mode for memory-efficient sequential store (@kleunen) -- Give objects a ZOrder which is sorted on output (@Nakaner) -- Add man page (@xamanu) -- Configurable language support in OMT-compatible schema (@systemed) -- Support highway=pedestrian (@leonardehrenfried) -- New --skip-integrity option to disable way-node check (@systemed) -- New --bbox option which overwrites any other bounding box (@systemed) - -### Changed -- Reduce Docker image size (@guillaumerose) -- Build no longer requires git (@xamanu) -- Faster multipolygon assembly (@systemed) -- Faster simplify (@kleunen) -- Faster shutdown and delete mmap file (@kleunen) -- Reduce memory usage by optimising OutputObject (@kleunen) -- Reduce memory usage by not storing ways unless used by relations (@systemed) -- Unbundle rapidjson and expect it as a dependency (@xamanu, @kleunen) -- simplify_level used consistently through OMT-compatible schema (@systemed) -- Use destdir and prefix variables in Makefile (@xamanu) - -### Fixed -- Load JSON module in example Ruby server (@Silvercast) -- Support multiple types of entities in a single PBF block (@irnc) -- Correctly output OSM object IDs (@typebrook) -- Improve POI output in OMT-compatible schema (@systemed) -- Don't write 'meta'-layers (using write_to attribute) to metadata.json (@Nakaner) -- Handle nan issue in MinZoom/ZOrder with invalid values (@kleunen) -- Use real relation IDs in processing (@systemed) -- Support new homebrew paths on Apple Silicon Macs (@prebm) -- Improve Lua support in Makefile (@kleunen, @zidel) -- Clamp latitude to range valid for spherical Mercator (@kleunen) -- Documentation updates (@xamanu, @systemed) - -## [2.0.0] - 2021-07-09 - -### Added -- Optionally use on-disk workspace with new --store option (@kleunen) -- Load .pbf in parallel (@kleunen) -- Static executable build for github CI (@kleunen) -- Mac and Windows CI builds (@kleunen) -- Write metadata.json for file output (@kleunen) -- Merge tile contents when using --merge switch -- Mapsplit (.msf) source data support -- `obj:MinZoom(z)` to set the minimum zoom at which a feature will be rendered -- `obj:Centroid` to get the central lat/lon of an OSM object -- `filter_below` to skip small areas at low zooms -- Make layer name available in shapefile `attribute_function` -- Set minimum zoom at which attributes are written -- Set minimum zoom for shapefile processing -- Set minimum zooms for placenames, waterways, buildings, and landcover in OpenMapTiles processing (@typebrook, @systemed) -- Render roads under construction on OpenMapTiles processing (@meromisi, @Beck-berry) -- Support any (post-5.1) version of Lua -- Build with Github Action (@typebrook) -- Use a shared key/value dictionary across OutputObjects to reduce memory usage (@kleunen) - -### Changed -- C++14 required -- Remove Lua scale functions now that we return metres -- Improve OpenMapTiles tag processing (@leonardehrenfried, @typebrook, @systemed, @QuentinC, @keichan34) -- Use OpenMapTiles processing as default in tilemaker directory -- Change OpenMapTiles minzoom to 0 -- Default simplify_ratio to 2 -- Ignore Lake Saimaa and USFS National Forest complex polygons in OpenMapTiles script -- Rewrite linestring/polygon combining, with zoom level control (`combine_below` and `combine_polygons_below`) -- Use boost::geometry::intersection for clipping (faster than clipper) -- New simplify code (@kleunen) -- Use boost::asio::thread_pool for tile generation (@kleunen) -- Fallback to valid polygons if simplification produces invalid ones -- Consistently use 1TBS in source -- Only output validity errors in verbose mode -- Various speedups (don't add objects to output list that fail minZoom, optimise clipping) - -### Fixed -- Don't filter out ABCA areas (@rdsa) -- Don't break with old versions of sqlite -- Don't generate tiles outside bounding box (@kleunen) -- Dissolve problematic geometries (@kleunen) -- Assign multipolygon inners to correct outers, including multiple way inners -- Significant performance improvements (@kleunen) -- Support nodes in LayerAsCentroid - -## [1.6.0] - 2020-05-22 - -### Added -- Specify `source_columns: true` for shapefiles to import all attributes -- Support creating tiles from shapefiles only (i.e. no .osm.pbf) -- `attribute_function` to rewrite shapefile attributes from Lua -- Improved diagnostics for invalid multipolygons -- Output shapefile layer names when reading -- Report memory usage in verbose mode -- Out-of-the-box test tileserver and OpenMapTiles-compatible resources - -### Changed -- Rewrite OpenMapTiles-compatible processing (@systemed, @sasfeat, @typebrook, @leonardehrenfried) -- `--combine` flag now off by default -- 32-bit ways and 16-bit tile index by default, change with `-DFAT_WAYS -DFAT_TILE_INDEX` -- Use tsl::sparse_map instead of std::unordered_map for ~7% memory saving -- Don't write invalid small polygons -- Speedup for shapefile reading (@TimSC) -- Move to Github Actions instead of Travis (@leonardehrenfried) -- Reduce size of Docker image, use Ubuntu 20.04 (@leonardehrenfried) -- Improve area and length calculation (@typebrook, @systemed) -- Overwrite existing .mbtiles file by default - -### Fixed -- CMake build fixed (@ogre) -- Compatibility with pre-1.59 Boost Geometry -- Typo fixes (@bezineb5) -- Fix return value for --help (@typebrook) -- Use supercover (modified Bresenham) algorithm for which tiles are affected by diagonal lines - -## [1.5.0] - 2018-02-18 - -### Added -- Support mbtiles 1.3 specification -- Write `extent` field to tiles -- Ability to specify MVT version (defaults to 2) -- OpenMapTiles-like Lua/JSON files (@TimSC) -- Dockerfile (@thomasbrueggemann) -- Better error messages (@TimSC) -- Support 64-bit way IDs (@TimSC) - -### Changed -- Significant refactoring (@TimSC) - -### Fixed -- Robustness fixes and error checking for invalid geometries, using clipper inter alia (@TimSC) -- Don't break if config files not found -- Don't break on massive .pbfs (e.g. France extract) -- Don't break if .pbf only contains nodes, not ways -- Fix build issues on some versions of OS X -- Makefile fixes (@pnorman, @thomersch) - -## [1.4.0] - 2016-11-07 - -### Added -- Use threads when creating output tiles for massive speedup (@grafi-tt) -- Bundle kaguya - no need for Luabind any more -- Report how many output objects were stored -- Add glug support to mbtileserver - -### Changed -- `way:FindContaining()` now returns a Lua table rather than an iterator - -### Fixed -- Polygon filling algorithm rewritten to work consistently (@grafi-tt) - -### Removed -- Mapbox Studio-compatible file layout removed (licensing debatable) -- Vagrantfile removed (dependency problems) - -## [1.3.0] - 2016-07-11 - -### Added -- Add cmake scripts and support MSVC on Windows (@alex85k) -- Support `way:IsClosed()`, `way:Area()`, `way:Length()`, and `way:ScaleToKm()` (@grafi-tt) -- Optionally call lua functions `init_function()` and `exit_function()` (@tinoue) -- Support `simplify_ratio`, and calculate the actual simplify level by - the formula `simplify_level * pow(simplify_ratio, (simplify_below-1) - )` (@tinoue) -- Support `simplify_length`, that is simplify threshold in meters, instead of in degrees (its length changes corresponding to the latitude) (@grafi-tt) -- Support 64-bit node IDs, with compile-time flag to use 32-bit (@systemed) -- Merge polygons with identical attributes (@grafi-tt) -- Error-handling for shapefile polygons and non-existent Lua layers (@grafi-tt) -- Support shapefile polygons with multiple exterior rings (@fofanov) - -### Changed -- Optimized SQLite output (@grafi-tt) -- Refactored OSM object implementation (@grafi-tt) - -### Fixed -- Add initialization to database class (avoid crash on shutdown) (@alex85k) -- Documentation issues (@AndreMiras, @rory) -- Clip shapefile geometries to tile boundaries (@grafi-tt) - -## [1.2.0] - 2015-10-08 - -### Added -- Load shapefiles into layers -- Spatial queries (Intersects, FindIntersecting) on shapefiles -- Choose deflate, gzip or no compression (@tinoue) -- Show trace on Luabind errors (@tinoue) - -### Changed -- Suppress "missing way" errors unless --verbose specified - -### Fixed -- Die less horribly on Lua syntax errors -- Don't add attributes if no Layer set -- AttributeNumeric error (@tinoue) - -## [1.1.0] - 2015-09-28 - -### Added -- `LayerAsCentroid` method to write centroid of polygons (for labelling and POIs) -- Option: simplify geometries on output -- Option: `write_to` combines multiple input layers in one output layer -- Option: gzip output compression -- Option: user-specified output metadata -- Vagrant config to ease creating VMs (@zerebubuth) -- Compile sources to .o temporary files, for faster recompiles (@zerebubuth) -- Lua/JSON config for Mapbox GL style-compatible output (@flamed0011) -- Simple Ruby .mbtiles server for testing - -### Changed -- Store nodes with projected latitudes -- 10% speedup by using unordered_map (@zerebubuth) - -### Fixed -- Don't die when `keys_vals` is empty in source .pbf (fixes bbbike/metro compatibility) -- Code correctness, esp. avoiding reallocating arrays (@zerebubuth) -- Build improvements (@zerebubuth) -- Documentation improvements - -## [1.0.0] - 2015-06-29 - -### Added -- Initial release diff --git a/action.yml b/action.yml deleted file mode 100644 index eae15412..00000000 --- a/action.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: 'tilemaker' -description: 'Make OpenStreetMap vector tiles without the stack' -inputs: - input: - description: 'An .osm.pbf file from planet extract, as typically downloaded from providers like Geofabrik' - required: true - config: - description: 'A JSON file listing each layer, and the zoom levels at which to apply it' - required: false - default: 'config.json' - process: - description: "A Lua program that looks at each node/way's tags, and places it into layers accordingly" - required: false - default: 'process.lua' - output: - description: 'Could be directory of tiles, or a .mbtiles files' - required: true - extra: - description: 'Other options for tilemaker' - required: false - default: '--verbose' -runs: - using: 'docker' - image: 'docker://ghcr.io/systemed/tilemaker:master' - args: - - --input=${{ inputs.input }} - - --config=${{ inputs.config }} - - --process=${{ inputs.process }} - - --output=${{ inputs.output }} - - ${{ inputs.extra }} diff --git a/config.json b/config.json deleted file mode 120000 index 6b6d256f..00000000 --- a/config.json +++ /dev/null @@ -1 +0,0 @@ -resources/config-openmaptiles.json \ No newline at end of file diff --git a/get-coastline.sh b/get-coastline.sh deleted file mode 100755 index 62ff4b30..00000000 --- a/get-coastline.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - - -mkdir -p coastline -pushd coastline - -if ! [ -f "water-polygons-split-4326.zip" ]; then - curl --proto '=https' --tlsv1.3 -sSfO https://osmdata.openstreetmap.de/download/water-polygons-split-4326.zip -fi - -unzip -o -j water-polygons-split-4326.zip - -popd diff --git a/get-landcover.sh b/get-landcover.sh deleted file mode 100755 index 224690d2..00000000 --- a/get-landcover.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - - -mkdir -p landcover -pushd landcover - -if ! [ -f "ne_10m_antarctic_ice_shelves_polys.zip" ]; then - curl --proto '=https' --tlsv1.3 -sSfO https://naciscdn.org/naturalearth/10m/physical/ne_10m_antarctic_ice_shelves_polys.zip -fi - -if ! [ -f "ne_10m_urban_areas.zip" ]; then - curl --proto '=https' --tlsv1.3 -sSfO https://naciscdn.org/naturalearth/10m/cultural/ne_10m_urban_areas.zip -fi - -if ! [ -f "ne_10m_glaciated_areas.zip" ]; then - curl --proto '=https' --tlsv1.3 -sSfO https://naciscdn.org/naturalearth/10m/physical/ne_10m_glaciated_areas.zip -fi - -mkdir -p ne_10m_antarctic_ice_shelves_polys -unzip -o ne_10m_antarctic_ice_shelves_polys.zip -d ne_10m_antarctic_ice_shelves_polys - -mkdir -p ne_10m_urban_areas -unzip -o ne_10m_urban_areas.zip -d ne_10m_urban_areas - -mkdir -p ne_10m_glaciated_areas -unzip -o ne_10m_glaciated_areas.zip -d ne_10m_glaciated_areas - -popd diff --git a/get-monaco.sh b/get-monaco.sh deleted file mode 100755 index c9bb5628..00000000 --- a/get-monaco.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - - -if ! [ -f "monaco-latest.osm.pbf" ]; then - curl --proto '=https' --tlsv1.3 -sSfO https://download.geofabrik.de/europe/monaco-latest.osm.pbf -fi diff --git a/process.lua b/process.lua deleted file mode 120000 index b8062678..00000000 --- a/process.lua +++ /dev/null @@ -1 +0,0 @@ -resources/process-openmaptiles.lua \ No newline at end of file diff --git a/resources/config-coastline.json b/resources/config-coastline.json deleted file mode 100644 index cd5cec34..00000000 --- a/resources/config-coastline.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "layers": { - "water": { "minzoom": 6, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "ocean": { "minzoom": 0, "maxzoom": 14, "source": "coastline/water_polygons.shp", "filter_below": 12, "filter_area": 0.5, - "simplify_below": 13, "simplify_level": 0.0001, "simplify_ratio": 2, "write_to": "water" }, - "landuse": { "minzoom": 4, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "urban_areas": { "minzoom": 4, "maxzoom": 8, "source": "landcover/ne_10m_urban_areas/ne_10m_urban_areas.shp", "source_columns": ["featurecla"], "simplify_below": 7, "simplify_level": 0.0003, "simplify_ratio": 2, "write_to": "landuse" }, - "landcover": { "minzoom": 0, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "ice_shelf": { "minzoom": 0, "maxzoom": 9, "source": "landcover/ne_10m_antarctic_ice_shelves_polys/ne_10m_antarctic_ice_shelves_polys.shp", "source_columns": ["featurecla"], "simplify_below": 13, "simplify_level": 0.0005, "write_to": "landcover" }, - "glacier": { "minzoom": 2, "maxzoom": 9, "source": "landcover/ne_10m_glaciated_areas/ne_10m_glaciated_areas.shp", "source_columns": ["featurecla"], "simplify_below": 13, "simplify_level": 0.0005, "write_to": "landcover" } - }, - "settings": { - "minzoom": 0, - "maxzoom": 14, - "basezoom": 14, - "include_ids": false, - "combine_below": 14, - "name": "Coastline", - "version": "3.0", - "description": "Coastline, low-resolution urban areas and ice shelves/glaciers", - "compress": "gzip", - "filemetadata": { - "tilejson": "2.0.0", - "scheme": "xyz", - "type": "baselayer", - "format": "pbf", - "tiles": ["https://example.com/liechtenstein/{z}/{x}/{y}.pbf"] - } - } -} diff --git a/resources/config-debug.json b/resources/config-debug.json deleted file mode 100644 index 261c79f9..00000000 --- a/resources/config-debug.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "layers": { - "place": { "minzoom": 4, "maxzoom": 14 }, - - "poi": { "minzoom": 12, "maxzoom": 14 }, - "poi_detail": { "minzoom": 14, "maxzoom": 14, "write_to": "poi"}, - - "housenumber": { "minzoom": 14, "maxzoom": 14 }, - - "waterway": { "minzoom": 8, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "waterway_detail": { "minzoom": 12, "maxzoom": 14, "write_to": "waterway" }, - - "transportation": { "minzoom": 8, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003 }, - "transportation_main": { "minzoom": 9, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "write_to": "transportation" }, - "transportation_mid": { "minzoom": 11, "maxzoom": 14, "write_to": "transportation" }, - "transportation_detail": { "minzoom": 13, "maxzoom": 14, "write_to": "transportation" }, - "transportation_name": { "minzoom": 8, "maxzoom": 14 }, - "transportation_name_mid": { "minzoom": 12, "maxzoom": 14, "write_to": "transportation_name" }, - "transportation_name_detail": { "minzoom": 14, "maxzoom": 14, "write_to": "transportation_name" }, - - "building": { "minzoom": 13, "maxzoom": 14 }, - - "water": { "minzoom": 6, "maxzoom": 14, "simplify_below": 12, "simplify_length": 1, "simplify_ratio": 2}, - "water_name": { "minzoom": 14, "maxzoom": 14 }, - "water_name_detail": { "minzoom": 14, "maxzoom": 14, "write_to": "water_name" }, - - "aeroway": { "minzoom": 11, "maxzoom": 14 }, - "aerodrome_label": { "minzoom": 10, "maxzoom": 14 }, - "park": { "minzoom": 11, "maxzoom": 14 }, - "landuse": { "minzoom": 11, "maxzoom": 14 }, - "landcover": { "minzoom": 6, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "mountain_peak": { "minzoom": 11, "maxzoom": 14 } - }, - "settings": { - "minzoom": 4, - "maxzoom": 14, - "basezoom": 14, - "include_ids": false, - "name": "Tilemaker to OpenMapTiles schema", - "version": "3.0", - "description": "Tile config based on OpenMapTiles schema", - "compress": "gzip" - } -} - diff --git a/resources/config-example.json b/resources/config-example.json deleted file mode 100644 index 36a4da0e..00000000 --- a/resources/config-example.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "layers": { - "place": { "minzoom": 0, "maxzoom": 14 }, - "poi": { "minzoom": 12, "maxzoom": 14 }, - "transportation": { "minzoom": 4, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2.0 }, - "transportation_name": { "minzoom": 10, "maxzoom": 14 }, - "building": { "minzoom": 13, "maxzoom": 14 }, - "water": { "minzoom": 6, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2.0 }, - "waterway": { "minzoom": 6, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2.0 } - }, - "settings": { - "minzoom": 4, - "maxzoom": 14, - "basezoom": 14, - "include_ids": false, - "name": "Tilemaker example", - "version": "0.1", - "description": "Sample vector tiles for Tilemaker", - "compress": "gzip" - } -} diff --git a/resources/config-openmaptiles.json b/resources/config-openmaptiles.json deleted file mode 100644 index 01d23bfd..00000000 --- a/resources/config-openmaptiles.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "layers": { - "place": { "minzoom": 0, "maxzoom": 14 }, - "boundary": { "minzoom": 0, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2 }, - - "poi": { "minzoom": 12, "maxzoom": 14 }, - "poi_detail": { "minzoom": 14, "maxzoom": 14, "write_to": "poi"}, - - "housenumber": { "minzoom": 14, "maxzoom": 14 }, - - "waterway": { "minzoom": 8, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "waterway_detail": { "minzoom": 12, "maxzoom": 14, "write_to": "waterway" }, - - "transportation": { "minzoom": 4, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003 }, - "transportation_name": { "minzoom": 8, "maxzoom": 14 }, - - "building": { "minzoom": 13, "maxzoom": 14 }, - - "water": { "minzoom": 6, "maxzoom": 14, "simplify_below": 12, "simplify_level": 0.0003, "simplify_ratio": 2}, - "ocean": { "minzoom": 0, "maxzoom": 14, "source": "coastline/water_polygons.shp", "filter_below": 12, "filter_area": 0.5, "simplify_below": 13, "simplify_level": 0.0001, "simplify_ratio": 2, "write_to": "water" }, - "water_name": { "minzoom": 14, "maxzoom": 14 }, - "water_name_detail": { "minzoom": 14, "maxzoom": 14, "write_to": "water_name" }, - - "aeroway": { "minzoom": 11, "maxzoom": 14 }, - "aerodrome_label": { "minzoom": 10, "maxzoom": 14 }, - "park": { "minzoom": 11, "maxzoom": 14 }, - "landuse": { "minzoom": 4, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "urban_areas": { "minzoom": 4, "maxzoom": 8, "source": "landcover/ne_10m_urban_areas/ne_10m_urban_areas.shp", "source_columns": ["featurecla"], "simplify_below": 7, "simplify_level": 0.0003, "simplify_ratio": 2, "write_to": "landuse" }, - "landcover": { "minzoom": 0, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0003, "simplify_ratio": 2 }, - "ice_shelf": { "minzoom": 0, "maxzoom": 9, "source": "landcover/ne_10m_antarctic_ice_shelves_polys/ne_10m_antarctic_ice_shelves_polys.shp", "source_columns": ["featurecla"], "simplify_below": 13, "simplify_level": 0.0005, "write_to": "landcover" }, - "glacier": { "minzoom": 2, "maxzoom": 9, "source": "landcover/ne_10m_glaciated_areas/ne_10m_glaciated_areas.shp", "source_columns": ["featurecla"], "simplify_below": 13, "simplify_level": 0.0005, "write_to": "landcover" }, - "mountain_peak": { "minzoom": 11, "maxzoom": 14 } - }, - "settings": { - "minzoom": 0, - "maxzoom": 14, - "basezoom": 14, - "include_ids": false, - "combine_below": 14, - "name": "Tilemaker to OpenMapTiles schema", - "version": "3.0", - "description": "Tile config based on OpenMapTiles schema", - "compress": "gzip", - "filemetadata": { - "tilejson": "2.0.0", - "scheme": "xyz", - "type": "baselayer", - "format": "pbf", - "tiles": ["https://example.com/liechtenstein/{z}/{x}/{y}.pbf"] - } - } -} - diff --git a/resources/process-coastline.lua b/resources/process-coastline.lua deleted file mode 100644 index d6de80d9..00000000 --- a/resources/process-coastline.lua +++ /dev/null @@ -1,27 +0,0 @@ --- Enter/exit Tilemaker -function init_function() -end -function exit_function() -end - -node_keys = {} -function node_function() -end - -function way_function() -end - --- Remap coastlines and landcover -function attribute_function(attr,layer) - if attr["featurecla"]=="Glaciated areas" then - return { subclass="glacier" } - elseif attr["featurecla"]=="Antarctic Ice Shelf" then - return { subclass="ice_shelf" } - elseif attr["featurecla"]=="Urban area" then - return { class="residential" } - elseif layer=="ocean" then - return { class="ocean" } - else - return attr - end -end diff --git a/resources/process-debug.lua b/resources/process-debug.lua deleted file mode 100644 index 80f875eb..00000000 --- a/resources/process-debug.lua +++ /dev/null @@ -1,538 +0,0 @@ --- Data processing based on openmaptiles.org schema --- https://openmaptiles.org/schema/ --- Copyright (c) 2016, KlokanTech.com & OpenMapTiles contributors. --- Used under CC-BY 4.0 - --------- --- Alter these lines to control which languages are written for place/streetnames --- Preferred language can be (for example) "en" for English, "de" for German, or nil to use OSM's name tag: -preferred_language = "cy" --- This is written into the following vector tile attribute: -preferred_language_attribute = "name:latin" --- If OSM's name tag differs, then write it into this attribute: -default_language_attribute = "name_int" --- Also write these languages if they differ - for example, { "de", "fr" } -additional_languages = { "en","de","fr" } --------- - --- Enter/exit Tilemaker -function init_function() -end -function exit_function() -end - --- Implement Sets in tables -function Set(list) - local set = {} - for _, l in ipairs(list) do set[l] = true end - return set -end - --- Meters per pixel if tile is 256x256 -ZRES5 = 4891.97 -ZRES6 = 2445.98 -ZRES7 = 1222.99 -ZRES8 = 611.5 -ZRES9 = 305.7 -ZRES10 = 152.9 -ZRES11 = 76.4 -ZRES12 = 38.2 -ZRES13 = 19.1 - --- Process node/way tags -aerodromeValues = Set { "international", "public", "regional", "military", "private" } - --- Process node tags - -node_keys = { "amenity", "shop", "sport", "tourism", "place", "office", "natural", "addr:housenumber", "aeroway" } -function node_function() - -- Write 'aerodrome_label' - local aeroway = Find("aeroway") - if aeroway == "aerodrome" then - Layer("aerodrome_label", false) - SetNameAttributes() - Attribute("iata", Find("iata")) - SetEleAttributes() - Attribute("icao", Find("icao")) - - local aerodrome_value = Find("aerodrome") - local class - if aerodromeValues[aerodrome_value] then class = aerodrome_value else class = "other" end - Attribute("class", class) - end - -- Write 'housenumber' - local housenumber = Find("addr:housenumber") - if housenumber~="" then - Layer("housenumber", false) - Attribute("housenumber", housenumber) - end - - -- Write 'place' - -- note that OpenMapTiles has a rank for countries (1-3), states (1-6) and cities (1-10+); - -- we could potentially approximate it for cities based on the population tag - local place = Find("place") - if place ~= "" then - local rank = nil - local mz = 13 - local pop = tonumber(Find("population")) or 0 - - if place == "continent" then mz=2 - elseif place == "country" then mz=3; rank=1 - elseif place == "state" then mz=4; rank=2 - elseif place == "city" then mz=5; rank=3 - elseif place == "town" and pop>8000 then mz=7 - elseif place == "town" then mz=8 - elseif place == "village" and pop>2000 then mz=9 - elseif place == "village" then mz=10 - elseif place == "suburb" then mz=11 - elseif place == "hamlet" then mz=12 - elseif place == "neighbourhood" then mz=13 - elseif place == "locality" then mz=13 - end - - Layer("place", false) - Attribute("class", place) - MinZoom(mz) - if rank then AttributeNumeric("rank", rank) end - SetNameAttributes() - return - end - - -- Write 'poi' - local rank, class, subclass = GetPOIRank() - if rank then WritePOI(node,class,subclass,rank) end - - -- Write 'mountain_peak' and 'water_name' - local natural = Find("natural") - if natural == "peak" or natural == "volcano" then - Layer("mountain_peak", false) - SetEleAttributes() - AttributeNumeric("rank", 1) - Attribute("class", natural) - SetNameAttributes() - return - end - if natural == "bay" then - Layer("water_name", false) - SetNameAttributes() - return - end -end - --- Process way tags - -majorRoadValues = Set { "motorway", "trunk", "primary" } -mainRoadValues = Set { "secondary", "motorway_link", "trunk_link", "primary_link", "secondary_link" } -midRoadValues = Set { "tertiary", "tertiary_link" } -minorRoadValues = Set { "unclassified", "residential", "road", "living_street" } -trackValues = Set { "cycleway", "byway", "bridleway", "track" } -pathValues = Set { "footway", "path", "steps" } -linkValues = Set { "motorway_link", "trunk_link", "primary_link", "secondary_link", "tertiary_link" } -constructionValues = Set { "primary", "secondary", "tertiary", "motorway", "service", "trunk", "track" } - -aerowayBuildings= Set { "terminal", "gate", "tower" } -landuseKeys = Set { "school", "university", "kindergarten", "college", "library", "hospital", - "railway", "cemetery", "military", "residential", "commercial", "industrial", - "retail", "stadium", "pitch", "playground", "theme_park", "bus_station", "zoo" } -landcoverKeys = { wood="wood", forest="wood", - wetland="wetland", - beach="sand", sand="sand", - farmland="farmland", farm="farmland", orchard="farmland", vineyard="farmland", plant_nursery="farmland", - glacier="ice", ice_shelf="ice", - grassland="grass", grass="grass", meadow="grass", allotments="grass", park="grass", village_green="grass", recreation_ground="grass", garden="grass", golf_course="grass" } - --- POI key/value pairs: based on https://github.com/openmaptiles/openmaptiles/blob/master/layers/poi/mapping.yaml -poiTags = { aerialway = Set { "station" }, - amenity = Set { "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "embassy", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub", "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone", "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket" }, - barrier = Set { "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile", "toll_booth" }, - building = Set { "dormitory" }, - highway = Set { "bus_stop" }, - historic = Set { "monument", "castle", "ruins" }, - landuse = Set { "basin", "brownfield", "cemetery", "reservoir", "winter_sports" }, - leisure = Set { "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina", "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool", "water_park" }, - railway = Set { "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop" }, - shop = Set { "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages", "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "carpet", "charity", "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop", "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics", "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer", "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk", "lamps", "laundry", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument", "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video", "video_games", "watches", "weapons", "wholesale", "wine" }, - sport = Set { "american_football", "archery", "athletics", "australian_football", "badminton", "baseball", "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe", "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling", "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games", "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo", "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering", "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league", "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating", "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis", "toboggan", "volleyball", "water_ski", "yoga" }, - tourism = Set { "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site", "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "theme_park", "viewpoint", "zoo" }, - waterway = Set { "dock" } } - --- POI "class" values: based on https://github.com/openmaptiles/openmaptiles/blob/master/layers/poi/poi.yaml -poiClasses = { townhall="town_hall", public_building="town_hall", courthouse="town_hall", community_centre="town_hall", - golf="golf", golf_course="golf", miniature_golf="golf", - fast_food="fast_food", food_court="fast_food", - park="park", bbq="park", - bus_stop="bus", bus_station="bus", - subway_entrance="entrance", train_station_entrance="entrance", - camp_site="campsite", caravan_site="campsite", - laundry="laundry", dry_cleaning="laundry", - supermarket="grocery", deli="grocery", delicatessen="grocery", department_store="grocery", greengrocer="grocery", marketplace="grocery", - books="library", library="library", - university="college", college="college", - hotel="lodging", motel="lodging", bed_and_breakfast="lodging", guest_house="lodging", hostel="lodging", chalet="lodging", alpine_hut="lodging", dormitory="lodging", - chocolate="ice_cream", confectionery="ice_cream", - post_box="post", post_office="post", - cafe="cafe", - school="school", kindergarten="school", - alcohol="alcohol_shop", beverages="alcohol_shop", wine="alcohol_shop", - bar="bar", nightclub="bar", - marina="harbor", dock="harbor", - car="car", car_repair="car", taxi="car", - hospital="hospital", nursing_home="hospital", clinic="hospital", - grave_yard="cemetery", cemetery="cemetery", - attraction="attraction", viewpoint="attraction", - biergarten="beer", pub="beer", - music="music", musical_instrument="music", - american_football="stadium", stadium="stadium", soccer="stadium", - art="art_gallery", artwork="art_gallery", gallery="art_gallery", arts_centre="art_gallery", - bag="clothing_store", clothes="clothing_store", - swimming_area="swimming", swimming="swimming", - castle="castle", ruins="castle" } -poiClassRanks = { hospital=1, railway=2, bus=3, attraction=4, harbor=5, college=6, - school=7, stadium=8, zoo=9, town_hall=10, campsite=11, cemetery=12, - park=13, library=14, police=15, post=16, golf=17, shop=18, grocery=19, - fast_food=20, clothing_store=21, bar=22 } -poiKeys = Set { "amenity", "sport", "tourism", "office", "historic", "leisure", "landuse", "information" } -waterClasses = Set { "river", "riverbank", "stream", "canal", "drain", "ditch", "dock" } -waterwayClasses = Set { "stream", "river", "canal", "drain", "ditch" } - - -function way_function() - local highway = Find("highway") - local waterway = Find("waterway") - local water = Find("water") - local building = Find("building") - local natural = Find("natural") - local historic = Find("historic") - local landuse = Find("landuse") - local leisure = Find("leisure") - local amenity = Find("amenity") - local aeroway = Find("aeroway") - local railway = Find("railway") - local sport = Find("sport") - local shop = Find("shop") - local tourism = Find("tourism") - local man_made = Find("man_made") - local isClosed = IsClosed() - local housenumber = Find("addr:housenumber") - local write_name = false - local construction = Find("construction") - - -- Miscellaneous preprocessing - if Find("disused") == "yes" then return end - if highway == "proposed" then return end - if aerowayBuildings[aeroway] then building="yes"; aeroway="" end - if landuse == "field" then landuse = "farmland" end - if landuse == "meadow" and Find("meadow")=="agricultural" then landuse="farmland" end - - -- Roads ('transportation' and 'transportation_name', plus 'transportation_name_detail') - if highway~="" then - local h = highway - local layer = "transportation_detail" - if majorRoadValues[highway] then layer="transportation" end - if mainRoadValues[highway] then layer="transportation_main" end - if midRoadValues[highway] then layer="transportation_mid" end - if minorRoadValues[highway] then h = "minor"; layer="transportation_mid" end - if trackValues[highway] then h = "track"; layer="transportation_detail" end - if pathValues[highway] then h = "path" ; layer="transportation_detail" end - if h=="service" then layer="transportation_detail" end - Layer(layer, false) - Attribute("class", h) - SetBrunnelAttributes() - - -- Construction - if highway == "construction" then - if constructionValues[construction] then - Attribute("class", construction .. "_construction") - else - Attribute("class", "minor_construction") - end - end - - -- Service - local service = Find("service") - if highway == "service" and service ~="" then Attribute("service", service) end - - -- Links (ramp) - if linkValues[highway] then - splitHighway = split(highway, "_") - highway = splitHighway[1] - AttributeNumeric("ramp",1) - end - - local oneway = Find("oneway") - if oneway == "yes" or oneway == "1" then - AttributeNumeric("oneway",1) - end - if oneway == "-1" then - -- **** TODO - end - - -- Write names - if layer == "motorway" or layer == "trunk" then - Layer("transportation_name", false) - elseif h == "minor" or h == "track" or h == "path" or h == "service" then - Layer("transportation_name_detail", false) - else - Layer("transportation_name_mid", false) - end - SetNameAttributes() - Attribute("class",h) - Attribute("network","road") -- **** needs fixing - if h~=highway then Attribute("subclass",highway) end - local ref = Find("ref") - if ref~="" then - Attribute("ref",ref) - AttributeNumeric("ref_length",ref:len()) - end - end - - -- Railways ('transportation' and 'transportation_name', plus 'transportation_name_detail') - if railway~="" then - Layer("transportation", false) - Attribute("class", railway) - - Layer("transportation_name", false) - SetNameAttributes() - MinZoom(14) - Attribute("class", "rail") - end - - -- 'Aeroway' - if aeroway~="" then - Layer("aeroway", isClosed) - Attribute("class",aeroway) - Attribute("ref",Find("ref")) - write_name = true - end - - -- 'aerodrome_label' - if aeroway=="aerodrome" then - LayerAsCentroid("aerodrome_label") - SetNameAttributes() - Attribute("iata", Find("iata")) - SetEleAttributes() - Attribute("icao", Find("icao")) - - local aerodrome = Find(aeroway) - local class - if aerodromeValues[aerodrome] then class = aerodrome else class = "other" end - Attribute("class", class) - end - - -- Set 'waterway' and associated - if waterwayClasses[waterway] and not isClosed then - if waterway == "river" and Holds("name") then - Layer("waterway", false) - else - Layer("waterway_detail", false) - end - if Find("intermittent")=="yes" then AttributeNumeric("intermittent", 1) else AttributeNumeric("intermittent", 0) end - Attribute("class", waterway) - SetNameAttributes() - SetBrunnelAttributes() - elseif waterway == "boatyard" then Layer("landuse", isClosed); Attribute("class", "industrial") - elseif waterway == "dam" then Layer("building",isClosed) - elseif waterway == "fuel" then Layer("landuse", isClosed); Attribute("class", "industrial") - end - -- Set names on rivers - if waterwayClasses[waterway] and not isClosed then - if waterway == "river" and Holds("name") then - Layer("water_name", false) - else - Layer("water_name_detail", false) - MinZoom(14) - end - Attribute("class", waterway) - SetNameAttributes() - end - - -- Set 'building' and associated - if building~="" then - Layer("building", true) - SetMinZoomByArea() - end - - -- Set 'housenumber' - if housenumber~="" then - LayerAsCentroid("housenumber") - Attribute("housenumber", housenumber) - end - - -- Set 'water' - if natural=="water" or natural=="bay" or leisure=="swimming_pool" or landuse=="reservoir" or landuse=="basin" or waterClasses[waterway] then - if Find("covered")=="yes" or not isClosed then return end - local class="lake"; if natural=="bay" then class="ocean" elseif waterway~="" then class="river" end - Layer("water",true) --- SetMinZoomByArea() - Attribute("class",class) - - if Find("intermittent")=="yes" then Attribute("intermittent",1) end - -- we only want to show the names of actual lakes not every man-made basin that probably doesn't even have a name other than "basin" - -- examples for which we don't want to show a name: - -- https://www.openstreetmap.org/way/25958687 - -- https://www.openstreetmap.org/way/27201902 - -- https://www.openstreetmap.org/way/25309134 - -- https://www.openstreetmap.org/way/24579306 - if Holds("name") and natural=="water" and water ~= "basin" and water ~= "wastewater" then - LayerAsCentroid("water_name_detail") - SetNameAttributes() --- SetMinZoomByArea() - Attribute("class", class) - end - - return -- in case we get any landuse processing - end - - -- Set 'landcover' (from landuse, natural, leisure) - local l = landuse - if l=="" then l=natural end - if l=="" then l=leisure end - if landcoverKeys[l] then - Layer("landcover", true) - SetMinZoomByArea() - Attribute("class", landcoverKeys[l]) - if l=="wetland" then Attribute("subclass", Find("wetland")) - else Attribute("subclass", l) end - write_name = true - - -- Set 'landuse' - else - if l=="" then l=amenity end - if l=="" then l=tourism end - if landuseKeys[l] then - Layer("landuse", true) - Attribute("class", l) - write_name = true - end - end - - -- Parks - if boundary=="national_park" then Layer("park",true); Attribute("class",boundary); SetNameAttributes() - elseif leisure=="nature_reserve" then Layer("park",true); Attribute("class",leisure ); SetNameAttributes() end - - -- POIs ('poi' and 'poi_detail') - local rank, class, subclass = GetPOIRank() - if rank then WritePOI(way,class,subclass,rank); return end - - -- Catch-all - if (building~="" or write_name) and Holds("name") then - LayerAsCentroid("poi_detail") - SetNameAttributes() - if write_name then rank=6 else rank=25 end - AttributeNumeric("rank", rank) - end -end - --- Remap coastlines -function attribute_function(attr) - return { class="ocean" } -end - --- ========================================================== --- Common functions - --- Write a way centroid to POI layer -function WritePOI(obj,class,subclass,rank) - local layer = "poi" - if rank>4 then layer="poi_detail" end - LayerAsCentroid(layer) - SetNameAttributes(obj) - AttributeNumeric("rank", rank) - Attribute("class", class) - Attribute("subclass", subclass) -end - --- Set name attributes on any object -function SetNameAttributes(obj) - local name = Find("name") - local main_written = name - local iname - -- if we have a preferred language, then write that (if available), and additionally write the base name tag - if preferred_language and Holds("name:"..preferred_language) then - iname = Find("name:"..preferred_language) -print("Found "..preferred_language..": "..iname) - Attribute(preferred_language_attribute, iname) - if iname~=name and default_language_attribute then - Attribute(default_language_attribute, name) - else main_written = iname end - else - Attribute(preferred_language_attribute, name) - end - -- then set any additional languages - for i,lang in ipairs(additional_languages) do - iname = Find("name:"..lang) - if iname=="" then iname=name end - if iname~=main_written then Attribute("name:"..lang, iname) end - end -end - --- Set ele and ele_ft on any object -function SetEleAttributes(obj) - local ele = Find("ele") - if ele ~= "" then - local meter = math.floor(tonumber(ele) or 0) - local feet = math.floor(meter * 3.2808399) - AttributeNumeric("ele", meter) - AttributeNumeric("ele_ft", feet) - end -end - -function SetBrunnelAttributes(obj) - if Find("bridge") == "yes" then Attribute("brunnel", "bridge") - elseif Find("tunnel") == "yes" then Attribute("brunnel", "tunnel") - elseif Find("ford") == "yes" then Attribute("brunnel", "ford") - end -end - --- Set minimum zoom level by area -function SetMinZoomByArea() - local area=Area() - if area>ZRES5^2 then MinZoom(6) - elseif area>ZRES6^2 then MinZoom(7) - elseif area>ZRES7^2 then MinZoom(8) - elseif area>ZRES8^2 then MinZoom(9) - elseif area>ZRES9^2 then MinZoom(10) - elseif area>ZRES10^2 then MinZoom(11) - elseif area>ZRES11^2 then MinZoom(12) - elseif area>ZRES12^2 then MinZoom(13) - else MinZoom(14) end -end - --- Calculate POIs (typically rank 1-4 go to 'poi' z12-14, rank 5+ to 'poi_detail' z14) --- returns rank, class, subclass -function GetPOIRank(obj) - local k,list,v,class,rank - - -- Can we find the tag? - for k,list in pairs(poiTags) do - if list[Find(k)] then - v = Find(k) -- k/v are the OSM tag pair - class = poiClasses[v] or v - rank = poiClassRanks[class] or 25 - return rank, class, v - end - end - - -- Catch-all for shops - local shop = Find("shop") - if shop~="" then return poiClassRanks['shop'], "shop", shop end - - -- Nothing found - return nil,nil,nil -end - --- ========================================================== --- Lua utility functions - -function split(inputstr, sep) -- https://stackoverflow.com/a/7615129/4288232 - if sep == nil then - sep = "%s" - end - local t={} ; i=1 - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - t[i] = str - i = i + 1 - end - return t -end - diff --git a/resources/process-example.lua b/resources/process-example.lua deleted file mode 100644 index cf3266c2..00000000 --- a/resources/process-example.lua +++ /dev/null @@ -1,105 +0,0 @@ ---[[ - - A simple example tilemaker configuration, intended to illustrate how it - works and to act as a starting point for your own configurations. - - The basic principle is: - - read OSM tags with Find(key) - - write to vector tile layers with Layer(layer_name) - - add attributes with Attribute(field, value) - - (This is a very basic subset of the OpenMapTiles schema. Don't take much - notice of the "class" attribute, that's an OMT implementation thing which - is just here to get them to show up with the default style.) - - It doesn't do much filtering by zoom level - all the roads appear all the - time. If you want a practice project, try fixing that! - - You can view your output with tilemaker-server: - - tilemaker-server /path/to/your.mbtiles --static server/static - -]]-- - - --- Nodes will only be processed if one of these keys is present - -node_keys = { "amenity", "historic", "leisure", "place", "shop", "tourism" } - - --- Assign nodes to a layer, and set attributes, based on OSM tags - -function node_function(node) - -- POIs go to a "poi" layer (we just look for amenity and shop here) - local amenity = Find("amenity") - local shop = Find("shop") - if amenity~="" or shop~="" then - Layer("poi") - if amenity~="" then Attribute("class",amenity) - else Attribute("class",shop) end - Attribute("name:latin", Find("name")) - AttributeNumeric("rank", 3) - end - - -- Places go to a "place" layer - local place = Find("place") - if place~="" then - Layer("place") - Attribute("class", place) - Attribute("name:latin", Find("name")) - if place=="city" then - AttributeNumeric("rank", 4) - MinZoom(3) - elseif place=="town" then - AttributeNumeric("rank", 6) - MinZoom(6) - else - AttributeNumeric("rank", 9) - MinZoom(10) - end - end -end - - --- Assign ways to a layer, and set attributes, based on OSM tags - -function way_function() - local highway = Find("highway") - local waterway = Find("waterway") - local building = Find("building") - - -- Roads - if highway~="" then - Layer("transportation", false) - if highway=="unclassified" or highway=="residential" then highway="minor" end - Attribute("class", highway) - -- ...and road names - local name = Find("name") - if name~="" then - Layer("transportation_name", false) - Attribute("class", highway) - Attribute("name:latin", name) - end - end - - -- Rivers - if waterway=="stream" or waterway=="river" or waterway=="canal" then - Layer("waterway", false) - Attribute("class", waterway) - AttributeNumeric("intermittent", 0) - end - - -- Lakes and other water polygons - if Find("natural")=="water" then - Layer("water", true) - if Find("water")=="river" then - Attribute("class", "river") - else - Attribute("class", "lake") - end - end - -- Buildings - if building~="" then - Layer("building", true) - end -end diff --git a/resources/process-openmaptiles.lua b/resources/process-openmaptiles.lua deleted file mode 100644 index c06fd6e7..00000000 --- a/resources/process-openmaptiles.lua +++ /dev/null @@ -1,948 +0,0 @@ --- Data processing based on openmaptiles.org schema --- https://openmaptiles.org/schema/ --- Copyright (c) 2016, KlokanTech.com & OpenMapTiles contributors. --- Used under CC-BY 4.0 - --------- --- Alter these lines to control which languages are written for place/streetnames --- --- Preferred language can be (for example) "en" for English, "de" for German, or nil to use OSM's name tag: -preferred_language = nil --- This is written into the following vector tile attribute (usually "name:latin"): -preferred_language_attribute = "name:latin" --- If OSM's name tag differs, then write it into this attribute (usually "name_int"): -default_language_attribute = "name_int" --- Also write these languages if they differ - for example, { "de", "fr" } -additional_languages = { } --------- - --- Enter/exit Tilemaker -function init_function() -end -function exit_function() -end - --- Implement Sets in tables -function Set(list) - local set = {} - for _, l in ipairs(list) do set[l] = true end - return set -end - --- Meters per pixel if tile is 256x256 -ZRES5 = 4891.97 -ZRES6 = 2445.98 -ZRES7 = 1222.99 -ZRES8 = 611.5 -ZRES9 = 305.7 -ZRES10 = 152.9 -ZRES11 = 76.4 -ZRES12 = 38.2 -ZRES13 = 19.1 - --- The height of one floor, in meters -BUILDING_FLOOR_HEIGHT = 3.66 --- Used to express that a feature should not end up the vector tiles -INVALID_ZOOM = 99 - --- Process node/way tags -aerodromeValues = Set { "international", "public", "regional", "military", "private" } -pavedValues = Set { "paved", "asphalt", "cobblestone", "concrete", "concrete:lanes", "concrete:plates", "metal", "paving_stones", "sett", "unhewn_cobblestone", "wood" } -unpavedValues = Set { "unpaved", "compacted", "dirt", "earth", "fine_gravel", "grass", "grass_paver", "gravel", "gravel_turf", "ground", "ice", "mud", "pebblestone", "salt", "sand", "snow", "woodchips" } - --- Process node tags - -node_keys = { "addr:housenumber","aerialway","aeroway","amenity","barrier","highway","historic","leisure","natural","office","place","railway","shop","sport","tourism","waterway" } - --- Get admin level which the place node is capital of. --- Returns nil in case of invalid capital and for places which are not capitals. -function capitalLevel(capital) - local capital_al = tonumber(capital) or 0 - if capital == "yes" then - capital_al = 2 - end - if capital_al == 0 then - return nil - end - return capital_al -end - --- Calculate rank for place nodes --- place: value of place=* --- popuplation: population as number --- capital_al: result of capitalLevel() -function calcRank(place, population, capital_al) - local rank = 0 - if capital_al and capital_al >= 2 and capital_al <= 4 then - rank = capital_al - if population > 3 * 10^6 then - rank = rank - 2 - elseif population > 1 * 10^6 then - rank = rank - 1 - elseif population < 100000 then - rank = rank + 2 - elseif population < 50000 then - rank = rank + 3 - end - -- Safety measure to avoid place=village/farm/... appear early (as important capital) because a mapper added capital=yes/2/3/4 - if place ~= "city" then - rank = rank + 3 - -- Decrease rank further if it is not even a town. - if place ~= "town" then - rank = rank + 2 - end - end - return rank - end - if place ~= "city" and place ~= "town" then - return nil - end - if population > 3 * 10^6 then - return 1 - elseif population > 1 * 10^6 then - return 2 - elseif population > 500000 then - return 3 - elseif population > 200000 then - return 4 - elseif population > 100000 then - return 5 - elseif population > 75000 then - return 6 - elseif population > 50000 then - return 7 - elseif population > 25000 then - return 8 - elseif population > 10000 then - return 9 - end - return 10 -end - - -function node_function() - -- Write 'aerodrome_label' - local aeroway = Find("aeroway") - if aeroway == "aerodrome" then - Layer("aerodrome_label", false) - SetNameAttributes() - Attribute("iata", Find("iata")) - SetEleAttributes() - Attribute("icao", Find("icao")) - - local aerodrome_value = Find("aerodrome") - local class - if aerodromeValues[aerodrome_value] then class = aerodrome_value else class = "other" end - Attribute("class", class) - end - -- Write 'housenumber' - local housenumber = Find("addr:housenumber") - if housenumber~="" then - Layer("housenumber", false) - Attribute("housenumber", housenumber) - end - - -- Write 'place' - -- note that OpenMapTiles has a rank for countries (1-3), states (1-6) and cities (1-10+); - -- we could potentially approximate it for cities based on the population tag - local place = Find("place") - if place ~= "" then - local mz = 13 - local pop = tonumber(Find("population")) or 0 - local capital = capitalLevel(Find("capital")) - local rank = calcRank(place, pop, capital) - - if place == "continent" then mz=0 - elseif place == "country" then - if pop>50000000 then rank=1; mz=1 - elseif pop>20000000 then rank=2; mz=2 - else rank=3; mz=3 end - elseif place == "state" then mz=4 - elseif place == "province" then mz=5 - elseif place == "city" then mz=5 - elseif place == "town" and pop>8000 then mz=7 - elseif place == "town" then mz=8 - elseif place == "village" and pop>2000 then mz=9 - elseif place == "village" then mz=10 - elseif place == "borough" then mz=10 - elseif place == "suburb" then mz=11 - elseif place == "quarter" then mz=12 - elseif place == "hamlet" then mz=12 - elseif place == "neighbourhood" then mz=13 - elseif place == "isolated_dwelling" then mz=13 - elseif place == "locality" then mz=13 - elseif place == "island" then mz=12 - end - - Layer("place", false) - Attribute("class", place) - MinZoom(mz) - if rank then AttributeNumeric("rank", rank) end - if capital then AttributeNumeric("capital", capital) end - if place=="country" then - local iso_a2 = Find("ISO3166-1:alpha2") - while iso_a2 == "" do - local rel, role = NextRelation() - if not rel then break end - if role == 'label' then - iso_a2 = FindInRelation("ISO3166-1:alpha2") - end - end - Attribute("iso_a2", iso_a2) - end - SetNameAttributes() - return - end - - -- Write 'poi' - local rank, class, subclass = GetPOIRank() - if rank then WritePOI(class,subclass,rank) end - - -- Write 'mountain_peak' and 'water_name' - local natural = Find("natural") - if natural == "peak" or natural == "volcano" then - Layer("mountain_peak", false) - SetEleAttributes() - AttributeNumeric("rank", 1) - Attribute("class", natural) - SetNameAttributes() - return - end - if natural == "bay" then - Layer("water_name", false) - SetNameAttributes() - return - end -end - --- Process way tags - -majorRoadValues = Set { "motorway", "trunk", "primary" } -z9RoadValues = Set { "secondary", "motorway_link", "trunk_link" } -z10RoadValues = Set { "primary_link", "secondary_link" } -z11RoadValues = Set { "tertiary", "tertiary_link", "busway", "bus_guideway" } --- On zoom 12, various road classes are merged into "minor" -z12MinorRoadValues = Set { "unclassified", "residential", "road", "living_street" } -z12OtherRoadValues = Set { "raceway" } -z13RoadValues = Set { "track", "service" } -manMadeRoadValues = Set { "pier", "bridge" } -pathValues = Set { "footway", "cycleway", "bridleway", "path", "steps", "pedestrian", "platform" } -linkValues = Set { "motorway_link", "trunk_link", "primary_link", "secondary_link", "tertiary_link" } -pavedValues = Set { "paved", "asphalt", "cobblestone", "concrete", "concrete:lanes", "concrete:plates", "metal", "paving_stones", "sett", "unhewn_cobblestone", "wood" } -unpavedValues = Set { "unpaved", "compacted", "dirt", "earth", "fine_gravel", "grass", "grass_paver", "gravel", "gravel_turf", "ground", "ice", "mud", "pebblestone", "salt", "sand", "snow", "woodchips" } -railwayClasses = { rail="rail", narrow_gauge="rail", preserved="rail", funicular="rail", subway="transit", light_rail="transit", monorail="transit", tram="transit" } - -aerowayBuildings= Set { "terminal", "gate", "tower" } -landuseKeys = Set { "school", "university", "kindergarten", "college", "library", "hospital", - "railway", "cemetery", "military", "residential", "commercial", "industrial", - "retail", "stadium", "pitch", "playground", "theme_park", "bus_station", "zoo" } -landcoverKeys = { wood="wood", forest="wood", - wetland="wetland", - beach="sand", sand="sand", dune="sand", - farmland="farmland", farm="farmland", orchard="farmland", vineyard="farmland", plant_nursery="farmland", - glacier="ice", ice_shelf="ice", - bare_rock="rock", scree="rock", - fell="grass", grassland="grass", grass="grass", heath="grass", meadow="grass", allotments="grass", park="grass", village_green="grass", recreation_ground="grass", scrub="grass", shrubbery="grass", tundra="grass", garden="grass", golf_course="grass", park="grass" } - --- POI key/value pairs: based on https://github.com/openmaptiles/openmaptiles/blob/master/layers/poi/mapping.yaml -poiTags = { aerialway = Set { "station" }, - amenity = Set { "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "embassy", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub", "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone", "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket" }, - barrier = Set { "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile", "toll_booth" }, - building = Set { "dormitory" }, - highway = Set { "bus_stop" }, - historic = Set { "monument", "castle", "ruins" }, - landuse = Set { "basin", "brownfield", "cemetery", "reservoir", "winter_sports" }, - leisure = Set { "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina", "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool", "water_park" }, - railway = Set { "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop" }, - shop = Set { "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages", "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "carpet", "charity", "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop", "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics", "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer", "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk", "lamps", "laundry", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument", "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video", "video_games", "watches", "weapons", "wholesale", "wine" }, - sport = Set { "american_football", "archery", "athletics", "australian_football", "badminton", "baseball", "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe", "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling", "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games", "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo", "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering", "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league", "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating", "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis", "toboggan", "volleyball", "water_ski", "yoga" }, - tourism = Set { "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site", "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "theme_park", "viewpoint", "zoo" }, - waterway = Set { "dock" } } - --- POI "class" values: based on https://github.com/openmaptiles/openmaptiles/blob/master/layers/poi/poi.yaml -poiClasses = { townhall="town_hall", public_building="town_hall", courthouse="town_hall", community_centre="town_hall", - golf="golf", golf_course="golf", miniature_golf="golf", - fast_food="fast_food", food_court="fast_food", - park="park", bbq="park", - bus_stop="bus", bus_station="bus", - subway_entrance="entrance", train_station_entrance="entrance", - camp_site="campsite", caravan_site="campsite", - laundry="laundry", dry_cleaning="laundry", - supermarket="grocery", deli="grocery", delicatessen="grocery", department_store="grocery", greengrocer="grocery", marketplace="grocery", - books="library", library="library", - university="college", college="college", - hotel="lodging", motel="lodging", bed_and_breakfast="lodging", guest_house="lodging", hostel="lodging", chalet="lodging", alpine_hut="lodging", dormitory="lodging", - chocolate="ice_cream", confectionery="ice_cream", - post_box="post", post_office="post", - cafe="cafe", - school="school", kindergarten="school", - alcohol="alcohol_shop", beverages="alcohol_shop", wine="alcohol_shop", - bar="bar", nightclub="bar", - marina="harbor", dock="harbor", - car="car", car_repair="car", taxi="car", - hospital="hospital", nursing_home="hospital", clinic="hospital", - grave_yard="cemetery", cemetery="cemetery", - attraction="attraction", viewpoint="attraction", - biergarten="beer", pub="beer", - music="music", musical_instrument="music", - american_football="stadium", stadium="stadium", soccer="stadium", - art="art_gallery", artwork="art_gallery", gallery="art_gallery", arts_centre="art_gallery", - bag="clothing_store", clothes="clothing_store", - swimming_area="swimming", swimming="swimming", - castle="castle", ruins="castle" } --- POI classes where class is the matching value and subclass is the value of a separate key -poiSubClasses = { information="information", place_of_worship="religion", pitch="sport" } -poiClassRanks = { hospital=1, railway=2, bus=3, attraction=4, harbor=5, college=6, - school=7, stadium=8, zoo=9, town_hall=10, campsite=11, cemetery=12, - park=13, library=14, police=15, post=16, golf=17, shop=18, grocery=19, - fast_food=20, clothing_store=21, bar=22 } -waterClasses = Set { "river", "riverbank", "stream", "canal", "drain", "ditch", "dock" } -waterwayClasses = Set { "stream", "river", "canal", "drain", "ditch" } - --- Scan relations for use in ways - -function relation_scan_function() - if Find("type")=="boundary" and Find("boundary")=="administrative" then - Accept() - end -end - -function write_to_transportation_layer(minzoom, highway_class, subclass, ramp, service, is_rail, is_road, is_area) - Layer("transportation", is_area) - SetZOrder() - Attribute("class", highway_class) - if subclass and subclass ~= "" then - Attribute("subclass", subclass) - end - AttributeNumeric("layer", tonumber(Find("layer")) or 0, accessMinzoom) - SetBrunnelAttributes() - -- We do not write any other attributes for areas. - if is_area then - SetMinZoomByAreaWithLimit(minzoom) - return - end - MinZoom(minzoom) - if ramp then AttributeNumeric("ramp",1) end - - -- Service - if (is_rail or highway_class == "service") and (service and service ~="") then Attribute("service", service) end - - local accessMinzoom = 9 - if is_road then - local oneway = Find("oneway") - if oneway == "yes" or oneway == "1" then - AttributeNumeric("oneway",1) - end - if oneway == "-1" then - -- **** TODO - end - local surface = Find("surface") - local surfaceMinzoom = 12 - if pavedValues[surface] then - Attribute("surface", "paved", surfaceMinzoom) - elseif unpavedValues[surface] then - Attribute("surface", "unpaved", surfaceMinzoom) - end - if Holds("access") then Attribute("access", Find("access"), accessMinzoom) end - if Holds("bicycle") then Attribute("bicycle", Find("bicycle"), accessMinzoom) end - if Holds("foot") then Attribute("foot", Find("foot"), accessMinzoom) end - if Holds("horse") then Attribute("horse", Find("horse"), accessMinzoom) end - AttributeBoolean("toll", Find("toll") == "yes", accessMinzoom) - if Find("expressway") == "yes" then AttributeBoolean("expressway", true, 7) end - if Holds("mtb_scale") then Attribute("mtb_scale", Find("mtb:scale"), 10) end - end -end - --- Process way tags - -function way_function() - local route = Find("route") - local highway = Find("highway") - local waterway = Find("waterway") - local water = Find("water") - local building = Find("building") - local natural = Find("natural") - local historic = Find("historic") - local landuse = Find("landuse") - local leisure = Find("leisure") - local amenity = Find("amenity") - local aeroway = Find("aeroway") - local railway = Find("railway") - local service = Find("service") - local sport = Find("sport") - local shop = Find("shop") - local tourism = Find("tourism") - local man_made = Find("man_made") - local boundary = Find("boundary") - local aerialway = Find("aerialway") - local public_transport = Find("public_transport") - local place = Find("place") - local is_closed = IsClosed() - local housenumber = Find("addr:housenumber") - local write_name = false - local construction = Find("construction") - local is_highway_area = highway~="" and Find("area")=="yes" and is_closed - - -- Miscellaneous preprocessing - if Find("disused") == "yes" then return end - if boundary~="" and Find("protection_title")=="National Forest" and Find("operator")=="United States Forest Service" then return end - if highway == "proposed" then return end - if aerowayBuildings[aeroway] then building="yes"; aeroway="" end - if landuse == "field" then landuse = "farmland" end - if landuse == "meadow" and Find("meadow")=="agricultural" then landuse="farmland" end - - if place == "island" then - LayerAsCentroid("place") - Attribute("class", place) - MinZoom(10) - local pop = tonumber(Find("population")) or 0 - local capital = capitalLevel(Find("capital")) - local rank = calcRank(place, pop, nil) - if rank then AttributeNumeric("rank", rank) end - SetNameAttributes() - end - - -- Boundaries within relations - -- note that we process administrative boundaries as properties on ways, rather than as single relation geometries, - -- because otherwise we get multiple renderings where boundaries are coterminous - local admin_level = 11 - local isBoundary = false - while true do - local rel = NextRelation() - if not rel then break end - isBoundary = true - admin_level = math.min(admin_level, tonumber(FindInRelation("admin_level")) or 11) - end - - -- Boundaries in ways - if boundary=="administrative" then - admin_level = math.min(admin_level, tonumber(Find("admin_level")) or 11) - isBoundary = true - end - - -- Administrative boundaries - -- https://openmaptiles.org/schema/#boundary - if isBoundary and not (Find("maritime")=="yes") then - local mz = 0 - if admin_level>=3 and admin_level<5 then mz=4 - elseif admin_level>=5 and admin_level<7 then mz=8 - elseif admin_level==7 then mz=10 - elseif admin_level>=8 then mz=12 - end - - Layer("boundary",false) - AttributeNumeric("admin_level", admin_level) - MinZoom(mz) - -- disputed status (0 or 1). some styles need to have the 0 to show it. - local disputed = Find("disputed") - if disputed=="yes" then - AttributeNumeric("disputed", 1) - else - AttributeNumeric("disputed", 0) - end - end - - -- Aerialways ('transportation' and 'transportation_name') - if aerialway ~= "" then - write_to_transportation_layer(12, "aerialway", aerialway, false, nil, false, false, is_closed) - if HasNames() then - Layer("transportation_name", false) - MinZoom(12) - SetNameAttributes() - Attribute("class", "aerialway") - Attribute("subclass", aerialway) - end - end - - -- Roads ('transportation' and 'transportation_name') - if highway ~= "" or public_transport == "platform" then - local access = Find("access") - local surface = Find("surface") - - local h = highway - local is_road = true - if h == "" then - h = public_transport - is_road = false - end - local subclass = nil - local under_construction = false - if highway == "construction" and construction ~= "" then - h = construction - under_construction = true - end - local minzoom = INVALID_ZOOM - if majorRoadValues[h] then minzoom = 4 - elseif h == "trunk" then minzoom = 5 - elseif highway == "primary" then minzoom = 7 - elseif z9RoadValues[h] then minzoom = 9 - elseif z10RoadValues[h] then minzoom = 10 - elseif z11RoadValues[h] then minzoom = 11 - elseif z12MinorRoadValues[h] then - minzoom = 12 - subclass = h - h = "minor" - elseif z12OtherRoadValues[h] then minzoom = 12 - elseif z13RoadValues[h] then minzoom = 13 - elseif pathValues[h] then - minzoom = 14 - subclass = h - h = "path" - end - - -- Links (ramp) - local ramp=false - if linkValues[h] then - splitHighway = split(highway, "_") - highway = splitHighway[1]; h = highway - ramp = true - end - - -- Construction - if under_construction then - h = h .. "_construction" - end - - -- Drop underground platforms - local layer = Find("layer") - local layerNumeric = tonumber(layer) - if not is_road and layerNumeric ~= nil and layerNumeric < 0 then - minzoom = INVALID_ZOOM - end - - -- Drop all areas except infrastructure for pedestrians handled above - if is_highway_area and h ~= "path" then - minzoom = INVALID_ZOOM - end - - -- Write to layer - if minzoom <= 14 then - write_to_transportation_layer(minzoom, h, subclass, ramp, service, false, is_road, is_highway_area) - - -- Write names - if not is_closed and (HasNames() or Holds("ref")) then - if h == "motorway" then - minzoom = 7 - elseif h == "trunk" then - minzoom = 8 - elseif h == "primary" then - minzoom = 10 - elseif h == "secondary" then - minzoom = 11 - elseif h == "minor" or h == "track" or h == "tertiary" then - minzoom = 13 - else - minzoom = 14 - end - Layer("transportation_name", false) - MinZoom(minzoom) - SetNameAttributes() - Attribute("class",h) - Attribute("network","road") -- **** could also be us-interstate, us-highway, us-state - if subclass then Attribute("subclass", highway) end - local ref = Find("ref") - if ref~="" then - Attribute("ref",ref) - AttributeNumeric("ref_length",ref:len()) - end - end - end - end - - -- Railways ('transportation' and 'transportation_name') - if railway~="" then - local class = railwayClasses[railway] - if class then - local minzoom = 14 - Layer("transportation", false) - local usage = Find("usage") - if railway == "rail" and service == "" then - if usage == "main" then - minzoom = 8 - else - minzoom = 10 - end - elseif railway == "narrow_gauge" and service == "" then - minzoom = 10 - elseif railway == "light_rail" and service == "" then - minzoom = 11 - end - write_to_transportation_layer(minzoom, class, railway, false, service, true, false, is_closed) - - if HasNames() then - Layer("transportation_name", false) - SetNameAttributes() - MinZoom(14) - Attribute("class", class) - end - end - end - - -- Pier - if manMadeRoadValues[man_made] then - write_to_transportation_layer(13, man_made, nil, false, nil, false, false, is_closed) - end - - -- 'Ferry' - if route=="ferry" then - write_to_transportation_layer(9, "ferry", nil, false, nil, false, false, is_closed) - - if HasNames() then - Layer("transportation_name", false) - SetNameAttributes() - MinZoom(12) - Attribute("class", "ferry") - end - end - - -- 'Aeroway' - if aeroway~="" then - Layer("aeroway", is_closed) - Attribute("class",aeroway) - Attribute("ref",Find("ref")) - write_name = true - end - - -- 'aerodrome_label' - if aeroway=="aerodrome" then - LayerAsCentroid("aerodrome_label") - SetNameAttributes() - Attribute("iata", Find("iata")) - SetEleAttributes() - Attribute("icao", Find("icao")) - - local aerodrome = Find(aeroway) - local class - if aerodromeValues[aerodrome] then class = aerodrome else class = "other" end - Attribute("class", class) - end - - -- Set 'waterway' and associated - if waterwayClasses[waterway] and not is_closed then - if waterway == "river" and Holds("name") then - Layer("waterway", false) - else - Layer("waterway_detail", false) - end - if Find("intermittent")=="yes" then AttributeNumeric("intermittent", 1) else AttributeNumeric("intermittent", 0) end - Attribute("class", waterway) - SetNameAttributes() - SetBrunnelAttributes() - elseif waterway == "boatyard" then Layer("landuse", is_closed); Attribute("class", "industrial"); MinZoom(12) - elseif waterway == "dam" then Layer("building",is_closed) - elseif waterway == "fuel" then Layer("landuse", is_closed); Attribute("class", "industrial"); MinZoom(14) - end - -- Set names on rivers - if waterwayClasses[waterway] and not is_closed then - if waterway == "river" and Holds("name") then - Layer("water_name", false) - else - Layer("water_name_detail", false) - MinZoom(14) - end - Attribute("class", waterway) - SetNameAttributes() - end - - -- Set 'building' and associated - if building~="" then - Layer("building", true) - SetBuildingHeightAttributes() - SetMinZoomByArea() - end - - -- Set 'housenumber' - if housenumber~="" then - LayerAsCentroid("housenumber") - Attribute("housenumber", housenumber) - end - - -- Set 'water' - if natural=="water" or leisure=="swimming_pool" or landuse=="reservoir" or landuse=="basin" or waterClasses[waterway] then - if Find("covered")=="yes" or not is_closed then return end - local class="lake"; if waterway~="" then class="river" end - if class=="lake" and Find("wikidata")=="Q192770" then return end - Layer("water",true) - SetMinZoomByArea(way) - Attribute("class",class) - - if Find("intermittent")=="yes" then Attribute("intermittent",1) end - -- we only want to show the names of actual lakes not every man-made basin that probably doesn't even have a name other than "basin" - -- examples for which we don't want to show a name: - -- https://www.openstreetmap.org/way/25958687 - -- https://www.openstreetmap.org/way/27201902 - -- https://www.openstreetmap.org/way/25309134 - -- https://www.openstreetmap.org/way/24579306 - if Holds("name") and natural=="water" and water ~= "basin" and water ~= "wastewater" then - LayerAsCentroid("water_name_detail") - SetNameAttributes() - SetMinZoomByArea() - Attribute("class", class) - end - - return -- in case we get any landuse processing - end - - -- Set 'landcover' (from landuse, natural, leisure) - local l = landuse - if l=="" then l=natural end - if l=="" then l=leisure end - if landcoverKeys[l] then - Layer("landcover", true) - SetMinZoomByArea() - Attribute("class", landcoverKeys[l]) - if l=="wetland" then Attribute("subclass", Find("wetland")) - else Attribute("subclass", l) end - write_name = true - - -- Set 'landuse' - else - if l=="" then l=amenity end - if l=="" then l=tourism end - if landuseKeys[l] then - Layer("landuse", true) - Attribute("class", l) - if l=="residential" then - if Area()4 then layer="poi_detail" end - LayerAsCentroid(layer) - SetNameAttributes() - AttributeNumeric("rank", rank) - Attribute("class", class) - Attribute("subclass", subclass) - -- layer defaults to 0 - AttributeNumeric("layer", tonumber(Find("layer")) or 0) - -- indoor defaults to false - AttributeBoolean("indoor", (Find("indoor") == "yes")) - -- level has no default - local level = tonumber(Find("level")) - if level then - AttributeNumeric("level", level) - end -end - --- Check if there are name tags on the object -function HasNames() - if Holds("name") then return true end - local iname - local main_written = name - if preferred_language and Holds("name:"..preferred_language) then return true end - -- then set any additional languages - for i,lang in ipairs(additional_languages) do - if Holds("name:"..lang) then return true end - end - return false -end - --- Set name attributes on any object -function SetNameAttributes() - local name = Find("name"), iname - local main_written = name - -- if we have a preferred language, then write that (if available), and additionally write the base name tag - if preferred_language and Holds("name:"..preferred_language) then - iname = Find("name:"..preferred_language) - Attribute(preferred_language_attribute, iname) - if iname~=name and default_language_attribute then - Attribute(default_language_attribute, name) - else main_written = iname end - else - Attribute(preferred_language_attribute, name) - end - -- then set any additional languages - for i,lang in ipairs(additional_languages) do - iname = Find("name:"..lang) - if iname=="" then iname=name end - if iname~=main_written then Attribute("name:"..lang, iname) end - end -end - --- Set ele and ele_ft on any object -function SetEleAttributes() - local ele = Find("ele") - if ele ~= "" then - local meter = math.floor(tonumber(ele) or 0) - local feet = math.floor(meter * 3.2808399) - AttributeNumeric("ele", meter) - AttributeNumeric("ele_ft", feet) - end -end - -function SetBrunnelAttributes() - if Find("bridge") == "yes" or Find("man_made") == "bridge" then Attribute("brunnel", "bridge") - elseif Find("tunnel") == "yes" then Attribute("brunnel", "tunnel") - elseif Find("ford") == "yes" then Attribute("brunnel", "ford") - end -end - --- Set minimum zoom level by area -function SetMinZoomByArea() - SetMinZoomByAreaWithLimit(0) -end - --- Set minimum zoom level by area but not below given minzoom -function SetMinZoomByAreaWithLimit(minzoom) - local area=Area() - if minzoom <= 6 and area>ZRES5^2 then MinZoom(6) - elseif minzoom <= 7 and area>ZRES6^2 then MinZoom(7) - elseif minzoom <= 8 and area>ZRES7^2 then MinZoom(8) - elseif minzoom <= 9 and area>ZRES8^2 then MinZoom(9) - elseif minzoom <= 10 and area>ZRES9^2 then MinZoom(10) - elseif minzoom <= 11 and area>ZRES10^2 then MinZoom(11) - elseif minzoom <= 12 and area>ZRES11^2 then MinZoom(12) - elseif minzoom <= 13 and area>ZRES12^2 then MinZoom(13) - else MinZoom(14) end -end - --- Calculate POIs (typically rank 1-4 go to 'poi' z12-14, rank 5+ to 'poi_detail' z14) --- returns rank, class, subclass -function GetPOIRank() - local k,list,v,class,rank - - -- Can we find the tag? - for k,list in pairs(poiTags) do - if list[Find(k)] then - v = Find(k) -- k/v are the OSM tag pair - class = poiClasses[v] or k - rank = poiClassRanks[class] or 25 - subclassKey = poiSubClasses[v] - if subclassKey then - class = v - v = Find(subclassKey) - end - return rank, class, v - end - end - - -- Catch-all for shops - local shop = Find("shop") - if shop~="" then return poiClassRanks['shop'], "shop", shop end - - -- Nothing found - return nil,nil,nil -end - -function SetBuildingHeightAttributes() - local height = tonumber(Find("height"), 10) - local minHeight = tonumber(Find("min_height"), 10) - local levels = tonumber(Find("building:levels"), 10) - local minLevel = tonumber(Find("building:min_level"), 10) - - local renderHeight = BUILDING_FLOOR_HEIGHT - if height or levels then - renderHeight = height or (levels * BUILDING_FLOOR_HEIGHT) - end - local renderMinHeight = 0 - if minHeight or minLevel then - renderMinHeight = minHeight or (minLevel * BUILDING_FLOOR_HEIGHT) - end - - -- Fix upside-down buildings - if renderHeight < renderMinHeight then - renderHeight = renderHeight + renderMinHeight - end - - AttributeNumeric("render_height", renderHeight) - AttributeNumeric("render_min_height", renderMinHeight) -end - --- Implement z_order as calculated by Imposm --- See https://imposm.org/docs/imposm3/latest/mapping.html#wayzorder for details. -function SetZOrder() - local highway = Find("highway") - local layer = tonumber(Find("layer")) - local bridge = Find("bridge") - local tunnel = Find("tunnel") - local zOrder = 0 - if bridge ~= "" and bridge ~= "no" then - zOrder = zOrder + 10 - elseif tunnel ~= "" and tunnel ~= "no" then - zOrder = zOrder - 10 - end - if not (layer == nil) then - if layer > 7 then - layer = 7 - elseif layer < -7 then - layer = -7 - end - zOrder = zOrder + layer * 10 - end - local hwClass = 0 - -- See https://github.com/omniscale/imposm3/blob/53bb80726ca9456e4a0857b38803f9ccfe8e33fd/mapping/columns.go#L251 - if highway == "motorway" then - hwClass = 9 - elseif highway == "trunk" then - hwClass = 8 - elseif highway == "primary" then - hwClass = 6 - elseif highway == "secondary" then - hwClass = 5 - elseif highway == "tertiary" then - hwClass = 4 - else - hwClass = 3 - end - zOrder = zOrder + hwClass - ZOrder(zOrder) -end - --- ========================================================== --- Lua utility functions - -function split(inputstr, sep) -- https://stackoverflow.com/a/7615129/4288232 - if sep == nil then - sep = "%s" - end - local t={} ; i=1 - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - t[i] = str - i = i + 1 - end - return t -end - --- vim: tabstop=2 shiftwidth=2 noexpandtab diff --git a/test/append_vector.test.cpp b/test/append_vector.test.cpp deleted file mode 100644 index db4949e2..00000000 --- a/test/append_vector.test.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include "external/minunit.h" -#include "append_vector.h" - -using namespace AppendVectorNS; - -MU_TEST(test_append_vector) { - AppendVector vec; - AppendVector vec2; - mu_check(vec.size() == 0); - mu_check(vec.begin() == vec.end()); - mu_check(vec.begin() != vec2.begin()); - - for (int i = 0; i < 10000; i++) { - vec.push_back(i); - } - mu_check(vec.size() == 10000); - - mu_check(vec[25] == 25); - - const AppendVector::Iterator& it = vec.begin(); - mu_check(*it == 0); - mu_check(*(it + 1) == 1); - mu_check(*(it + 2) == 2); - mu_check(*(it + 9000) == 9000); - mu_check(*(it + 1 - 1) == 0); - mu_check(*(vec.end() + -1) == 9999); - mu_check(*(vec.end() - 1) == 9999); - mu_check(*(vec.end() - 2) == 9998); - mu_check(*(vec.end() - 9000) == 1000); - mu_check(*(vec.begin() - -1) == 1); - - boost::sort::block_indirect_sort( - vec.begin(), - vec.end(), - [](auto const &a, auto const&b) { return b < a; }, - 1 - ); - - mu_check(vec[0] == 9999); - mu_check(vec[9999] == 0); - - boost::sort::block_indirect_sort( - vec.begin(), - vec.end(), - [](auto const &a, auto const&b) { return a < b; }, - 1 - ); - - mu_check(vec[0] == 0); - mu_check(vec[9999] == 9999); - - auto iter = std::lower_bound( - vec.begin(), - vec.end(), - 123, - [](const int32_t& a, const int32_t& toFind) { - return a < toFind; - } - ); - - mu_check(iter != vec.end()); - mu_check(*iter == 123); - - iter = std::lower_bound( - vec.begin(), - vec.end(), - 123123, - [](const int32_t& a, const int32_t& toFind) { - return a < toFind; - } - ); - - mu_check(iter == vec.end()); - - iter = std::lower_bound( - vec.begin(), - vec.end(), - -2, - [](const int32_t& a, const int32_t& toFind) { - return a < toFind; - } - ); - - mu_check(iter == vec.begin()); -} - -MU_TEST_SUITE(test_suite_append_vector) { - MU_RUN_TEST(test_append_vector); -} - -int main() { - MU_RUN_SUITE(test_suite_append_vector); - MU_REPORT(); - return MU_EXIT_CODE; -} - diff --git a/test/attribute_store.test.cpp b/test/attribute_store.test.cpp deleted file mode 100644 index aa3c842f..00000000 --- a/test/attribute_store.test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include "external/minunit.h" -#include "attribute_store.h" - -MU_TEST(test_attribute_store) { - AttributeStore store; - store.reset(); - - mu_check(store.size() == 0); - - AttributeSet s1; - store.addAttribute(s1, "str1", std::string("someval"), 0); - store.addAttribute(s1, "str2", std::string("a very long string"), 14); - store.addAttribute(s1, "bool1", false, 0); - store.addAttribute(s1, "bool2", true, 0); - store.addAttribute(s1, "float1", (float)42.0, 4); - - const auto s1Index = store.add(s1); - - mu_check(store.size() == 1); - - const auto s1Pairs = store.getUnsafe(s1Index); - mu_check(s1Pairs.size() == 5); - const auto str1 = std::find_if(s1Pairs.begin(), s1Pairs.end(), [&store](auto ap) { - return ap->keyIndex == store.keyStore.key2index("str1"); - }); - mu_check(str1 != s1Pairs.end()); - mu_check((*str1)->hasStringValue()); - mu_check((*str1)->stringValue() == "someval"); - - const auto str2 = std::find_if(s1Pairs.begin(), s1Pairs.end(), [&store](auto ap) { - return ap->keyIndex == store.keyStore.key2index("str2"); - }); - mu_check(str2 != s1Pairs.end()); - mu_check((*str2)->hasStringValue()); - mu_check((*str2)->stringValue() == "a very long string"); - mu_check((*str2)->minzoom == 14); - - const auto bool1 = std::find_if(s1Pairs.begin(), s1Pairs.end(), [&store](auto ap) { - return ap->keyIndex == store.keyStore.key2index("bool1"); - }); - mu_check(bool1 != s1Pairs.end()); - mu_check((*bool1)->hasBoolValue()); - mu_check((*bool1)->boolValue() == false); - - const auto bool2 = std::find_if(s1Pairs.begin(), s1Pairs.end(), [&store](auto ap) { - return ap->keyIndex == store.keyStore.key2index("bool2"); - }); - mu_check(bool2 != s1Pairs.end()); - mu_check((*bool2)->hasBoolValue()); - mu_check((*bool2)->boolValue() == true); - - const auto float1 = std::find_if(s1Pairs.begin(), s1Pairs.end(), [&store](auto ap) { - return ap->keyIndex == store.keyStore.key2index("float1"); - }); - mu_check(float1 != s1Pairs.end()); - mu_check((*float1)->hasFloatValue()); - mu_check((*float1)->floatValue() == 42); - mu_check((*float1)->minzoom == 4); -} - -MU_TEST(test_attribute_store_reuses) { - AttributeStore store; - store.reset(); - - mu_check(store.size() == 0); - - { - AttributeSet s1a; - store.addAttribute(s1a, "str1", std::string("someval"), 0); - const auto s1aIndex = store.add(s1a); - - AttributeSet s1b; - store.addAttribute(s1b, "str1", std::string("someval"), 0); - const auto s1bIndex = store.add(s1b); - - mu_check(s1aIndex == s1bIndex); - } - - { - AttributeSet s1a; - store.addAttribute(s1a, "str1", std::string("this is a very long string"), 0); - const auto s1aIndex = store.add(s1a); - - AttributeSet s1b; - store.addAttribute(s1b, "str1", std::string("this is a very long string"), 0); - const auto s1bIndex = store.add(s1b); - - mu_check(s1aIndex == s1bIndex); - } -} - -MU_TEST(test_attribute_store_capacity) { - // We support a maximum of 511 attribute name, so confirm that we can roundtrip - // this value. - AttributePair pair(511, true, 0); - mu_check(pair.keyIndex == 511); - - // Confirm that the attribute store will throw if we try to add more than 511 keys. - AttributeKeyStore keys; - - for (int i = 1; i <= 511; i++) { - const uint16_t keyIndex = keys.key2index("key" + std::to_string(i)); - mu_check(keyIndex == i); - } - - // Trying to add a 512th key should throw - bool caughtException = false; - - try { - keys.key2index("key512"); - } catch (std::out_of_range) { - caughtException = true; - } - - mu_check(caughtException == true); -} - -MU_TEST_SUITE(test_suite_attribute_store) { - MU_RUN_TEST(test_attribute_store); - MU_RUN_TEST(test_attribute_store_reuses); - MU_RUN_TEST(test_attribute_store_capacity); -} - -int main() { - MU_RUN_SUITE(test_suite_attribute_store); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/deque_map.test.cpp b/test/deque_map.test.cpp deleted file mode 100644 index 28023542..00000000 --- a/test/deque_map.test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include "external/minunit.h" -#include "deque_map.h" - -MU_TEST(test_deque_map) { - DequeMap strs; - - mu_check(strs.size() == 0); - mu_check(!strs.full()); - mu_check(strs.find("foo") == -1); - mu_check(strs.add("foo") == 0); - mu_check(!strs.full()); - mu_check(strs.find("foo") == 0); - mu_check(strs.size() == 1); - mu_check(strs.add("foo") == 0); - mu_check(strs.size() == 1); - mu_check(strs.add("bar") == 1); - mu_check(strs.size() == 2); - mu_check(strs.add("aardvark") == 2); - mu_check(strs.size() == 3); - mu_check(strs.add("foo") == 0); - mu_check(strs.add("bar") == 1); - mu_check(strs.add("quux") == 3); - mu_check(strs.size() == 4); - - mu_check(strs.at(0) == "foo"); - mu_check(strs[0] == "foo"); - mu_check(strs.at(1) == "bar"); - mu_check(strs[1] == "bar"); - mu_check(strs.at(2) == "aardvark"); - mu_check(strs[2] == "aardvark"); - mu_check(strs.at(3) == "quux"); - mu_check(strs[3] == "quux"); - - std::vector rv; - for (std::string x : strs) { - rv.push_back(x); - } - mu_check(rv[0] == "aardvark"); - mu_check(rv[1] == "bar"); - mu_check(rv[2] == "foo"); - mu_check(rv[3] == "quux"); - - DequeMap boundedMap(1); - mu_check(!boundedMap.full()); - mu_check(boundedMap.add("foo") == 0); - mu_check(boundedMap.add("foo") == 0); - mu_check(boundedMap.full()); - mu_check(boundedMap.add("bar") == -1); - boundedMap.clear(); - mu_check(!boundedMap.full()); - mu_check(boundedMap.find("foo") == -1); - mu_check(boundedMap.add("bar") == 0); - mu_check(boundedMap.add("bar") == 0); - mu_check(boundedMap.full()); -} - -MU_TEST_SUITE(test_suite_deque_map) { - MU_RUN_TEST(test_deque_map); -} - -int main() { - MU_RUN_SUITE(test_suite_deque_map); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/monaco.pbf b/test/monaco.pbf deleted file mode 100644 index 6e6c3122..00000000 Binary files a/test/monaco.pbf and /dev/null differ diff --git a/test/options_parser.test.cpp b/test/options_parser.test.cpp deleted file mode 100644 index 352ae26c..00000000 --- a/test/options_parser.test.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include "external/minunit.h" -#include "options_parser.h" - -const char* PROGRAM_NAME = "./tilemaker"; -using namespace OptionsParser; - -Options parse(std::vector& args) { - const char* argv[100]; - - argv[0] = PROGRAM_NAME; - for(int i = 0; i < args.size(); i++) - argv[1 + i] = args[i].data(); - - return parse(1 + args.size(), argv); -} - -#define ASSERT_THROWS(MESSAGE, ...) \ -{ \ - std::vector args = { __VA_ARGS__ }; \ - bool threw = false; \ - try { \ - auto opts = parse(args); \ - } catch(OptionsParser::OptionException& e) { \ - threw = std::string(e.what()).find(MESSAGE) != std::string::npos; \ - } \ - if (!threw) mu_check((std::string("expected exception with ") + MESSAGE).empty()); \ -} - -MU_TEST(test_options_parser) { - // No args is invalid. - ASSERT_THROWS("You must specify an output file"); - - // Output without input is valid - { - std::vector args = {"--output", "foo.mbtiles"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 0); - } - - // You can ask for --help. - { - std::vector args = {"--help"}; - auto opts = parse(args); - mu_check(opts.showHelp); - } - - // Common happy path is output and input - { - std::vector args = {"--output", "foo.mbtiles", "--input", "ontario.pbf"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 1); - mu_check(opts.inputFiles[0] == "ontario.pbf"); - mu_check(opts.outputFile == "foo.mbtiles"); - mu_check(opts.outputMode == OutputMode::MBTiles); - mu_check(!opts.osm.materializeGeometries); - mu_check(!opts.osm.shardStores); - } - - // --fast without store should have materialized geometries - { - std::vector args = {"--output", "foo.mbtiles", "--input", "ontario.pbf", "--fast"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 1); - mu_check(opts.inputFiles[0] == "ontario.pbf"); - mu_check(opts.outputFile == "foo.mbtiles"); - mu_check(opts.outputMode == OutputMode::MBTiles); - mu_check(opts.osm.materializeGeometries); - mu_check(!opts.osm.shardStores); - } - - // --store should optimize for reduced memory - { - std::vector args = {"--output", "foo.mbtiles", "--input", "ontario.pbf", "--store", "/tmp/store"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 1); - mu_check(opts.inputFiles[0] == "ontario.pbf"); - mu_check(opts.outputFile == "foo.mbtiles"); - mu_check(opts.outputMode == OutputMode::MBTiles); - mu_check(opts.osm.storeFile == "/tmp/store"); - mu_check(!opts.osm.materializeGeometries); - mu_check(opts.osm.shardStores); - } - - // --store --fast should optimize for speed - { - std::vector args = {"--output", "foo.pmtiles", "--input", "ontario.pbf", "--store", "/tmp/store", "--fast"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 1); - mu_check(opts.inputFiles[0] == "ontario.pbf"); - mu_check(opts.outputFile == "foo.pmtiles"); - mu_check(opts.outputMode == OutputMode::PMTiles); - mu_check(opts.osm.storeFile == "/tmp/store"); - mu_check(!opts.osm.materializeGeometries); - mu_check(!opts.osm.shardStores); - } - - // Two input files implies --materialize - { - std::vector args = {"--output", "foo.mbtiles", "--input", "ontario.pbf", "--input", "alberta.pbf"}; - auto opts = parse(args); - mu_check(opts.inputFiles.size() == 2); - mu_check(opts.inputFiles[0] == "ontario.pbf"); - mu_check(opts.inputFiles[1] == "alberta.pbf"); - mu_check(opts.outputFile == "foo.mbtiles"); - mu_check(opts.outputMode == OutputMode::MBTiles); - mu_check(opts.osm.materializeGeometries); - mu_check(!opts.osm.shardStores); - } - - ASSERT_THROWS("Couldn't open .json config", "--input", "foo", "--output", "bar", "--config", "nonexistent-config.json"); - ASSERT_THROWS("Couldn't open .lua script", "--input", "foo", "--output", "bar", "--process", "nonexistent-script.lua"); -} - -MU_TEST_SUITE(test_suite_options_parser) { - MU_RUN_TEST(test_options_parser); -} - -int main() { - MU_RUN_SUITE(test_suite_options_parser); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/pbf_reader.test.cpp b/test/pbf_reader.test.cpp deleted file mode 100644 index 8b15468f..00000000 --- a/test/pbf_reader.test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include "external/minunit.h" -#include "pbf_reader.h" - -MU_TEST(test_pbf_reader) { - std::ifstream monaco("test/monaco.pbf", std::ifstream::in); - - PbfReader::PbfReader reader; - PbfReader::BlobHeader bh = reader.readBlobHeader(monaco); - protozero::data_view blob = reader.readBlob(bh.datasize, monaco); - PbfReader::HeaderBlock header = reader.readHeaderBlock(blob); - - mu_check(header.hasBbox); - mu_check(header.optionalFeatures.size() == 1); - mu_check(header.optionalFeatures.find("Sort.Type_then_ID") != header.optionalFeatures.end()); - - mu_check(header.bbox.minLon == 7.409205); - mu_check(header.bbox.maxLon == 7.448637); - mu_check(header.bbox.minLat == 43.723350); - mu_check(header.bbox.maxLat == 43.751690); - - - bool foundNode = false, foundWay = false, foundRelation = false; - int blocks = 0, groups = 0, strings = 0, nodes = 0, ways = 0, relations = 0; - while (!monaco.eof()) { - bh = reader.readBlobHeader(monaco); - if (bh.type == "eof") - break; - - - blocks++; - blob = reader.readBlob(bh.datasize, monaco); - - PbfReader::PrimitiveBlock pb = reader.readPrimitiveBlock(blob); - - for (const auto str : pb.stringTable) { - if (strings == 200) { - std::string s(str.data(), str.size()); - mu_check(s == "description:FR"); - } - strings++; - } - - for (const auto& group : pb.groups()) { - groups++; - for (const auto& node : group.nodes()) { - nodes++; - - if (node.id == 21911886) { - foundNode = true; - - bool foundHighwayCrossing = false; - - for (int i = node.tagStart; i < node.tagEnd; i += 2) { - const auto keyIndex = group.translateNodeKeyValue(i); - const auto valueIndex = group.translateNodeKeyValue(i + 1); - std::string key(pb.stringTable[keyIndex].data(), pb.stringTable[keyIndex].size()); - std::string value(pb.stringTable[valueIndex].data(), pb.stringTable[valueIndex].size()); - - if (key == "highway" && value == "crossing") - foundHighwayCrossing = true; - } - mu_check(foundHighwayCrossing); - } - } - - for (const auto& way : group.ways()) { - ways++; - - if (way.id == 4224978) { - foundWay = true; - - bool foundSportSoccer = false; - for (int i = 0; i < way.keys.size(); i++) { - std::string key(pb.stringTable[way.keys[i]].data(), pb.stringTable[way.keys[i]].size()); - std::string value(pb.stringTable[way.vals[i]].data(), pb.stringTable[way.vals[i]].size()); - - if (key == "sport" && value == "soccer") - foundSportSoccer = true; - } - mu_check(foundSportSoccer); - - mu_check(way.refs.size() == 5); - mu_check(way.refs[0] == 25178088); - mu_check(way.refs[2] == 25178045); - mu_check(way.refs[4] == 25178088); - } - } - - for (const auto& relation : group.relations()) { - relations++; - - if (relation.id == 1124039) { - foundRelation = true; - mu_check(relation.memids.size() == 17); - mu_check(relation.types.size() == 17); - mu_check(relation.roles_sid.size() == 17); - mu_check(relation.types[0] == PbfReader::Relation::MemberType::NODE); - mu_check(relation.types[2] == PbfReader::Relation::MemberType::WAY); - mu_check(relation.types[16] == PbfReader::Relation::MemberType::RELATION); - } - } - } - } - - //std::cout << blocks << " blocks, " << groups << " groups, " << nodes << " nodes, " << ways << " ways, " << relations << " relations" << std::endl; - - mu_check(foundNode); - mu_check(foundWay); - mu_check(foundRelation); - - mu_check(blocks == 6); - mu_check(groups == 6); - mu_check(strings == 8236); - mu_check(nodes == 30477); - mu_check(ways == 4825); - mu_check(relations == 285); -} - -MU_TEST_SUITE(test_suite_pbf_reader) { - MU_RUN_TEST(test_pbf_reader); -} - -int main() { - MU_RUN_SUITE(test_suite_pbf_reader); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/pooled_string.test.cpp b/test/pooled_string.test.cpp deleted file mode 100644 index 93a05843..00000000 --- a/test/pooled_string.test.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "external/minunit.h" -#include "pooled_string.h" - -MU_TEST(test_pooled_string) { - mu_check(PooledString("").size() == 0); - mu_check(PooledString("").toString() == ""); - mu_check(PooledString("f").size() == 1); - mu_check(PooledString("f").toString() == "f"); - mu_check(PooledString("hi").size() == 2); - mu_check(PooledString("f") == PooledString("f")); - mu_check(PooledString("f") != PooledString("g")); - - mu_check(PooledString("this is more than fifteen bytes").size() == 31); - mu_check(PooledString("this is more than fifteen bytes") != PooledString("f")); - - PooledString big("this is also a really long string"); - mu_check(big == big); - mu_check(big.toString() == "this is also a really long string"); - - PooledString big2("this is also a quite long string"); - mu_check(big != big2); - mu_check(big.toString() != big2.toString()); - - std::string shortString("short"); - protozero::data_view shortStringView = { shortString.data(), shortString.size() }; - std::string longString("this is a very long string"); - protozero::data_view longStringView = { longString.data(), longString.size() }; - - PooledString stdShortString(&shortStringView); - mu_check(stdShortString.size() == 5); - mu_check(stdShortString.toString() == "short"); - - PooledString stdLongString(&longStringView); - mu_check(stdLongString.size() == 26); - mu_check(stdLongString.toString() == "this is a very long string"); - - // PooledStrings that are backed by std::string have the usual - // == semantics. - mu_check(stdShortString == PooledString("short")); - mu_check(PooledString("short") == stdShortString); - - mu_check(stdLongString == PooledString("this is a very long string")); - mu_check(PooledString("this is a very long string") == stdLongString); - - mu_check(stdShortString != stdLongString); -} - -MU_TEST_SUITE(test_suite_pooled_string) { - MU_RUN_TEST(test_pooled_string); -} - -int main() { - MU_RUN_SUITE(test_suite_pooled_string); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/relation_roles.test.cpp b/test/relation_roles.test.cpp deleted file mode 100644 index 2cf8c438..00000000 --- a/test/relation_roles.test.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include "external/minunit.h" -#include "relation_roles.h" - -MU_TEST(test_relation_roles) { - RelationRoles rr; - - mu_check(rr.getRole(0) == ""); - mu_check(rr.getOrAddRole("inner") == rr.getOrAddRole("inner")); - mu_check(rr.getOrAddRole("never before seen") == rr.getOrAddRole("never before seen")); - mu_check(rr.getRole(rr.getOrAddRole("inner")) == "inner"); - mu_check(rr.getRole(rr.getOrAddRole("never before seen")) == "never before seen"); -} - -MU_TEST_SUITE(test_suite_relation_roles) { - MU_RUN_TEST(test_relation_roles); -} - -int main() { - MU_RUN_SUITE(test_suite_relation_roles); - MU_REPORT(); - return MU_EXIT_CODE; -} - diff --git a/test/significant_tags.test.cpp b/test/significant_tags.test.cpp deleted file mode 100644 index 33e26948..00000000 --- a/test/significant_tags.test.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include "external/minunit.h" -#include "significant_tags.h" -#include "tag_map.h" - -MU_TEST(test_parse_filter) { - { - TagFilter expected{true, "foo", ""}; - mu_check(SignificantTags::parseFilter("foo") == expected); - } - - { - TagFilter expected{false, "foo", ""}; - mu_check(SignificantTags::parseFilter("~foo") == expected); - } - - { - TagFilter expected{true, "foo", "bar"}; - mu_check(SignificantTags::parseFilter("foo=bar") == expected); - } - - { - TagFilter expected{false, "foo", "bar"}; - mu_check(SignificantTags::parseFilter("~foo=bar") == expected); - } - -} - -MU_TEST(test_invalid_significant_tags) { - bool threw = false; - try { - // Filters must be all accept, or all reject, not a mix. - SignificantTags tags({"a", "~b"}); - } catch (...) { - threw = true; - } - - mu_check(threw); -} - -MU_TEST(test_significant_tags) { - const std::string building = "building"; - const std::string yes = "yes"; - const std::string name = "name"; - const std::string nameValue = "Some name"; - const std::string power = "power"; - const std::string tower = "tower"; - - // If created with no list, it's not enabled and all things pass filter. - // This is the case when people omit `node_keys` or `way_keys`. - { - SignificantTags tags; - TagMap map; - mu_check(tags.filter(map)); - } - - // If created with empty list, it rejects all things. - // This is the case when people write `way_keys = {}`, e.g. when creating - // an extract that only parses nodes. - { - std::vector empty; - SignificantTags tags(empty); - TagMap map; - mu_check(!tags.filter(map)); - } - - // If created in default-accept mode, it accepts anything with an unmatched tag. - // This is the case when people write `way_keys = {"-building"}` - { - std::vector defaultAccept{"~building"}; - SignificantTags tags(defaultAccept); - - { - TagMap map; - map.addTag(building, yes); - mu_check(!tags.filter(map)); - } - - { - TagMap map; - map.addTag(building, yes); - map.addTag(name, nameValue); - mu_check(tags.filter(map)); - } - - } - - // If created in default-reject mode, it accepts anything with a matched tag. - // This is the case when people write `way_keys = {"power=tower"}` - { - std::vector defaultReject{"power=tower"}; - SignificantTags tags(defaultReject); - - { - TagMap map; - mu_check(!tags.filter(map)); - } - - { - TagMap map; - map.addTag(power, tower); - mu_check(tags.filter(map)); - } - - } -} - -MU_TEST_SUITE(test_suite_significant_tags) { - MU_RUN_TEST(test_parse_filter); - MU_RUN_TEST(test_significant_tags); - MU_RUN_TEST(test_invalid_significant_tags); -} - -int main() { - MU_RUN_SUITE(test_suite_significant_tags); - MU_REPORT(); - return MU_EXIT_CODE; -} - diff --git a/test/sorted_node_store.test.cpp b/test/sorted_node_store.test.cpp deleted file mode 100644 index de66445f..00000000 --- a/test/sorted_node_store.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "external/minunit.h" -#include "sorted_node_store.h" - -MU_TEST(test_sorted_node_store) { - bool compressed = true; - - for (int i = 0; i < 2; i++) { - compressed = !compressed; - SortedNodeStore s1(compressed), s2(compressed); - mu_check(s1.size() == 0); - mu_check(s2.size() == 0); - - s1.batchStart(); - s2.batchStart(); - - s1.insert({ {1, {2, 3 } } }); - s2.insert({ {2, {3, 4 } } }); - - s1.finalize(1); - s2.finalize(1); - - mu_check(s1.size() == 1); - mu_check(s1.at(1) == LatpLon({2, 3})); - mu_check(s1.contains(0, 1)); - mu_check(!s1.contains(0, 2)); - mu_check(!s1.contains(0, 1ull << 34)); - mu_check(s2.size() == 1); - mu_check(s2.at(2) == LatpLon({3, 4})); - } -} - -MU_TEST_SUITE(test_suite_sorted_node_store) { - MU_RUN_TEST(test_sorted_node_store); -} - -int main() { - MU_RUN_SUITE(test_suite_sorted_node_store); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/sorted_way_store.test.cpp b/test/sorted_way_store.test.cpp deleted file mode 100644 index 02749924..00000000 --- a/test/sorted_way_store.test.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include "external/minunit.h" -#include "sorted_way_store.h" -#include "node_store.h" - -class TestNodeStore : public NodeStore { - void clear() override {} - void reopen() override {} - void batchStart() override {} - void finalize(size_t threadNum) override {} - size_t size() const override { return 1; } - LatpLon at(NodeID id) const override { - return { (int32_t)id, -(int32_t)id }; - } - void insert(const std::vector>& elements) override {} - - bool contains(size_t shard, NodeID id) const override { return true; } - NodeStore& shard(size_t shard) override { return *this; } - const NodeStore& shard(size_t shard) const override { return *this; } - - size_t shards() const override { return 1; } -}; - -void roundtripWay(const std::vector& way) { - bool compress = false; - - for (int i = 0; i < 2; i++) { - std::vector output; - uint16_t flags = SortedWayStore::encodeWay(way, output, compress); - - if (false) { - std::cout << "input="; - for (const auto& node : way) { - std::cout << node << " "; - } - std::cout << std::endl; - std::cout << "flags=" << flags << ", output.size()=" << output.size() << ", "; - - for (const uint8_t byte : output) - std::cout << " " << std::to_string(byte); - std::cout << std::endl; - } - - const std::vector roundtrip = SortedWayStore::decodeWay(flags, &output[0]); - - mu_check(roundtrip.size() == way.size()); - for (int i = 0; i < way.size(); i++) { - //std::cout << "roundtrip[" << i << "]=" << roundtrip[i] << ", way[" << i << "]=" << way[i] << std::endl; - mu_check(roundtrip[i] == way[i]); - } - compress = !compress; - } -} - -MU_TEST(test_encode_way) { - roundtripWay({ 1 }); - roundtripWay({ 1, 2 }); - roundtripWay({ 1, 2, 1 }); - roundtripWay({ 1, 2, 3, 4 }); - roundtripWay({ 4294967295, 4294967297, 8589934592, 4, 5 }); - // 11386679771 uses the full lower 32-bits, so is a good test case that - // zigzag encoding hasn't broken anything. - roundtripWay({ 5056880431, 538663248, 538663257, 538663260, 538663263, 11386679771, 538663266 }); - - // When the high bytes are all the same, it should take - // less space to encode. - { - std::vector output; - SortedWayStore::encodeWay({ 1, 2, 3, 4 }, output, false); - const uint16_t l1 = output.size(); - - SortedWayStore::encodeWay({ 1, 8589934592, 3, 4 }, output, false); - const uint16_t l2 = output.size(); - - mu_check(l1 < l2); - } -} - -MU_TEST(test_multiple_stores) { - bool compressed = false; - - for (int i = 0; i < 2; i++) { - compressed = !compressed; - TestNodeStore ns; - SortedWayStore s1(compressed, ns), s2(compressed, ns); - s1.batchStart(); - s2.batchStart(); - - s1.insertNodes({{ 1, { 1 } }}); - - // We store small ways differently than large ways, so - // store both kinds for testing. - std::vector longWay; - for (int i = 200; i < 2048; i++) - longWay.push_back(i + 3 * (i % 37)); - - s1.insertNodes({{ 42, longWay }}); - s2.insertNodes({{ 2, { 2 } }}); - - s1.finalize(1); - s2.finalize(1); - - mu_check(s1.size() == 2); - mu_check(s2.size() == 1); - - mu_check(s1.contains(0, 1)); - mu_check(s1.contains(0, 42)); - mu_check(!s1.contains(0, 2)); - } -} - -MU_TEST(test_way_store) { - TestNodeStore ns; - SortedWayStore sws(true, ns); - sws.batchStart(); - - std::vector>> ways; - std::vector shortWay; - shortWay.push_back(123); - ways.push_back(std::make_pair(1, shortWay)); - ways.push_back(std::make_pair(2, shortWay)); - ways.push_back(std::make_pair(513, shortWay)); - - std::vector longWay; - for(int i = 200; i < 300; i++) - longWay.push_back(i); - ways.push_back(std::make_pair(65536, longWay)); - ways.push_back(std::make_pair(131072, longWay)); - - sws.insertNodes(ways); - sws.finalize(1); - - mu_check(sws.size() == 5); - - { - const auto& rv = sws.at(1); - mu_check(rv.size() == 1); - mu_check(rv[0].latp == 123); - } - - { - const auto& rv = sws.at(2); - mu_check(rv.size() == 1); - mu_check(rv[0].latp == 123); - } - - { - const auto& rv = sws.at(513); - mu_check(rv.size() == 1); - mu_check(rv[0].latp == 123); - } - - { - const auto& rv = sws.at(65536); - mu_check(rv.size() == 100); - mu_check(rv[0].latp == 200); - mu_check(rv[99].latp == 299); - } - - { - const auto& rv = sws.at(131072); - mu_check(rv.size() == 100); - mu_check(rv[0].latp == 200); - mu_check(rv[99].latp == 299); - } - - // missing things should throw std::out_of_range - - bool threw = false; - try { - sws.at(123123123); - } catch (std::out_of_range &e) { - threw = true; - } catch (...) {} - mu_check(threw == true); - - threw = false; - try { - sws.at(3); - } catch (std::out_of_range &e) { - threw = true; - } catch (...) {} - mu_check(threw == true); - -} - -MU_TEST(test_populate_mask) { - uint8_t mask[32]; - std::vector ids; - - { - // No ids: all 0s - populateMask(mask, ids); - for(int i = 0; i < 32; i++) - mu_check(mask[i] == 0); - } - - { - // Every id: all 1s - for(int i = 0; i < 256; i++) - ids.push_back(i); - populateMask(mask, ids); - for(int i = 0; i < 32; i++) - mu_check(mask[i] == 255); - } - - { - // Every other ID - ids.clear(); - for (int i = 0; i < 256; i += 2) - ids.push_back(i); - populateMask(mask, ids); - for(int i = 0; i < 32; i++) - mu_check(mask[i] == 0b01010101); - } -} - -MU_TEST_SUITE(test_suite_sorted_way_store) { - MU_RUN_TEST(test_encode_way); - MU_RUN_TEST(test_multiple_stores); - MU_RUN_TEST(test_way_store); -} - -MU_TEST_SUITE(test_suite_bitmask) { - MU_RUN_TEST(test_populate_mask); -} - -int main() { - MU_RUN_SUITE(test_suite_sorted_way_store); - MU_RUN_SUITE(test_suite_bitmask); - MU_REPORT(); - return MU_EXIT_CODE; -} diff --git a/test/test.jsonl b/test/test.jsonl deleted file mode 100644 index 915b080c..00000000 --- a/test/test.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{} -{"foo":1} -{"x":true} diff --git a/test/tile_coordinates_set.test.cpp b/test/tile_coordinates_set.test.cpp deleted file mode 100644 index 87a054b8..00000000 --- a/test/tile_coordinates_set.test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include "external/minunit.h" -#include "tile_coordinates_set.h" - -MU_TEST(test_tile_coordinates_set) { - { - PreciseTileCoordinatesSet z0(0); - mu_check(z0.test(0, 0) == false); - mu_check(z0.size() == 0); - mu_check(z0.zoom() == 0); - - z0.set(0, 0); - mu_check(z0.test(0, 0) == true); - mu_check(z0.size() == 1); - } - - { - PreciseTileCoordinatesSet z6(6); - mu_check(z6.test(0, 0) == false); - - z6.set(0, 0); - mu_check(z6.test(0, 0) == true); - mu_check(z6.test(1, 0) == false); - mu_check(z6.test(0, 1) == false); - mu_check(z6.size() == 1); - mu_check(z6.zoom() == 6); - } - - // Wrapped sets should extrapolate from lower zooms - { - PreciseTileCoordinatesSet z1(1); - LossyTileCoordinatesSet z2(2, z1); - - mu_check(z2.size() == 0); - for (int x = 0; x < 4; x++) { - for (int y = 0; y < 4; y++) { - mu_check(z2.test(x, y) == false); - } - } - z1.set(0, 0); - mu_check(z2.size() == 4); - mu_check(z2.test(0, 0) == true); - mu_check(z2.test(0, 1) == true); - mu_check(z2.test(1, 0) == true); - mu_check(z2.test(1, 1) == true); - mu_check(z2.test(2, 2) == false); - } -} - -MU_TEST_SUITE(test_suite_tile_coordinates_set) { - MU_RUN_TEST(test_tile_coordinates_set); -} - -int main() { - MU_RUN_SUITE(test_suite_tile_coordinates_set); - MU_REPORT(); - return MU_EXIT_CODE; -}