-
-
Save dch0ph/5d152262ac69798d0f321885af86a5e0 to your computer and use it in GitHub Desktop.
Proof of principle for extending rendering of access tags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Adapted from https://github.com/imagico/osm-carto-alternative-colors/tree/591c861112b4e5d44badd108f4cd1409146bca0b/sql/roads.sql */ | |
/* Numerical scale for 'severity' of access restriction, including NULL if null input */ | |
CREATE OR REPLACE FUNCTION carto_restriction_severity(highway_type text, accesstag text) | |
RETURNS integer | |
LANGUAGE SQL | |
IMMUTABLE PARALLEL SAFE | |
AS $$ | |
SELECT | |
CASE | |
WHEN accesstag IN ('yes', 'designated', 'permissive', 'customers') THEN 0 | |
WHEN accesstag IN ('destination', 'delivery') THEN | |
CASE WHEN highway_type = 'type_footway' THEN 0 ELSE 1 END | |
WHEN accesstag IN ('no', 'private') THEN 2 | |
ELSE NULL::INTEGER | |
END | |
END | |
$$; | |
/* Classify highways into categories. Default is NULL in which case simple access tag will be used */ | |
CREATE OR REPLACE FUNCTION carto_access_type(highway text) | |
RETURNS text | |
LANGUAGE SQL | |
IMMUTABLE PARALLEL SAFE | |
AS $$ | |
SELECT | |
CASE | |
WHEN highway IN ('motorway', 'motorway_link', 'trunk', 'trunk_link', 'primary', 'primary_link', 'secondary', | |
'secondary_link', 'tertiary', 'tertiary_link', 'residential', 'unclassified', 'service', | |
'road') THEN 'type_motorvehicle' | |
WHEN highway = 'pedestrian' THEN 'type_pedestrian' | |
WHEN highway IN ('footway', 'steps') THEN 'type_footway' | |
ELSE NULL | |
END | |
END | |
$$; | |
/* Return int_access value which will be used to determine access marking. */ | |
/* Only a restricted number of types can be returned, with NULL corresponding to no access restriction */ | |
CREATE OR REPLACE FUNCTION carto_highway_int_access_internal (highway text, "access" text, foot text, tags hstore, OUT int_access text) | |
language plpgsql | |
immutable | |
AS $$ | |
DECLARE | |
highway_type text DEFAULT NULL; | |
specific_severity INTEGER DEFAULT NULL; | |
overall_severity INTEGER DEFAULT NULL; | |
BEGIN | |
SELECT INTO highway_type carto_access_type(highway); | |
IF highway_type = 'type_motorvehicle' THEN | |
SELECT INTO specific_severity MAX(severity) FROM (VALUES (carto_restriction_severity(highway_type, tags->'motor_vehicle')), | |
(carto_restriction_severity(highway_type, tags->'motorcar')), (carto_restriction_severity(highway_type, tags->'vehicle'))) AS tmp(severity); | |
ELSIF highway_type = 'type_footway' THEN | |
SELECT INTO specific_severity carto_restriction_severity(highway_type, foot); | |
ELSIF highway_type = 'type_pedestrian' THEN | |
SELECT INTO specific_severity 2; | |
END IF; | |
SELECT INTO overall_severity | |
CASE WHEN specific_severity IS NOT NULL THEN specific_severity ELSE carto_restriction_severity(highway_type, "access") END; | |
SELECT INTO int_access | |
CASE overall_severity | |
WHEN 0 THEN NULL | |
WHEN NULL THEN NULL | |
WHEN 1 THEN 'destination' | |
WHEN 2 THEN 'no' | |
END; | |
END; | |
$$; | |
CREATE OR REPLACE FUNCTION carto_highway_access_modifier (highway text, tags hstore, OUT access_modifier text) | |
language plpgsql | |
immutable | |
AS $$ | |
DECLARE | |
highway_type text DEFAULT NULL; | |
BEGIN | |
SELECT INTO highway_type carto_access_type(highway); | |
SELECT INTO access_modifier | |
CASE WHEN highway_type = 'type_motorvehicle' THEN | |
CASE | |
WHEN (tags->'psv' IN ('yes', 'designated')) OR (tags->'bus' IN ('yes', 'designated')) THEN 'psv' | |
WHEN tags->'hgv' IN ('yes', 'designated') THEN 'hgv' | |
ELSE NULL | |
END | |
ELSE NULL | |
END; | |
END; | |
$$; | |
ALTER TABLE planet_osm_line DROP COLUMN IF EXISTS int_access; | |
ALTER TABLE planet_osm_line | |
ADD int_access text GENERATED ALWAYS AS (CASE WHEN highway IS NOT NULL THEN carto_highway_int_access_internal(highway, "access", foot, tags) ELSE NULL END) STORED; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
table: &tunnels_sql |- | |
(SELECT | |
way, | |
(CASE WHEN feature IN ('highway_motorway_link', 'highway_trunk_link', 'highway_primary_link', 'highway_secondary_link', 'highway_tertiary_link') THEN substr(feature, 0, length(feature)-4) ELSE feature END) AS feature, | |
[...] | |
int_access AS access, | |
access_modifier, | |
[...] | |
FROM ( -- subselect that contains both roads and rail | |
SELECT | |
way, | |
'highway_' || highway AS feature, --only motorway to tertiary links are accepted later on | |
[...] | |
int_access, | |
CASE WHEN int_access IS NULL THEN NULL::text ELSE carto_highway_access_modifier (highway, tags) END AS access_modifier, | |
[...] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Taken from osm-carto-alternative-colors | |
@access-marking-psv: lighten(@transportation-icon, 28%); | |
@access-marking-hgv: #888; | |
[...] | |
[access = 'no'] { | |
[feature = 'highway_service'][service = 'INT-normal'] { | |
[zoom >= 15] { | |
access/line-color: @access-marking; | |
[access_modifier = 'psv'] { access/line-color: @access-marking-psv; } | |
[access_modifier = 'hgv'] { access/line-color: @access-marking-hgv; } | |
access/line-join: round; | |
access/line-cap: round; | |
[...] | |
} | |
} | |
} |
Examples
Above is a current Carto rendering. Below new access marking in a Carto-derived personal style (ignore the non-access related differences):
PSV access
Bus only road on bridge. access=no, bicycle=yes, bus=yes, foot=yes
.
The presence of bus=yes
means the access=no
restriction is rendered in pale blue.
Honouring motor_vehicle
Residential highway tagged with motor_vehicle=destination
.
Honouring foot
North-south footway tagged with highway=footway, foot=private
More tagging normalisation
Cycleway tagged as highway=path, foot=yes, bicycle=yes
Carto currently only accepts bicycle=designated.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Notes
int_access
, inplanet_osm_line
, which crunches various access tags on highways to an overall result with a restricted set of values.highway_type
, depending on which access tags are being considered. Currently three types considered: obvious vehicle road ways (considering vehicle access tags), foot ways (consideringfoot
) andhighway=pedestrian
(with implicit restricted vehicle access).access
tag is considered if the highway does not fit into these categories, i.e. defaults to existing behaviour.severity
ranking: 0 represents "no access marking", 2 represents "marking for no access", 1 represents an "intermediate" (typicallyaccess=destination
). Footways only support "no" vs. "yes".motorcar
,motor_vehicle
andvehicle
are considered for road types, since this covers most cases where a road might be not be open to vehicles. Rather than prioritising specific tags, "approximately equivalent" tags are combined by finding the most severe restriction.destination
orno
scale, stored asint_access
, which is fully compatible with the existing usage ofaccess
in the MSS. Currently,int_access
is simply presented asaccess
to the MSS, but it would be better to modify the MSS toint_access
to clearly delineate the calculated column from the original.access_modifier
, which can be easily generated on the fly - thecarto_highway_access_modifier
function is only called for the relatively small number of ways with access restrictions.psv
andbus
.highway=path
could be dissolved into cycleway, bridleway, footway, depending on access tags in a Lua transform. Effectivelyhighway=path
andbicycle=yes
is a cycleway, and it simplifies the MML/MMS/XML considerably to get rid of it early. For the moment, however, we can stay with the current scheme of acceptinghighway=path
+int_access=yes
as equivalent tohighway=cycleway
.Issues
access.sql
, but is a bit more cumbersome / unfamiliar than re-runningcarto
and changing the XML file. GENERATED columns appeared in version 12 of PostgresSQL.highway=path
in Lua would database reload. In which case, it would make sense to movefoot
andbicycle
columns into hstore, since these have been "processed" intoint_access
. This would neaten the code. But this perhaps best done separately.access_modifier
seems to generate a lot of additional mapnik XML. At least part of this is simply the number of the combinations needed of road type times road width times access colours (3 here). It will also be linked to the number of road layers, i.e. an efficient solution for multiple tintings will probably require rationalisation of the road rendering.