Skip to content

Instantly share code, notes, and snippets.

@dch0ph
Last active April 6, 2024 15:52
Show Gist options
  • Save dch0ph/b7ec9b5458e4510318e5fe886f21e077 to your computer and use it in GitHub Desktop.
Save dch0ph/b7ec9b5458e4510318e5fe886f21e077 to your computer and use it in GitHub Desktop.
Proof of principle for extending rendering of access tags V2
/* Adapted from https://github.com/imagico/osm-carto-alternative-colors/tree/591c861112b4e5d44badd108f4cd1409146bca0b/sql/roads.sql */
/* Simplified 'yes', 'destination', 'no', NULL scale for access restriction
'no' is returned if the rendering for highway category does not support 'destination'.
NULL is functionally equivalent to 'yes', but indicates the absence of a restriction
rather than a positive access = yes */
CREATE OR REPLACE FUNCTION carto_int_access(primary_mode text, accesstag text)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE
WHEN accesstag IN ('yes', 'designated', 'permissive', 'customers') THEN 'yes'
WHEN accesstag IN ('destination', 'delivery', 'permit') THEN
CASE WHEN primary_mode IN ('motorcar', 'pedestrian') THEN 'destination' ELSE 'no' END
WHEN accesstag IN ('no', 'private', 'agricultural', 'forestry', 'agricultural;forestry') THEN 'no'
ELSE NULL
END
END
$$;
/* Try to promote path to cycleway (if bicycle allowed), then bridleway (if horse) */
CREATE OR REPLACE FUNCTION carto_path_primary_mode(bicycle text, horse text)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE
WHEN bicycle IN ('yes', 'designated', 'permissive') THEN 'bicycle'
WHEN horse IN ('yes', 'designated', 'permissive' ) THEN 'horse'
ELSE 'foot'
END
END
$$;
/* Classify highways into access categories which will be treated in the same way
Default is NULL in which case only the access tag will be used (e.g. highway=track)
Note that bicycle, horse arguments are only relevant if considering highway=path */
CREATE OR REPLACE FUNCTION carto_highway_primary_mode(highway text, bicycle text, horse 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', 'living_street', 'service', 'road') THEN 'motorcar'
WHEN highway = 'pedestrian' THEN 'pedestrian'
WHEN highway IN ('footway', 'steps') THEN 'foot'
WHEN highway = 'bridleway' THEN 'horse'
WHEN highway = 'cycleway' THEN 'bicycle'
WHEN highway = 'path' THEN carto_path_primary_mode(bicycle, horse)
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(highway text, "access" text, foot text, bicycle text, horse text, tags hstore)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT
CASE carto_highway_primary_mode(highway, bicycle, horse)
WHEN 'motorcar' THEN
carto_int_access('motorcar', CASE
WHEN tags->'motorcar' IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN tags->'motorcar'
WHEN tags->'motor_vehicle' IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN tags->'motor_vehicle'
WHEN tags->'vehicle' IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN tags->'vehicle'
ELSE "access" END)
WHEN 'pedestrian' THEN carto_int_access('pedestrian', 'no')
WHEN 'foot' THEN carto_int_access('foot', CASE WHEN foot IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN foot ELSE "access" END)
WHEN 'bicycle' THEN carto_int_access('bicycle', CASE WHEN bicycle IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN bicycle ELSE "access" END)
WHEN 'horse' THEN carto_int_access('horse', CASE WHEN horse IN ('yes', 'designated', 'permissive', 'no', 'private', 'destination', 'customers', 'delivery', 'permit') THEN horse ELSE "access" END)
ELSE carto_int_access(NULL, "access")
END
END
$$;
/* Return a label to indicate that an access restriction should be tinted to
indicate that the restriction does not apply to a given category of vehicles.
Only relevant to 'road types' with an access restriction on vehicles (including
pedestrian) */
CREATE OR REPLACE FUNCTION carto_highway_access_modifier(highway text, tags hstore)
RETURNS text
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$
SELECT CASE
WHEN carto_highway_primary_mode(highway, NULL, NULL) IN ('motorcar', 'pedestrian') THEN
CASE
WHEN (tags->'psv' IN ('yes', 'designated')) OR (tags->'bus' IN ('yes', 'designated')) THEN 'psv'
ELSE NULL
END
ELSE NULL
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(highway, "access", foot, bicycle, horse, tags) ELSE NULL END) STORED;
table: &tunnels_sql |-
[...]
int_access,
CASE WHEN highway = 'path' THEN carto_path_primary_mode(bicycle, horse) ELSE NULL::text END AS path_mode,
CASE WHEN int_access IS NULL THEN NULL::text ELSE carto_highway_access_modifier (highway, tags) END AS access_modifier,
[...]
// Taken from osm-carto-alternative-colors
@access-marking-psv: lighten(@transportation-icon, 28%);
[...]
[int_access = 'no'] {
[...]
[feature = 'highway_pedestrian'][access_modifier = 'psv'],
[feature = 'highway_service'][service = 'INT-normal'] {
[zoom >= 15] {
access/line-color: @access-marking;
[access_modifier = 'psv'] { access/line-color: @access-marking-psv; }
access/line-join: round;
access/line-cap: round;
[...]
}
}
}
@dch0ph
Copy link
Author

dch0ph commented Apr 6, 2024

Extended version of earlier gist.

Example renders are unchanged from previous version, just the internals have been simplified and coverage extended to all highway types. highway=track defaults to the current behaviour of using the access tag only.

In the previous version, highway=path was "dissolved" into footway/cycleway/bridleway by Lua transformation on import. Here path is retained, and the added path_mode is used to denote paths that should be treated as cycleways in MSS e.g. [highway = path][path_mode = 'bicycle']. Note that it is no longer necessary to pass foot, bicycle, horse access tags to MSS.

highway=pedestrian is a special case, where there is an implicit motor_vehicle=no, but no explicit access render unless access_modifier is being used to indicate that public service vehicles are allowed.

permit has been added as an access value, treated as the intermediate "access restrictions apply".

The agricultural and forestry tags are not associated with individual access modes, only overall the access tag, and so are not including in the list of valid access tags for individual modes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment