[openstreetmap-carto] 01/04: Imported Upstream version 4.0.0

Bas Couwenberg sebastic at debian.org
Sun May 28 08:14:45 UTC 2017


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository openstreetmap-carto.

commit c408e5ab5e112366878313e2b13c0656a84fe7a7
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sun May 28 10:11:35 2017 +0200

    Imported Upstream version 4.0.0
---
 .travis.yml                         |   9 +-
 CHANGELOG.md                        |  17 +-
 CONTRIBUTING.md                     |  14 +-
 INSTALL.md                          |   8 +-
 README.md                           |   7 +-
 openstreetmap-carto.lua             | 422 ++++++++++++++++++++++++++++++++++++
 openstreetmap-carto.style           | 141 ++----------
 project.mml                         | 100 ++++-----
 scripts/lua/README.md               |   5 +
 scripts/lua/openstreetmap-carto.lua |   1 +
 scripts/lua/test.lua                | 165 ++++++++++++++
 water.mss                           |  12 +-
 12 files changed, 712 insertions(+), 189 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 3426d02..3a6229b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,9 +2,12 @@ language: node_js
 sudo: false
 node_js:
   - "0.10"
+addons:
+  apt:
+    packages:
+    - lua5.1
 env:
-  - CARTO=0.16.0 MAPNIK='3.0.0 3.0.12'
-  - CARTO=0.16.3 MAPNIK='3.0.0 3.0.12'
+  - CARTO=0.18.0 MAPNIK='3.0.0 3.0.12'
 install:
   - npm install carto@$CARTO
   - mkdir -p data/world_boundaries data/simplified-land-polygons-complete-3857 data/ne_110m_admin_0_boundary_lines_land data/ne_10m_populated_places data/land-polygons-split-3857
@@ -16,3 +19,5 @@ script:
   - for m in $MAPNIK; do ./node_modules/carto/bin/carto -a $m project.mml | xmllint - | wc -l; done
   # Validate that the SVGs are valid XML
   - find symbols/ -name '*.svg' | xargs xmllint --noout
+  # Check the Lua transforms
+  - lua scripts/lua/test.lua
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49713e6..8094eb5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,19 @@
-## [Unreleased](https://github.com/gravitystorm/openstreetmap-carto/compare/v3.3.0...master)
+## [Unreleased](https://github.com/gravitystorm/openstreetmap-carto/compare/v4.0.0...master)
+
+## [v4.0.0](https://github.com/gravitystorm/openstreetmap-carto/compare/v3.3.0...v4.0.0)
+### Major changes
+- The database schema has changed from the osm2pgsql default. This requires a database reload.
+- osm2pgsql Lua transforms are used for some preprocessing. This requires osm2pgsql built with lua support, which most versions will have.
+
+### Changes
+- Old-style multipolygons (those with tags on the outer way instead of the relation) are no longer supported
+- Multipolygons composed of multiple areas are now rendered with one label
+- Fixes to various problems determining if an object is an area or not
+- CartoCSS 0.18.0 is required
+
+## [v3.3.1](https://github.com/gravitystorm/openstreetmap-carto/compare/v3.3.0...v3.3.1) - 2017-05-22
+### Changes
+- Fix a regression in intermittent waterways
 
 ## [v3.3.0](https://github.com/gravitystorm/openstreetmap-carto/compare/v3.2.0...v3.3.0) - 2017-05-10
 ### Changes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 107be6f..f6b79ce 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,6 +17,16 @@ contain a cropped screenshot of the problem, and a link to the area. Don't assum
 that we will see exactly what you see. If a particular OSM object is an issue,
 the issue should contain the tagging of the object.
 
