Skip to content

Instantly share code, notes, and snippets.

@dch0ph
Last active April 3, 2024 15:02
Show Gist options
  • Save dch0ph/5d152262ac69798d0f321885af86a5e0 to your computer and use it in GitHub Desktop.
Save dch0ph/5d152262ac69798d0f321885af86a5e0 to your computer and use it in GitHub Desktop.
Proof of principle for extending rendering of access tags
/* 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;
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,
[...]
// 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;
[...]
}
}
}
@dch0ph
Copy link
Author

dch0ph commented Apr 1, 2024

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.

image

image

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.

image

image

Honouring foot

North-south footway tagged with highway=footway, foot=private
image
Screenshot 2024-04-01 120915

More tagging normalisation

Cycleway tagged as highway=path, foot=yes, bicycle=yes

image

image

Carto currently only accepts bicycle=designated.

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