+## 3.x compatibility
+
+OpenStreetMap Carto is currently maintaining compatibility in the output of 3.x
+and 4.x to allow users to smoothly transition and reload their databases. Pull
+requests which cannot be backported to 3.x are not being accepted at this time
+and will be closed.
+
+Whenever a pull request is merged into master, it also needs to be backported to
+the 3.x branch at the same time by the person merging.
+
 ## Easy pickings
 
 Some [easy issues](https://github.com/gravitystorm/openstreetmap-carto/issues?q=is%3Aopen+is%3Aissue+label%3Aeasy) have been selected
@@ -26,7 +36,7 @@ that are particularly suitable for new contributors to get familiar with the pro
 
 OpenStreetMap Carto uses a YAML file for defining layers, because it [works much
 better for big projects](https://github.com/gravitystorm/openstreetmap-carto/issues/711).
-This requires CartoCSS 0.16.0 or later. If you need JSON MML, you can generate it
+This requires CartoCSS 0.18.0 or later. If you need JSON MML, you can generate it
 with `python -c 'import sys, yaml, json; json.dump(yaml.safe_load(sys.stdin), sys.stdout)' < project.mml > project.json`
 or the equivalent in a different language.
 
@@ -115,6 +125,8 @@ Because SQL within JSON or YAML will not generally be syntax highlighted, indent
 * Add indentation if necessary for complex function calls, WHERE parenthesis, and CASE statements
 * One space before and after = etc
 * Name SQL subqueries after the layer name (but use underscores)
+* When extracting tags from hstore, use `tags->'foo'`, not `tags -> 'foo'`, and only add parenthesis if needed for order of operations
+* To check if a tag is in the tags hstore, use `tags @> 'foo=>bar'`, relying on automatic conversion from `text` to `hstore`.
 
 ## Map Icon Guidelines
 
diff --git a/INSTALL.md b/INSTALL.md
index afb19d2..0f40031 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,12 +1,12 @@
 # Installation
 
 ## OpenStreetMap data
-You need OpenStreetMap data loaded into a PostGIS database (see below for [dependencies](#dependencies)). These stylesheets currently work only with the osm2pgsql defaults (i.e. database name is `gis`, table names are `planet_osm_point`, etc).
+You need OpenStreetMap data loaded into a PostGIS database (see below for [dependencies](#dependencies)). These stylesheets expect a database generated with osm2pgsql using the pgsql backend (table names of `planet_osm_point`, etc), the default database name (`gis`), and the [lua transforms](https://github.com/openstreetmap/osm2pgsql/blob/master/docs/lua.md) documented in the instructions below.
 
-It's probably easiest to grab an PBF of OSM data from [Mapzen](https://mapzen.com/metro-extracts/) or [geofabrik](http://download.geofabrik.de/). Once you've set up your PostGIS database, import with osm2pgsql:
+Start by setting up your database to have PostGIS and hstore with ``psql -d gis -c 'CREATE EXTENSION postgis; CREATE EXTENSION hstore;'``, then grab some OSM data. It's probably easiest to grab an PBF of OSM data from [Mapzen](https://mapzen.com/metro-extracts/) or [geofabrik](http://download.geofabrik.de/). Once you've done that, import with osm2pgsql:
 
 ```
-osm2pgsql -d gis ~/path/to/data.osm.pbf --style openstreetmap-carto.style
+osm2pgsql -G --hstore --style openstreetmap-carto.style --tag-transform-script openstreetmap-carto.lua -d gis ~/path/to/data.osm.pbf
 ```
 
 You can find a more detailed guide to setting up a database and loading data with osm2pgsql at [switch2osm.org](http://switch2osm.org/loading-osm-data/).
@@ -93,7 +93,7 @@ For development, a style design studio is needed.
 
 For deployment, CartoCSS and Mapnik are required.
 
-* [CartoCSS](https://github.com/mapbox/carto) >= 0.16.0 (we're using YAML)
+* [CartoCSS](https://github.com/mapbox/carto) >= 0.18.0 (we're using YAML)
 * [Mapnik](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) >= 3.0
 
 Remember to run CartoCSS with proper API version to avoid errors (at least 3.0.0: `carto -a "3.0.0"`).
diff --git a/README.md b/README.md
index 82d0a29..361da62 100644
--- a/README.md
+++ b/README.md
@@ -76,10 +76,9 @@ and issues have their own [tag](https://github.com/gravitystorm/openstreetmap-ca
 
 Initial releases will not make use of the new features, maintaining compatibility
 with v3.x and v3.x releases will continue with backports, allowing the style to be
-rendered from either a new database or an old one.
-
-When sufficient time has passed for users to reload their databases, new features
-can be used and 3.x compatibility will not be maintained.
+rendered from either a new database or an old one. In order to allow time for users
+to reload their databases, this will be maintained until at least two MINOR
+releases have occurred. After that compatibility will not be maintained.
 
 # Alternatives
 
diff --git a/openstreetmap-carto.lua b/openstreetmap-carto.lua
new file mode 100644
index 0000000..26117e3
--- /dev/null
+++ b/openstreetmap-carto.lua
@@ -0,0 +1,422 @@
+-- For documentation of Lua tag transformations, see:
+-- https://github.com/openstreetmap/osm2pgsql/blob/master/docs/lua.md
+
+-- Objects with any of the following keys will be treated as polygon
+local polygon_keys = {
+    'abandoned:aeroway',
+    'abandoned:amenity',
+    'abandoned:building',
+    'abandoned:landuse',
+    'abandoned:power',
+    'aeroway',
+    'amenity',
+    'area:highway',
+    'building',
+    'building:part',
+    'harbour',
+    'historic',
+    'landuse',
+    'leisure',
+    'man_made',
+    'military',
+    'natural',
+    'office',
+    'place',
+    'power',
+    'public_transport',
+    'shop',
+    'tourism',
+    'water',
+    'waterway',
+    'wetland'
+}
+
+-- Objects with any of the following key/value combinations will be treated as linestring
+local linestring_values = {
+    leisure = {track = true, slipway = true},
+    man_made = {embankment = true, breakwater = true, groyne = true},
+    natural = {cliff = true, tree_row = true},
+    historic = {citywalls = true},
+    waterway = {canal = true, derelict_canal = true, ditch = true, drain = true, river = true, stream = true, wadi = true, weir = true},
+    power = {line = true, minor_line = true},
+    natural = {ridge = true, arete = true}
+}
+
+-- Objects with any of the following key/value combinations will be treated as polygon
+local polygon_values = {
+    highway = {services = true, rest_area = true},
+    junction = {yes = true}
+}
+
+-- The following keys will be deleted
+local delete_tags = {
+    'note',
+    'source',
+    'source_ref',
+    'attribution',
+    'comment',
+    'fixme',
+    -- Tags generally dropped by editors, not otherwise covered
+    'created_by',
+    'odbl',
+    'odbl:note',
+    -- Lots of import tags
+    -- EUROSHA (Various countries)
+    'project:eurosha_2012',
+
+    -- UrbIS (Brussels, BE)
+    'ref:UrbIS',
+
+    -- NHN (CA)
+    'accuracy:meters',
+    'sub_sea:type',
+    'waterway:type',
+    -- StatsCan (CA)
+    'statscan:rbuid',
+
+    -- RUIAN (CZ)
+    'ref:ruian:addr',
+    'ref:ruian',
+    'building:ruian:type',
+    -- DIBAVOD (CZ)
+    'dibavod:id',
+    -- UIR-ADR (CZ)
+    'uir_adr:ADRESA_KOD',
+
+    -- GST (DK)
+    'gst:feat_id',
+
+    -- Maa-amet (EE)
+    'maaamet:ETAK',
+    -- FANTOIR (FR)
+    'ref:FR:FANTOIR',
+
+    -- 3dshapes (NL)
+    '3dshapes:ggmodelk',
+    -- AND (NL)
+    'AND_nosr_r',
+
+    -- OPPDATERIN (NO)
+    'OPPDATERIN',
+    -- Various imports (PL)
+    'addr:city:simc',
+    'addr:street:sym_ul',
+    'building:usage:pl',
+    'building:use:pl',
+    -- TERYT (PL)
+    'teryt:simc',
+
+    -- RABA (SK)
+    'raba:id',
+    -- DCGIS (Washington DC, US)
+    'dcgis:gis_id',
+    -- Building Identification Number (New York, US)
+    'nycdoitt:bin',
+    -- Chicago Building Inport (US)
+    'chicago:building_id',
+    -- Louisville, Kentucky/Building Outlines Import (US)
+    'lojic:bgnum',
+    -- MassGIS (Massachusetts, US)
+    'massgis:way_id',
+
+    -- misc
+    'import',
+    'import_uuid',
+    'OBJTYPE',
+    'SK53_bulk:load'
+}
+delete_prefixes = {
+    'note:',
+    'source:',
+    -- Corine (CLC) (Europe)
+    'CLC:',
+
+    -- Geobase (CA)
+    'geobase:',
+    -- CanVec (CA)
+    'canvec:',
+    -- Geobase (CA)
+    'geobase:',
+
+    -- osak (DK)
+    'osak:',
+    -- kms (DK)
+    'kms:',
+
+    -- ngbe (ES)
+    -- See also note:es and source:file above
+    'ngbe:',
+
+    -- Friuli Venezia Giulia (IT)
+    'it:fvg:',
+
+    -- KSJ2 (JA)
+    -- See also note:ja and source_ref above
+    'KSJ2:',
+    -- Yahoo/ALPS (JA)
+    'yh:',
+
+    -- LINZ (NZ)
+    'LINZ2OSM:',
+    'linz2osm:',
+    'LINZ:',
+
+    -- WroclawGIS (PL)
+    'WroclawGIS:',
+    -- Naptan (UK)
+    'naptan:',
+
+    -- TIGER (US)
+    'tiger:',
+    -- GNIS (US)
+    'gnis:',
+    -- National Hydrography Dataset (US)
+    'NHD:',
+    'nhd:',
+    -- mvdgis (Montevideo, UY)
+    'mvdgis:'
+}
+
+-- Big table for z_order and roads status for certain tags. z=0 is turned into
+-- nil by the z_order function
+local roads_info = {
+    highway = {
+        motorway        = {z = 380, roads = true},
+        trunk           = {z = 370, roads = true},
+        primary         = {z = 360, roads = true},
+        secondary       = {z = 350, roads = true},
+        tertiary        = {z = 340, roads = false},
+        residential     = {z = 330, roads = false},
+        unclassified    = {z = 330, roads = false},
+        road            = {z = 330, roads = false},
+        living_street   = {z = 320, roads = false},
+        pedestrian      = {z = 310, roads = false},
+        raceway         = {z = 300, roads = false},
+        motorway_link   = {z = 240, roads = true},
+        trunk_link      = {z = 230, roads = true},
+        primary_link    = {z = 220, roads = true},
+        secondary_link  = {z = 210, roads = true},
+        tertiary_link   = {z = 200, roads = false},
+        service         = {z = 150, roads = false},
+        track           = {z = 110, roads = false},
+        path            = {z = 100, roads = false},
+        footway         = {z = 100, roads = false},
+        bridleway       = {z = 100, roads = false},
+        cycleway        = {z = 100, roads = false},
+        steps           = {z = 90,  roads = false},
+        platform        = {z = 90,  roads = false},
+        construction    = {z = 10,  roads = false}
+    },
+    railway = {
+        rail            = {z = 440, roads = true},
+        subway          = {z = 420, roads = true},
+        narrow_gauge    = {z = 420, roads = true},
+        light_rail      = {z = 420, roads = true},
+        funicular       = {z = 420, roads = true},
+        preserved       = {z = 420, roads = false},
+        monorail        = {z = 420, roads = false},
+        miniature       = {z = 420, roads = false},
+        turntable       = {z = 420, roads = false},
+        tram            = {z = 410, roads = false},
+        disused         = {z = 400, roads = false},
+        construction    = {z = 400, roads = false},
+        platform        = {z = 90,  roads = false},
+    },
+    aeroway = {
+        runway          = {z = 60,  roads = false},
+        taxiway         = {z = 50,  roads = false},
+    },
+    boundary = {
+        administrative  = {z = 0,  roads = true}
+    },
+}
+
+local excluded_railway_service = {
+    spur = true,
+    siding = true,
+    yard = true
+}
+--- Gets the z_order for a set of tags
+-- @param tags OSM tags
+-- @return z_order if an object with z_order, otherwise nil
+function z_order(tags)
+    local z = 0
+    for k, v in pairs(tags) do
+        if roads_info[k] and roads_info[k][v] then
+            z = math.max(z, roads_info[k][v].z)
+        end
+    end
+    return z ~= 0 and z or nil
+end
+
+--- Gets the roads table status for a set of tags
+-- @param tags OSM tags
+-- @return 1 if it belongs in the roads table, 0 otherwise
+function roads(tags)
+    for k, v in pairs(tags) do
+        if roads_info[k] and roads_info[k][v] and roads_info[k][v].roads then
+            if not (k ~= 'railway' or tags.service) then
+                return 1
+            elseif not excluded_railway_service[tags.service] then
+                return 1
+            end
+        end
+    end
+    return 0
+end
+
+--- Generic filtering of OSM tags
+-- @param tags Raw OSM tags
+-- @return Filtered OSM tags
+function filter_tags_generic(tags)
+    -- Short-circuit for untagged objects
+    if next(tags) == nil then
+        return 1, {}
+    end
+
+    -- Delete tags listed in delete_tags
+    for _, d in ipairs(delete_tags) do
+        tags[d] = nil
+    end
+
+    -- By using a second loop for wildcards we avoid checking already deleted tags
+    for tag, _ in pairs (tags) do
+        for _, d in ipairs(delete_prefixes) do
+            if string.sub(tag, 1, string.len(d)) == d then
+                tags[tag] = nil
+                break
+            end
+        end
+    end
+
+   -- Filter out objects that have no tags after deleting
+    if next(tags) == nil then
+        return 1, {}
+    end
+
+    -- Convert layer to an integer
+    tags['layer'] = layer(tags['layer'])
+    return 0, tags
+end
+
+-- Filtering on nodes
+function filter_tags_node (keyvalues, numberofkeys)
+    return filter_tags_generic(keyvalues)
+end
+
+-- Filtering on relations
+function filter_basic_tags_rel (keyvalues, numberofkeys)
+    -- Filter out objects that are filtered out by filter_tags_generic
+    local filter, keyvalues = filter_tags_generic(keyvalues)
+    if filter == 1 then
+        return 1, keyvalues
+    end
+
+    -- Filter out all relations except route, multipolygon and boundary relations
+    if ((keyvalues["type"] ~= "route") and (keyvalues["type"] ~= "multipolygon") and (keyvalues["type"] ~= "boundary")) then
+        return 1, keyvalues
+    end
+
+    return 0, keyvalues
+end
+
+-- Filtering on ways
+function filter_tags_way (keyvalues, numberofkeys)
+    local filter = 0  -- Will object be filtered out?
+    local polygon = 0 -- Will object be treated as polygon?
+
+    -- Filter out objects that are filtered out by filter_tags_generic
+    filter, keyvalues = filter_tags_generic(keyvalues)
+    if filter == 1 then
+        return filter, keyvalues, polygon, roads
+    end
+
+    polygon = isarea(keyvalues)
+
+    -- Add z_order column
+    keyvalues["z_order"] = z_order(keyvalues)
+
+    return filter, keyvalues, polygon, roads(keyvalues)
+end
+
+--- Handling for relation members and multipolygon generation
+-- @param keyvalues OSM tags, after processing by relation transform
+-- @param keyvaluemembers OSM tags of relation members, after processing by way transform
+-- @param roles OSM roles of relation members
+-- @param membercount number of members
+-- @return filter, cols, member_superseded, boundary, polygon, roads
+function filter_tags_relation_member (keyvalues, keyvaluemembers, roles, membercount)
+    local members_superseded = {}
+
+    -- Start by assuming that this not an old-style MP
+    for i = 1, membercount do
+        members_superseded[i] = 0
+    end
+
+    local type = keyvalues["type"]
+
+    -- Remove type key
+    keyvalues["type"] = nil
+
+    -- Filter out relations with just a type tag or no tags
+    if next(keyvalues) == nil then
+        return 1, keyvalues, members_superseded, 0, 0, 0
+    end
+
+    if type == "boundary" or (type == "multipolygon" and keyvalues["boundary"]) then
+        keyvalues.z_order = z_order(keyvalues)
+        return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
+    -- For multipolygons...
+    elseif (type == "multipolygon") then
+        -- Multipolygons by definition are polygons, so we know roads = linestring = 0, polygon = 1
+        keyvalues.z_order = z_order(keyvalues)
+        return 0, keyvalues, members_superseded, 0, 1, 0
+    elseif type == "route" then
+        keyvalues.z_order = z_order(keyvalues)
+        return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
+    end
+
+    -- Unknown type of relation or no type tag
+    return 1, keyvalues, members_superseded, 0, 0, 0
+end
+
+--- Check if an object with given tags should be treated as polygon
+-- @param tags OSM tags
+-- @return 1 if area, 0 if linear
+function isarea (tags)
+    -- Treat objects tagged as area=yes polygon, other area as no
+    if tags["area"] then
+        return tags["area"] == "yes" and 1 or 0
+    end
+
+   -- Search through object's tags
+    for k, v in pairs(tags) do
+        -- Check if it has a polygon key and not a linestring override, or a polygon k=v
+        for _, ptag in ipairs(polygon_keys) do
+            if k == ptag and not (linestring_values[k] and linestring_values[k][v]) then
+                return 1
+            end
+        end
+
+        if (polygon_values[k] and polygon_values[k][v]) then
+            return 1
+        end
+    end
+    return 0
+end
+
+function is_in (needle, haystack)
+    for index, value in ipairs (haystack) do
+        if value == needle then
+            return true
+        end
+    end
+    return false
+end
+
+--- Normalizes layer tags
+-- @param v The layer tag value
+-- @return An integer for the layer tag
+function layer (v)
+    return v and string.find(v, "^-?%d+$") and tonumber(v) < 100 and tonumber(v) > -100 and v or nil
+end
diff --git a/openstreetmap-carto.style b/openstreetmap-carto.style
index d3a005c..77134cb 100644
--- a/openstreetmap-carto.style
+++ b/openstreetmap-carto.style
@@ -1,154 +1,55 @@
-# This is the .style file for OpenStreetMap Carto, which is currently
-# the same as the upstream osm2pgsql style
-# phstore is used instead of polygon,nocolumn to preserve compatibility
-# with older osm2pgsql versions
+# This is the osm2pgsql .style file for openstreetmap-carto.
+# It is inteded to be used with openstreetmap-carto.lua and osm2pgsql Lua
+# transforms. Full usage details are in INSTALL.md
+# Among things, this means that the linear vs polygon distinction in this file
+# doesn't matter, because that is set in the Lua and this file is only used for
+# column names and types.
 
 # OsmType  Tag          DataType     Flags
 node,way   access       text         linear
 node,way   addr:housename      text  linear
 node,way   addr:housenumber    text  linear
-node,way   addr:interpolation  text  linear
+way        addr:interpolation  text  linear
 node,way   admin_level  text         linear
 node,way   aerialway    text         linear
 node,way   aeroway      text         polygon
 node,way   amenity      text         polygon
-node,way   area         text         polygon # hard coded support for area=1/yes => polygon is in osm2pgsql
 node,way   barrier      text         linear
-node,way   bicycle      text         linear
-node,way   brand        text         linear
-node,way   bridge       text         linear
+way        bicycle      text         linear
+way        bridge       text         linear
 node,way   boundary     text         linear
 node,way   building     text         polygon
-node       capital      text         linear
-node,way   construction text         linear
-node,way   covered      text         linear
-node,way   culvert      text         linear
-node,way   cutting      text         linear
-node,way   denomination text         linear
-node,way   disused      text         linear
-node       ele          text         linear
-node,way   embankment   text         linear
-node,way   foot         text         linear
-node,way   generator:source    text  linear
-node,way   harbour      text         polygon
+way        construction text         linear
+way        covered      text         linear
+way        foot         text         linear
 node,way   highway      text         linear
 node,way   historic     text         polygon
-node,way   horse        text         linear
-node,way   intermittent text         linear
+way        horse        text         linear
 node,way   junction     text         linear
 node,way   landuse      text         polygon
-node,way   layer        text         linear
+node,way   layer        int4         linear
 node,way   leisure      text         polygon
 node,way   lock         text         linear
 node,way   man_made     text         polygon
 node,way   military     text         polygon
-node,way   motorcar     text         linear
 node,way   name         text         linear
-node,way   natural      text         polygon  # natural=coastline tags are discarded by a hard coded rule in osm2pgsql
-node,way   office       text         polygon
+node,way   natural      text         polygon
 node,way   oneway       text         linear
-node,way   operator     text         linear
 node,way   place        text         polygon
-node,way   population   text         linear
 node,way   power        text         polygon
-node,way   power_source text         linear
-node,way   public_transport text     polygon
 node,way   railway      text         linear
 node,way   ref          text         linear
 node,way   religion     text         linear
-node,way   route        text         linear
-node,way   service      text         linear
+way        route        text         linear
+way        service      text         linear
 node,way   shop         text         polygon
-node,way   sport        text         polygon
-node,way   surface      text         linear
-node,way   toll         text         linear
+way        surface      text         linear
 node,way   tourism      text         polygon
-node,way   tower:type   text         linear
 way        tracktype    text         linear
-node,way   tunnel       text         linear
+way        tunnel       text         linear
 node,way   water        text         polygon
 node,way   waterway     text         polygon
-node,way   wetland      text         polygon
-node,way   width        text         linear
-node,way   wood         text         linear
-node,way   z_order      int4         linear # This is calculated during import
 way        way_area     real         linear # This is calculated during import
 
-# Area tags
-# We don't make columns for these tags, but objects with them are areas.
-way         abandoned:aeroway       text    phstore
-way         abandoned:amenity       text    phstore
-way         abandoned:building      text    phstore
-way         abandoned:landuse       text    phstore
-way         abandoned:power         text    phstore
-way         area:highway            text    phstore
-
-# Deleted tags
-# These are tags that are generally regarded as useless for most rendering.
-# Most of them are from imports or intended as internal information for mappers
-# Some of them are automatically deleted by editors.
-# If you want some of them, perhaps for a debugging layer, just delete the lines.
-
-# These tags are used by mappers to keep track of data.
-# They aren't very useful for rendering.
-node,way    note                    text    delete
-node,way    note:*                  text    delete
-node,way    source                  text    delete
-node,way    source_ref              text    delete
-node,way    source:*                text    delete
-node,way    attribution             text    delete
-node,way    comment                 text    delete
-node,way    fixme                   text    delete
-
-# Tags generally dropped by editors, not otherwise covered
-node,way    created_by              text    delete
-node,way    odbl                    text    delete
-node,way    odbl:note               text    delete
-node,way    SK53_bulk:load          text    delete
-
-# Lots of import tags
-# TIGER (US)
-node,way    tiger:*                 text    delete
-
-# NHD (US)
-# NHD has been converted every way imaginable
-node,way    NHD:*                   text    delete
-node,way    nhd:*                   text    delete
-
-# GNIS (US)
-node,way    gnis:*                  text    delete
-
-# Geobase (CA)
-node,way    geobase:*               text    delete
-# NHN (CA)
-node,way    accuracy:meters         text    delete
-node,way    sub_sea:type            text    delete
-node,way    waterway:type           text    delete
-
-# KSJ2 (JA)
-# See also note:ja and source_ref above
-node,way    KSJ2:*                  text    delete
-# Yahoo/ALPS (JA)
-node,way    yh:*                    text    delete
-
-# osak (DK)
-node,way    osak:*                  text    delete
-
-# kms (DK)
-node,way    kms:*                   text    delete
-
-# ngbe (ES)
-# See also note:es and source:file above
-node,way    ngbe:*                  text    delete
-
-# naptan (UK)
-node,way    naptan:*                text    delete
-
-# Corine (CLC) (Europe)
-node,way    CLC:*                   text    delete
-
-# misc
-node,way    3dshapes:ggmodelk       text    delete
-node,way    AND_nosr_r              text    delete
-node,way    import                  text    delete
-node,way    it:fvg:*                text    delete
+# Columns defined in openstreetmap-carto.lua file
+way        z_order      int4         linear
diff --git a/project.mml b/project.mml
index f986ca1..023fcab 100644
--- a/project.mml
+++ b/project.mml
@@ -108,14 +108,14 @@ Layer:
               way, COALESCE(name, '') AS name,
               ('landuse_' || (CASE WHEN landuse IN ('forest', 'military') THEN landuse ELSE NULL END)) AS landuse,
               ('natural_' || (CASE WHEN "natural" IN ('wood', 'sand', 'scree', 'shingle', 'bare_rock') THEN "natural" ELSE NULL END)) AS "natural",
-              ('wetland_' || (CASE WHEN "natural" IN ('wetland', 'mud') THEN (CASE WHEN "natural" IN ('mud') THEN "natural" ELSE wetland END) ELSE NULL END)) AS wetland,
+              ('wetland_' || (CASE WHEN "natural" IN ('wetland', 'mud') THEN (CASE WHEN "natural" IN ('mud') THEN "natural" ELSE tags->'wetland' END) ELSE NULL END)) AS wetland,
               way_area/NULLIF(!pixel_width!::real*!pixel_height!::real,0) AS way_pixels
             FROM planet_osm_polygon
             WHERE (landuse IN ('forest', 'military')
               OR "natural" IN ('wood', 'wetland', 'mud', 'sand', 'scree', 'shingle', 'bare_rock'))
               AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
               AND building IS NULL
-            ORDER BY CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END, way_area DESC
+            ORDER BY COALESCE(layer,0), way_area DESC
           ) AS features
         ) AS landcover_low_zoom
     properties:
@@ -146,7 +146,7 @@ Layer:
                                                     'track', 'dog_park') THEN leisure ELSE NULL END)) AS leisure,
               ('military_' || (CASE WHEN military IN ('danger_area') THEN military ELSE NULL END)) AS military,
               ('natural_' || (CASE WHEN "natural" IN ('beach', 'shoal', 'heath', 'grassland', 'wood', 'sand', 'scree', 'shingle', 'bare_rock', 'scrub') THEN "natural" ELSE NULL END)) AS "natural",
-              ('wetland_' || (CASE WHEN "natural" IN ('wetland', 'marsh', 'mud') THEN (CASE WHEN "natural" IN ('marsh', 'mud') THEN "natural" ELSE wetland END) ELSE NULL END)) AS wetland,
+              ('wetland_' || (CASE WHEN "natural" IN ('wetland', 'marsh', 'mud') THEN (CASE WHEN "natural" IN ('marsh', 'mud') THEN "natural" ELSE tags->'wetland' END) ELSE NULL END)) AS wetland,
               ('power_' || (CASE WHEN power IN ('station', 'sub_station', 'substation', 'generator') THEN power ELSE NULL END)) AS power,
               ('tourism_' || (CASE WHEN tourism IN ('attraction', 'camp_site', 'caravan_site', 'picnic_site') THEN tourism ELSE NULL END)) AS tourism,
               ('highway_' || (CASE WHEN highway IN ('services', 'rest_area') THEN highway ELSE NULL END)) AS highway,
@@ -166,7 +166,7 @@ Layer:
               OR highway IN ('services', 'rest_area')
               OR railway = 'station')
               AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
-            ORDER BY CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END, way_area DESC
+            ORDER BY COALESCE(layer,0), way_area DESC
           ) AS landcover
         ) AS features
     properties:
@@ -193,7 +193,7 @@ Layer:
       <<: *osm2pgsql
       table: |-
         (SELECT
-            way, waterway, intermittent,
+            way, waterway, tags->'intermittent' as intermittent,
             CASE WHEN tunnel IN ('yes', 'culvert') THEN 'yes' ELSE 'no' END AS int_tunnel
           FROM planet_osm_line
           WHERE waterway IN ('stream', 'drain', 'ditch')
@@ -210,7 +210,7 @@ Layer:
         (SELECT
             way,
             waterway,
-            intermittent
+            tags->'intermittent' as intermittent
           FROM planet_osm_line
           WHERE waterway = 'river'
         ) AS water_lines_low_zoom
@@ -247,7 +247,7 @@ Layer:
               OR "natural" IN ('water', 'glacier'))
             AND building IS NULL
             AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
-          ORDER BY z_order, way_area DESC
+          ORDER BY COALESCE(layer,0), way_area DESC
         ) AS water_areas
     properties:
       minzoom: 4
@@ -263,10 +263,10 @@ Layer:
             COALESCE(CASE WHEN landuse = 'forest' THEN 'wood' ELSE NULL END, "natural") AS "natural",
             CASE WHEN "natural" IN ('marsh', 'mud') 
                 THEN "natural" 
-                ELSE CASE WHEN ("natural" = 'wetland' AND wetland IS NULL) 
+                ELSE CASE WHEN ("natural" = 'wetland' AND NOT tags ? 'wetland') 
                   THEN 'wetland' 
                   ELSE CASE WHEN ("natural" = 'wetland')
-                    THEN wetland
+                    THEN tags->'wetland'
                     ELSE NULL
                     END 
                 END
@@ -275,7 +275,7 @@ Layer:
           WHERE ("natural" IN ('marsh', 'mud', 'wetland', 'wood', 'beach', 'shoal', 'reef', 'scrub') OR landuse = 'forest')
             AND building IS NULL
             AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
-          ORDER BY z_order, way_area DESC
+          ORDER BY COALESCE(layer,0), way_area DESC
         ) AS landcover_area_symbols
     properties:
       minzoom: 10
@@ -297,13 +297,13 @@ Layer:
       <<: *osm2pgsql
       table: |-
         (SELECT
-            way, waterway, name, intermittent,
+            way, waterway, name, tags->'intermittent' as intermittent,
             CASE WHEN tunnel IN ('yes', 'culvert') THEN 'yes' ELSE 'no' END AS int_tunnel,
             'no' AS bridge
           FROM planet_osm_line
           WHERE waterway IN ('river', 'canal', 'derelict_canal', 'stream', 'drain', 'ditch', 'wadi')
             AND (bridge IS NULL OR bridge NOT IN ('yes', 'aqueduct'))
-          ORDER BY z_order
+          ORDER BY COALESCE(layer,0)
         ) AS water_lines
     properties:
       minzoom: 12
@@ -429,7 +429,7 @@ Layer:
             AND (amenity IS NULL OR amenity != 'place_of_worship')
             AND building != 'train_station'
             AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
-          ORDER BY z_order, way_area DESC
+          ORDER BY COALESCE(layer,0), way_area DESC
         ) AS buildings
     properties:
       minzoom: 13
@@ -450,7 +450,7 @@ Layer:
             AND building != 'no'
             AND (aeroway = 'terminal' OR amenity = 'place_of_worship' OR building = 'train_station')
             AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
-          ORDER BY z_order, way_area DESC)
+          ORDER BY COALESCE(layer,0), way_area DESC)
         AS buildings_major
     properties:
       minzoom: 13
@@ -506,7 +506,7 @@ Layer:
                   WHEN substr(highway, length(highway)-3, 4) = 'link' THEN 'yes'
                   ELSE 'no'
                 END AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel = 'yes' OR tunnel = 'building_passage' OR covered = 'yes')
                 AND highway IS NOT NULL -- end of road select
@@ -532,7 +532,7 @@ Layer:
                 construction,
                 CASE WHEN service IN ('parking_aisle', 'drive-through', 'driveway') THEN 'INT-minor'::text ELSE 'INT-normal'::text END AS service,
                 'no' AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel = 'yes' OR tunnel = 'building_passage' OR covered = 'yes')
                 AND (railway IS NOT NULL OR aeroway IS NOT NULL) -- end of rail/aero select
@@ -723,7 +723,7 @@ Layer:
           FROM planet_osm_polygon
           WHERE highway IN ('residential', 'unclassified', 'pedestrian', 'service', 'footway', 'track', 'path', 'platform')
             OR railway IN ('platform')
-          ORDER BY z_order, way_area DESC
+          ORDER BY COALESCE(layer,0), way_area DESC
         ) AS highway_area_casing
     properties:
       minzoom: 14
@@ -775,7 +775,7 @@ Layer:
                   WHEN substr(highway, length(highway)-3, 4) = 'link' THEN 'yes'
                   ELSE 'no'
                 END AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel IS NULL OR NOT tunnel IN ('yes', 'building_passage'))
                 AND (covered IS NULL OR NOT covered = 'yes')
@@ -803,7 +803,7 @@ Layer:
                 construction,
                 CASE WHEN service IN ('parking_aisle', 'drive-through', 'driveway') THEN 'INT-minor'::text ELSE 'INT-normal'::text END AS service,
                 'no' AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel IS NULL OR NOT tunnel IN ('yes', 'building_passage'))
                 AND (covered IS NULL OR NOT covered = 'yes')
@@ -883,7 +883,7 @@ Layer:
           WHERE highway IN ('residential', 'unclassified', 'pedestrian', 'service', 'footway', 'living_street', 'track', 'path', 'platform', 'services')
             OR railway IN ('platform')
             OR aeroway IN ('runway', 'taxiway', 'helipad')
-          ORDER BY z_order, way_area desc
+          ORDER BY COALESCE(layer,0), way_area desc
         ) AS highway_area_fill
     properties:
       minzoom: 14
@@ -940,7 +940,7 @@ Layer:
                   WHEN substr(highway, length(highway)-3, 4) = 'link' THEN 'yes'
                   ELSE 'no'
                 END AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel IS NULL OR NOT tunnel IN ('yes', 'building_passage'))
                 AND (covered IS NULL OR NOT covered = 'yes')
@@ -968,7 +968,7 @@ Layer:
                 construction,
                 CASE WHEN service IN ('parking_aisle', 'drive-through', 'driveway') THEN 'INT-minor'::text ELSE 'INT-normal'::text END AS service,
                 'no' AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE (tunnel IS NULL OR NOT tunnel IN ('yes', 'building_passage'))
                 AND (covered IS NULL OR NOT covered = 'yes')
@@ -1099,7 +1099,7 @@ Layer:
           WHERE highway IS NOT NULL
             OR (railway IS NOT NULL AND railway != 'preserved'
               AND (service IS NULL OR service NOT IN ('spur', 'siding', 'yard')))
-          ORDER BY z_order
+          ORDER BY COALESCE(layer,0)
         ) AS roads_low_zoom
     properties:
       minzoom: 5
@@ -1116,13 +1116,13 @@ Layer:
             way,
             waterway,
             name,
-            intermittent,
+            tags->'intermittent' as intermittent,
             CASE WHEN tunnel IN ('yes', 'culvert') THEN 'yes' ELSE 'no' END AS int_tunnel,
             'yes' AS bridge
           FROM planet_osm_line
           WHERE waterway IN ('river', 'canal', 'derelict_canal', 'stream', 'drain', 'ditch', 'wadi')
             AND bridge IN ('yes', 'aqueduct')
-          ORDER BY z_order
+          ORDER BY COALESCE(layer,0)
         ) AS waterway_bridges
     properties:
       minzoom: 12
@@ -1174,7 +1174,7 @@ Layer:
                   WHEN substr(highway, length(highway)-3, 4) = 'link' THEN 'yes'
                   ELSE 'no'
                 END AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE bridge IN ('yes', 'boardwalk', 'cantilever', 'covered', 'low_water_crossing', 'movable', 'trestle', 'viaduct')
                 AND highway IS NOT NULL -- end of road select
@@ -1200,7 +1200,7 @@ Layer:
                 construction,
                 CASE WHEN service IN ('parking_aisle', 'drive-through', 'driveway') THEN 'INT-minor'::text ELSE 'INT-normal'::text END AS service,
                 'no' AS link,
-                CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END AS layernotnull
+                COALESCE(layer,0) AS layernotnull
               FROM planet_osm_line
               WHERE bridge IN ('yes', 'boardwalk', 'cantilever', 'covered', 'low_water_crossing', 'movable', 'trestle', 'viaduct')
                 AND (railway IS NOT NULL OR aeroway IS NOT NULL) -- end of rail/aero select
@@ -1446,13 +1446,13 @@ Layer:
             way,
             name,
             CASE
-              WHEN (population ~ '^[0-9]{1,8}$') THEN population::INTEGER ELSE 0
+              WHEN (tags->'population' ~ '^[0-9]{1,8}$') THEN (tags->'population')::INTEGER ELSE 0
             END as population,
             round(ascii(md5(osm_id::text)) / 55) AS dir -- base direction factor on geometry to be consistent across metatiles
           FROM planet_osm_point
           WHERE place IN ('city', 'town', 'village', 'hamlet')
             AND name IS NOT NULL
-            AND capital = 'yes'
+            AND tags @> 'capital=>yes'
           ORDER BY population DESC
         ) AS capital_names
     properties:
@@ -1504,21 +1504,21 @@ Layer:
                 name,
                 (
                   (CASE
-                    WHEN (population ~ '^[0-9]{1,8}$') THEN population::INTEGER
+                    WHEN (tags->'population' ~ '^[0-9]{1,8}$') THEN (tags->'population')::INTEGER
                     WHEN (place = 'city') THEN 100000
                     WHEN (place = 'town') THEN 1000
                     ELSE 1
                   END)
                   *
                   (CASE
-                    WHEN (capital = '4') THEN 2
+                    WHEN (tags @> 'capital=>4') THEN 2
                     ELSE 1
                   END)
                 ) AS score
               FROM planet_osm_point
               WHERE place IN ('city', 'town')
                 AND name IS NOT NULL
-                AND (capital IS NULL OR capital != 'yes')
+                AND NOT (tags @> 'capital=>yes')
             ) as p
           ORDER BY score DESC, length(name) DESC, name
         ) AS placenames_medium
@@ -1539,7 +1539,7 @@ Layer:
           FROM planet_osm_point
           WHERE place IN ('village', 'hamlet')
              AND name IS NOT NULL
-             AND (capital IS NULL OR capital != 'yes')
+             AND NOT tags @> 'capital=>yes'
              OR place IN ('suburb', 'neighbourhood', 'locality', 'isolated_dwelling', 'farm')
              AND name IS NOT NULL
           ORDER BY CASE
@@ -1634,9 +1634,9 @@ Layer:
             ) AS feature,
             access,
             religion,
-            denomination,
-            "generator:source",
-            power_source,
+            tags->'denomination' as denomination,
+            tags->'generator:source' as "generator:source",
+            tags->'power_source' as power_source,
             CASE WHEN shop IN ('supermarket', 'bag', 'bakery', 'beauty', 'books', 'butcher', 'clothes', 'computer', 
                                'confectionery', 'fashion', 'convenience', 'department_store', 'doityourself', 'hardware', 'fishmonger', 'florist', 
                                'garden_centre', 'hairdresser', 'hifi', 'ice_cream', 'car', 'car_repair', 'bicycle', 'mall', 'pet', 
@@ -1666,7 +1666,7 @@ Layer:
             OR "natural" IN ('spring')
             OR historic IN ('memorial', 'monument', 'archaeological_site')
             OR highway IN ('bus_stop', 'elevator', 'traffic_signals')
-            OR (power = 'generator' AND ("generator:source" = 'wind' OR power_source = 'wind'))
+            OR (power = 'generator' AND (tags @> '"generator:source"=>wind' OR tags @> 'power_source=>wind'))
           ORDER BY way_area desc
         ) AS amenity_points_poly
     properties:
@@ -1709,15 +1709,15 @@ Layer:
             CASE
               WHEN "natural" IN ('peak', 'volcano', 'saddle') THEN
                 CASE
-                  WHEN ele ~ '^-?\d{1,4}(\.\d+)?$' THEN ele::NUMERIC
+                  WHEN tags->'ele' ~ '^-?\d{1,4}(\.\d+)?$' THEN (tags->'ele')::NUMERIC
                   ELSE NULL
                 END
               ELSE NULL
             END AS score,
             religion,
-            denomination,
-            "generator:source",
-            power_source,
+            tags->'denomination' as denomination,
+            tags->'generator:source' as "generator:source",
+            tags->'power_source' as power_source,
             CASE WHEN shop IN ('supermarket', 'bag', 'bakery', 'beauty', 'books', 'butcher', 'clothes', 'computer', 
                                'confectionery', 'fashion', 'convenience', 'department_store', 'doityourself', 'hardware', 'fishmonger', 'florist', 
                                'garden_centre', 'hairdresser', 'hifi', 'ice_cream', 'car', 'car_repair', 'bicycle', 'mall', 'pet', 
@@ -1748,7 +1748,7 @@ Layer:
             OR "natural" IN ('peak', 'volcano', 'saddle', 'spring', 'cave_entrance')
             OR historic IN ('memorial', 'monument', 'archaeological_site', 'wayside_cross')
             OR highway IN ('bus_stop', 'elevator', 'traffic_signals', 'ford')
-            OR (power = 'generator' AND ("generator:source" = 'wind' OR power_source = 'wind'))
+            OR (power = 'generator' AND (tags @> '"generator:source"=>wind' OR tags @> 'power_source=>wind'))
           ORDER BY score DESC NULLS LAST
           ) AS amenity_points
     properties:
@@ -1993,7 +1993,7 @@ Layer:
               OR junction IN ('roundabout'))
           ORDER BY
             prio DESC, -- put important roads first
-            CASE WHEN layer~E'^-?\\d+$' AND length(layer)<10 THEN layer::integer ELSE 0 END DESC, -- put top layered roads first
+            COALESCE(layer, 0), -- put top layered roads first
             length(name) DESC, -- Try to fit big labels in first
             name DESC, -- Force a consistent ordering between differently named streets
             l.osm_id DESC -- Force an ordering for streets of the same name, e.g. dualized roads
@@ -2105,7 +2105,7 @@ Layer:
             ) AS feature,
             access,
             name,
-            operator,
+            tags->'operator' as operator,
             ref,
             way_area,
             CASE WHEN building = 'no' OR building IS NULL THEN 'no' ELSE 'yes' END AS is_building
@@ -2147,7 +2147,7 @@ Layer:
             COALESCE('man_made_' || man_made, 'waterway_' || waterway, 'natural_' || "natural") AS feature,
             access,
             name,
-            operator,
+            tags->'operator' as operator,
             ref,
             NULL AS way_area,
             CASE WHEN building = 'no' OR building IS NULL THEN 'no' ELSE 'yes' END AS is_building
@@ -2238,13 +2238,13 @@ Layer:
                 CASE
                   WHEN "natural" IN ('peak', 'volcano', 'saddle') OR tourism = 'alpine_hut' OR amenity = 'shelter' THEN
                     CASE
-                      WHEN ele ~ '^-?\d{1,4}(\.\d+)?$' THEN ele::NUMERIC
+                      WHEN tags->'ele' ~ '^-?\d{1,4}(\.\d+)?$' THEN (tags->'ele')::NUMERIC
                       ELSE NULL
                     END
                   ELSE NULL
                 END AS elevation,
                 "natural",
-                operator,
+                tags->'operator' as operator,
                 ref,
                 NULL AS way_area,
                 CASE WHEN building = 'no' OR building IS NULL THEN 'no' ELSE 'yes' END AS is_building
@@ -2269,7 +2269,7 @@ Layer:
                   OR boundary IN ('national_park')
                   OR waterway IN ('dam', 'weir'))
                 AND (name IS NOT NULL
-                     OR (ele IS NOT NULL AND ("natural" IN ('peak', 'volcano', 'saddle') OR tourism = 'alpine_hut' OR amenity = 'shelter'))
+                     OR (tags?'ele' AND ("natural" IN ('peak', 'volcano', 'saddle') OR tourism = 'alpine_hut' OR amenity = 'shelter'))
                      OR (ref IS NOT NULL AND aeroway IN ('gate'))
                     )
               ) AS p
@@ -2349,13 +2349,13 @@ Layer:
             waterway,
             lock,
             name,
-            intermittent,
+            tags->'intermittent' as intermittent,
             CASE WHEN tunnel IN ('yes', 'culvert') THEN 'yes' ELSE 'no' END AS int_tunnel
           FROM planet_osm_line
           WHERE waterway IN ('river', 'canal', 'derelict_canal', 'stream', 'drain', 'ditch', 'wadi')
             AND (tunnel IS NULL or tunnel != 'culvert')
             AND name IS NOT NULL
-          ORDER BY z_order
+          ORDER BY COALESCE(layer,0)
         ) AS water_lines_text
     properties:
       minzoom: 13
diff --git a/scripts/lua/README.md b/scripts/lua/README.md
new file mode 100644
index 0000000..b5c3a4e
--- /dev/null
+++ b/scripts/lua/README.md
@@ -0,0 +1,5 @@
+# Lua helper scripts #
+
+These scripts are for developing, testing, and profiling the [Lua tag transform](../../openstreetmap-carto.lua). There is a symlink to the transform in this directory so it can be `require`d by other files.
+
+They are not necessary for map rendering or most development.
diff --git a/scripts/lua/openstreetmap-carto.lua b/scripts/lua/openstreetmap-carto.lua
new file mode 120000
index 0000000..ba19fbe
--- /dev/null
+++ b/scripts/lua/openstreetmap-carto.lua
@@ -0,0 +1 @@
+../../openstreetmap-carto.lua
\ No newline at end of file
diff --git a/scripts/lua/test.lua b/scripts/lua/test.lua
new file mode 100644
index 0000000..ed4d5bb
--- /dev/null
+++ b/scripts/lua/test.lua
@@ -0,0 +1,165 @@
+--[[
+This file is part of OpenStreetMap Carto and used for validating the Lua tag transforms.
+
+Run it with lua test.lua
+]]
+
+require ("openstreetmap-carto")
+
+--- compare two tables.
+-- @param t1 A table
+-- @param t2 A table
+-- @return true or false
+function equaltables (t1,t2)
+    for k, v in pairs(t1) do
+        if t2[k] ~= v then return false end
+    end
+    for k, v in pairs(t2) do
+        if t1[k] ~= v then return false end
+    end
+    return true
+end
+
+print("TESTING: z_order")
+
+assert(z_order({}) == nil, "test failed: no tags")
+assert(z_order({foo="bar"}) == nil, "test failed: other tags")
+assert(z_order({highway="motorway"}) == 380 , "test failed: motorway")
+assert(z_order({highway="motorway", railway="rail"}) == 440 , "test failed: motorway + rail")
+
+print("TESTING: roads")
+assert(roads({}) == 0, "test failed: no tags")
+assert(roads({foo="bar"}) == 0, "test failed: other tags")
+assert(roads({highway="motorway"}) == 1, "test failed: motorway")
+assert(roads({railway="rail"}) == 1, "test failed: rail")
+assert(roads({highway="residential", railway="rail"}) == 1, "test failed: rail+residential")
+assert(roads({railway="turntable"}) == 0, "test failed: rail=turntable")
+assert(roads({railway="rail", service="spur"}) == 0, "test failed: rail SSY")
+assert(roads({railway="rail", service="main"}) == 1, "test failed: rail non-SSY")
+assert(roads({boundary="administrative"}) == 1, "test failed: boundary administrative")
+
+print("TESTING: isarea")
+assert(isarea({}) == 0, "test failed: no tags")
+assert(isarea({foo = "bar"}) == 0, "test failed: random tag")
+assert(isarea({area = "yes"}) == 1, "test failed: explicit area")
+assert(isarea({area = "no"}) == 0, "test failed: explicit not area")
+assert(isarea({area = "no", landuse = "forest"}) == 0, "test failed: explicit not area with polygon tag")
+assert(isarea({leisure = "track"}) == 0, "test failed: leisure=track")
+assert(isarea({area = "yes", leisure = "track"}) == 1, "test failed: leisure=track with area tag")
+assert(isarea({waterway = "river"}) == 0, "test failed: river")
+assert(isarea({waterway = "riverbank"}) == 1, "test failed: river")
+assert(isarea({highway = "services"}) == 1, "test failed: river")
+
+print("TESTING: filter_tags_generic")
+assert(({filter_tags_generic({})})[1] == 1, "Untagged filter")
+assert(equaltables(({filter_tags_generic({})})[2], {}), "Untagged tags")
+assert(({filter_tags_generic({note="foo"})})[1] == 1, "deleted filter")
+assert(equaltables(({filter_tags_generic({note="foo"})})[2], {}), "deleted tags")
+assert(({filter_tags_generic({foo="bar"})})[1] == 0, "single tag filter")
+assert(equaltables(({filter_tags_generic({foo="bar"})})[2], {foo="bar"}), "single tag tags")
+assert(({filter_tags_generic({foo="bar", note="baz"})})[1] == 0, "tag + deleted tag filter")
+assert(equaltables(({filter_tags_generic({foo="bar", note="baz"})})[2], {foo="bar"}), "tag + deleted tags")
+assert(({filter_tags_generic({["note:xx"]="foo"})})[1] == 1, "wildcard deleted filter")
+assert(equaltables(({filter_tags_generic({["note:xx"]="foo"})})[2], {}), "wildcard deleted tags")
+assert(({filter_tags_generic({["note:xx"]="foo", foo="bar"})})[1] == 0, "wildcard deleted + tag filter")
+assert(equaltables(({filter_tags_generic({["note:xx"]="foo", foo="bar"})})[2], {foo="bar"}), "wildcard deleted + tag tags")
+
+assert(({filter_tags_generic({["foo:note:xx"]="foo"})})[1] == 0, "prefix later in tag filter")
+assert(equaltables(({filter_tags_generic({["foo:note:xx"]="foo"})})[2], {["foo:note:xx"]="foo"}), "prefix later in tag tags")
+
+print("TESTING: filter_tags_relation_member")
+
+--- Tests filter_tags_relation_member against expected values
+-- @param keyvalues OSM tags, after processing by relation transform
+-- @param keyvaluemembers OSM tags of relation members, after processing by way transform
+-- @param filter expected filter result
+-- @param cols expected cols result
+-- @param member_superseded expected member_superseded result
+-- @param boundary expected boundary result
+-- @param polygon expected polygon result
+-- @param roads expected roads result
+local function check_rel_member(keyvalues, keyvaluemembers, filter, cols, member_superseded, boundary, polygon, roads)
+
+    local i = 0
+    for _ in pairs(keyvaluemembers) do
+        i = i + 1
+    end
+
+    local actual_filter, actual_cols, actual_member_superseded, actual_boundary, actual_polygon, actual_roads
+            = filter_tags_relation_member(keyvalues, keyvaluemembers, nil, i)
+
+    if actual_filter ~= filter then
+        print("filter mismatch")
+        return false
+    end
+    if not equaltables(actual_cols, cols) then
+        print("cols mismatch")
+        return false
+    end
+    if not equaltables(actual_member_superseded, member_superseded) then
+        print("member_superseded mismatch, actual table was")
+        for i, v in ipairs(actual_member_superseded) do
+            print(i, v)
+        end
+        return false
+    end
+    if actual_boundary ~= boundary then
+        print("boundary mismatch")
+        return false
+    end
+    if actual_polygon ~= polygon then
+        print("polygon mismatch")
+        return false
+    end
+    if actual_roads ~= roads then
+        print("roads mismatch")
+        return false
+    end
+    return true
+end
+
+assert(check_rel_member({}, {}, 1, {}, {}, 0, 0, 0), "test failed: untagged memberless relation")
+assert(check_rel_member({}, {{}}, 1, {}, {0}, 0, 0, 0), "test failed: untagged relation")
+
+assert(check_rel_member({type="multipolygon"}, {{}}, 1, {}, {0}, 0, 0, 0),
+       "test failed: untagged MP")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{}}, 0, {foo="bar"}, {0}, 0, 1, 0),
+       "test failed: MP with tag")
+
+-- New-style MPs
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{},{}}, 0, {foo="bar"}, {0,0}, 0, 1, 0),
+       "test failed: MP with tag, two ways")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{baz="qax"}}, 0, {foo="bar"}, {0}, 0, 1, 0),
+       "test failed: MP with tag, way with different tag")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{baz="qax"}, {}}, 0, {foo="bar"}, {0,0}, 0, 1, 0),
+       "test failed: MP with tag, way with different tag + untagged way")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{foo="bar"}}, 0, {foo="bar"}, {0}, 0, 1, 0),
+       "test failed: MP with tag, way with same tag")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{foo="bar"},{}}, 0, {foo="bar"}, {0,0}, 0, 1, 0),
+       "test failed: MP with tag, way with same tag + untagged way")
+assert(check_rel_member({type="multipolygon", foo="bar"}, {{foo="bar"}, {baz="qax"}}, 0, {foo="bar"}, {0,0}, 0, 1, 0),
+       "test failed: MP with tag, way with same tag")
+
+-- Old-style MPs
+assert(check_rel_member({type="multipolygon"}, {{foo="bar"}}, 1, {}, {0}, 0, 0, 0),
+       "test failed: MP w/o tag, way with tag")
+assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {}}, 1, {}, {0,0}, 0, 0, 0),
+       "test failed: MP w/o tag, way with tag + untagged way")
+assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {baz="qax"}}, 1, {}, {0,0}, 0, 0, 0),
+       "test failed: MP w/o tag, way with tag + way with other tag")
+
+-- Boundary relations
+assert(check_rel_member({type="boundary"}, {{}}, 1, {}, {0}, 0, 0, 0),
+       "test failed: untagged boundary")
+assert(check_rel_member({type="boundary", boundary="administrative"}, {{}}, 0, {boundary="administrative"}, {0}, 1, 0, 1),
+       "test failed: untagged boundary")
+assert(check_rel_member({type="boundary", boundary="administrative"}, {{}}, 0, {boundary="administrative"}, {0}, 1, 0, 1),
+       "test failed: untagged boundary")
+assert(check_rel_member({type="boundary", boundary="administrative"}, {{foo="bar"}}, 0, {boundary="administrative"}, {0}, 1, 0, 1),
+       "test failed: untagged boundary, tagged way")
+
+-- Route relations
+assert(check_rel_member({type="route"}, {{}}, 1, {}, {0}, 0, 0, 0),
+       "test failed: untagged route")
+assert(check_rel_member({type="route", route="road"}, {{}}, 0, {route="road"}, {0}, 1, 0, 0),
+       "test failed: tagged route")
diff --git a/water.mss b/water.mss
index 456b698..3a766df 100644
--- a/water.mss
+++ b/water.mss
@@ -103,10 +103,6 @@
       background/line-cap: round;
       background/line-join: round;
     }
-    water/line-color: @water-color;
-    water/line-width: 2;
-    water/line-cap: round;
-    water/line-join: round;
 
     [bridge = 'yes'] {
       [zoom >= 14] {
@@ -119,6 +115,11 @@
       }
     }
 
+    water/line-color: @water-color;
+    water/line-width: 2;
+    water/line-cap: round;
+    water/line-join: round;
+
     [intermittent = 'yes'],
     [waterway = 'wadi'] {
       [bridge = 'yes'][zoom >= 14] {
@@ -192,9 +193,6 @@
         water/line-cap: butt;
         water/line-join: round;
         water/line-clip: false;
-        background/line-cap: butt;
-        background/line-join: round;
-        background/line-clip: false;
       }
 
       [waterway = 'stream'][zoom >= 15] {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/openstreetmap-carto.git



More information about the Pkg-grass-devel mailing list