diff --git a/Dockerfile b/Dockerfile index 0179762..31fc540 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:12-slim as generation +FROM debian:trixie-slim as generation ENV DEBIAN_FRONTEND noninteractive @@ -38,7 +38,7 @@ RUN carto project.mml > mapnik.xml # Also see https://github.com/mapbox/carto/issues/238#issuecomment-19673987 RUN sed -i -E "s@@\1$(cat placements.xml)@g" mapnik.xml -FROM debian:12-slim +FROM debian:trixie-slim ENV DEBIAN_FRONTEND noninteractive diff --git a/bounds.Dockerfile b/bounds.Dockerfile index 9cde80e..076783e 100644 --- a/bounds.Dockerfile +++ b/bounds.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:12-slim +FROM debian:trixie-slim LABEL maintainer="Hidde Wieringa " diff --git a/carto/map-it/project.mml b/carto/map-it/project.mml index 8c26d34..a5a56ee 100644 --- a/carto/map-it/project.mml +++ b/carto/map-it/project.mml @@ -60,30 +60,13 @@ Layer: <<: *osm2pgsql table: |- ( - WITH landuse AS ( - SELECT - way, - CASE - WHEN landuse = 'forest' OR "natural" = 'wood' THEN 'forest' - WHEN aeroway IN ('aerodrome') THEN 'aerodrome' - END as type - FROM - planet_osm_polygon - WHERE - way && !bbox! AND - ( - ( - landuse = 'forest' OR - "natural" = 'wood' - ) OR - aeroway IN ('aerodrome') - ) - ) SELECT ST_Union(way) as way, type FROM - landuse + landuse_background + WHERE + way && !bbox! GROUP BY type ORDER BY @@ -126,23 +109,18 @@ Layer: ( SELECT ST_Union(way) as way, - landuse as type + type FROM - planet_osm_polygon + landuse_foreground WHERE - way && !bbox! AND - landuse IN ( - 'residential', - 'industrial', - 'military' - ) + way && !bbox! GROUP BY - landuse + type ORDER BY CASE - WHEN landuse = 'industrial' THEN 1 - WHEN landuse = 'residential' THEN 2 - WHEN landuse = 'military' THEN 3 + WHEN type = 'industrial' THEN 1 + WHEN type = 'residential' THEN 2 + WHEN type = 'military' THEN 3 END ASC ) AS data - id: waterways @@ -155,16 +133,9 @@ Layer: SELECT way FROM - planet_osm_line + waterways WHERE - way && !bbox! AND - waterway IN ( - 'river', - 'stream', - 'canal', - 'drain' - ) AND - (tunnel IS NULL OR tunnel != 'yes') + way && !bbox! ) AS data - id: water geometry: polygon @@ -176,17 +147,9 @@ Layer: SELECT ST_Union(way) as way FROM - planet_osm_polygon + water WHERE - way && !bbox! AND - ( - "natural" = 'water' OR - waterway = 'riverbank' OR - landuse IN ( - 'reservoir', - 'basin' - ) - ) + way && !bbox! UNION ALL @@ -206,91 +169,42 @@ Layer: ( SELECT way, - 'line' AS type + type FROM - planet_osm_line + dams WHERE - way && !bbox! AND - waterway = 'dam' - - UNION ALL - + way && !bbox! + ) AS data +- id: administrative-boundaries + geometry: linestring + <<: *extentsOSM + Datasource: + <<: *osm2pgsql + table: |- + ( SELECT way, - 'polygon' AS type + admin_level FROM - planet_osm_polygon + administrative_boundaries WHERE - way && !bbox! AND - waterway = 'dam' + way && !bbox! + ORDER BY + admin_level DESC ) AS data -- id: boundaries +- id: national-parks geometry: linestring <<: *extentsOSM Datasource: <<: *osm2pgsql - # Administrative boundaries: Levels 0 to 6 are included which has (super-)country - # and state administrative borders table: |- ( - WITH administrative AS ( - SELECT - way, - boundary, - admin_level::int as admin_level - FROM - planet_osm_roads - WHERE - way && !bbox! AND - boundary = 'administrative' AND - admin_level in ( - '0', - '1', - '2', - '3', - '4', - '5', - '6' - ) AND - osm_id < 0 - ), - national_parks AS ( - SELECT - way, - 'national_park'::text as boundary, - null::int as admin_level - FROM - planet_osm_polygon - WHERE - way && !bbox! AND - ( - boundary = 'national_park' OR - (boundary = 'protected_area' AND protect_class IN ('1','1a','1b','2','3','4','5','6')) - ) AND - way_area >= 5e5 - ) SELECT - * + way FROM - ( - SELECT - * - FROM - administrative - UNION ALL - - SELECT - * - FROM - national_parks - ) AS boundaries - ORDER BY - CASE - WHEN boundary = 'administrative' then 1 - WHEN boundary = 'national_park' then 2 - ELSE 100 - END ASC, - admin_level::int DESC + national_parks + WHERE + way && !bbox! ) AS data - id: ferry geometry: linestring @@ -302,10 +216,9 @@ Layer: SELECT way FROM - planet_osm_line + ferries WHERE - way && !bbox! AND - route = 'ferry' + way && !bbox! ) AS data - id: power-line geometry: linestring @@ -317,10 +230,9 @@ Layer: SELECT way FROM - planet_osm_line + power_lines WHERE - way && !bbox! AND - power = 'line' + way && !bbox! ) AS data - id: power-pole geometry: point @@ -332,10 +244,9 @@ Layer: SELECT way FROM - planet_osm_point + power_poles WHERE - way && !bbox! AND - power = 'tower' + way && !bbox! ) AS data - id: tunnels geometry: linestring @@ -345,60 +256,15 @@ Layer: table: |- ( SELECT - * - FROM ( - SELECT - way, - layer, - highway as type - FROM - planet_osm_line - WHERE - way && !bbox! AND - highway IN ( - 'motorway_link', - 'trunk_link', - 'secondary_link', - 'primary_link', - 'motorway', - 'trunk', - 'cycleway', - 'tertiary', - 'secondary', - 'primary' - ) AND - (access IS NULL OR access != 'private') AND - (tunnel = 'yes') - - UNION ALL - - SELECT - way, - layer, - 'railway' as type - FROM - planet_osm_line - WHERE - way && !bbox! AND - railway IN ( - 'rail', - 'narrow_gauge' - ) AND - tunnel = 'yes' AND - ( - service IS NULL OR - service NOT IN ( - 'crossover', - 'spur', - 'yard' - ) - ) - ) AS tunnels + way, + layer, + type + FROM + tunnels + WHERE + way && !bbox! ORDER BY - CASE - WHEN layer IS NOT NULL AND layer ~ '^-?\d+$' THEN layer::int - ELSE -1 - END ASC, + layer ASC, CASE WHEN type = 'railway' THEN 1 WHEN type = 'motorway_link' THEN 10 @@ -424,15 +290,11 @@ Layer: table: |- ( SELECT - way, - aeroway + way FROM - planet_osm_line + aeroways WHERE - way && !bbox! AND - aeroway IN ( - 'runway' - ) + way && !bbox! ) AS data - id: roads geometry: linestring @@ -442,65 +304,21 @@ Layer: table: |- ( SELECT - * - FROM ( - SELECT - way, - CASE - WHEN bicycle = 'designated' THEN 'cycleway' - WHEN highway = 'road' THEN 'unclassified' - WHEN highway = 'living_street' THEN 'residential' - ELSE highway - END as type, - NULL as railway, - CASE - WHEN bicycle IN ('yes', 'designated', 'permissive') THEN 'T' - ELSE 'F' - END as bicycle, - tracktype, - layer - FROM - planet_osm_line - WHERE - way && !bbox! AND - highway IS NOT NULL AND - highway NOT IN ('platform', 'construction', 'proposed', 'steps') AND - (access IS NULL OR access != 'private') AND - (tunnel IS NULL OR tunnel != 'yes') - - UNION ALL - - SELECT - way, - 'railway' as type, - railway, - 'F' as bicycle, - NULL as tracktype, - layer - FROM - planet_osm_line - WHERE - way && !bbox! AND - railway IN ( - 'rail', - 'narrow_gauge', - 'preserved' - ) AND - (tunnel IS NULL OR tunnel != 'yes') AND - ( - service IS NULL OR - service NOT IN ( - 'crossover', - 'spur', - 'yard' - ) - ) - ) AS roads - ORDER BY + way, + type, + railway, CASE - WHEN layer IS NOT NULL AND layer ~ '^-?\d+$' THEN layer::int - ELSE 0 - END ASC, + WHEN bicycle THEN 'T' + ELSE 'F' + END as bicycle, + tracktype, + layer + FROM + roads + WHERE + way && !bbox! + ORDER BY + layer ASC NULLS FIRST, CASE WHEN type = 'railway' THEN 1 WHEN type = 'motorway_link' THEN 10 @@ -528,11 +346,9 @@ Layer: SELECT way FROM - planet_osm_point + cycling_nodes WHERE - way && !bbox! AND - rcn_ref is not null AND - "network:type" = 'node_network' + way && !bbox! ) AS data - id: cycling-routes geometry: linestring @@ -554,11 +370,10 @@ Layer: SELECT way FROM - planet_osm_line + cycling_routes WHERE (NOT EXISTS(SELECT * FROM gpx)) AND - way && !bbox! AND - route = 'bicycle' + way && !bbox! ) AS data - id: transport geometry: point @@ -567,72 +382,13 @@ Layer: <<: *osm2pgsql table: |- ( - WITH points AS ( - SELECT - way, - aeroway, - railway, - station, - amenity - FROM - planet_osm_point - WHERE - way && !bbox! AND - ( - aeroway IS NOT NULL OR - railway IS NOT NULL OR - amenity IS NOT NULL - ) - - UNION ALL - - SELECT - ST_PointOnSurface(way) as way, - aeroway, - railway, - station, - amenity - FROM - planet_osm_polygon - WHERE - way && !bbox! AND - ( - aeroway IS NOT NULL OR - railway IS NOT NULL OR - amenity IS NOT NULL - ) - ) SELECT - * - FROM ( - SELECT - way, - CASE - WHEN aeroway IN ('aerodrome') THEN 'aerodrome' - WHEN railway IN ('station', 'halt') THEN 'train_station' - WHEN amenity IN ('ferry_terminal') THEN 'ferry_terminal' - END as type - FROM - points - WHERE - way && !bbox! AND - aeroway IN ( - 'aerodrome' - ) OR - ( - railway IN ( - 'station', - 'halt' - ) AND - (station IS NULL OR station NOT IN ( - 'subway', - 'light_rail', - 'monorail', - 'funicular' - )) - ) OR - amenity = 'ferry_terminal' - ) transport + way, + type + FROM + transport + WHERE + way && !bbox! ORDER BY CASE WHEN type = 'train_station' THEN 1 @@ -648,24 +404,16 @@ Layer: <<: *osm2pgsql table: |- ( - WITH nodes AS ( - SELECT - way, - rcn_ref as ref - FROM - planet_osm_point - WHERE - way && !bbox! AND - rcn_ref is not null AND - "network:type" = 'node_network' - ), clustered_nodes AS ( + WITH clustered_nodes AS ( SELECT way, ref, - ST_ClusterDBSCAN(way, eps:= 3000, minpoints := 1) + ST_ClusterDBSCAN(way, eps:= 3000, minpoints := 1) OVER (PARTITION by ref) as cluster FROM - nodes + cycling_nodes + WHERE + way && !bbox! ) SELECT @@ -684,91 +432,6 @@ Layer: <<: *osm2pgsql table: |- ( - WITH points AS ( - SELECT - way, - osm_id, - tourism, - amenity, - historic, - man_made, - "natural", - shop, - religion, - power, - "tower:type", - CASE - WHEN height IS NOT NULL AND height ~ '^\d{1,3}(\.\d+)?( m)?$' THEN (SUBSTRING(height, '^(\d{1,3}(\.\d+)?)( m)?$'))::NUMERIC - END as height, - CASE - WHEN ele ~ '^-?\d{1,4}(\.\d+)?$' THEN (ROUND(ele::NUMERIC)::TEXT) || ' m' - END as ele, - location, - "generator:source", - mountain_pass as mountain_pass, - tents, - CASE - WHEN scout = 'yes' THEN 'yes' - ELSE 'no' - END as scout, - surface - FROM - planet_osm_point - WHERE - way && !bbox! AND - ( - amenity IS NOT NULL OR - tourism IS NOT NULL OR - historic IS NOT NULL OR - man_made IS NOT NULL OR - shop IS NOT NULL OR - power IS NOT NULL OR - religion IS NOT NULL OR - "natural" IS NOT NULL OR - mountain_pass IS NOT NULL - ) - - UNION ALL - - SELECT - ST_PointOnSurface(way) AS way, - osm_id, - tourism, - amenity, - historic, - man_made, - "natural", - shop, - religion, - power, - "tower:type", - CASE - WHEN height IS NOT NULL AND height ~ '^\d{1,3}(\.\d+)?( m)?$' THEN (SUBSTRING(height, '^(\d{1,3}(\.\d+)?)( m)?$'))::NUMERIC - END as height, - NULL as ele, - location, - "generator:source", - NULL as mountain_pass, - tents, - CASE - WHEN scout = 'yes' THEN 'yes' - ELSE 'no' - END as scout, - surface - FROM - planet_osm_polygon - WHERE - way && !bbox! AND - ( - amenity IS NOT NULL OR - tourism IS NOT NULL OR - historic IS NOT NULL OR - man_made IS NOT NULL OR - shop IS NOT NULL OR - power IS NOT NULL OR - religion IS NOT NULL - ) - ) SELECT * FROM ( @@ -783,17 +446,11 @@ Layer: FROM ( SELECT way, - tourism, - tents, ST_ClusterDBSCAN(way, eps := 300.0 / cosd(ST_Y(ST_Transform(way, 4326))), minpoints := 2) over () AS cid FROM - points + pois WHERE - tourism = 'camp_site' OR - ( - tourism = 'caravan_site' AND - tents = 'yes' - ) + type = 'camp_site' ) ungrouped_campings WHERE cid IS NOT NULL @@ -804,88 +461,29 @@ Layer: SELECT way, - CASE - WHEN tourism IN ('camp_site', 'caravan_site') THEN 'camp_site' - WHEN tourism = 'hostel' THEN 'hostel' - WHEN shop = 'supermarket' THEN 'supermarket' - WHEN shop = 'convenience' THEN 'convenience_store' - WHEN shop = 'bicycle_shop' THEN 'bicycle_shop' - WHEN historic = 'castle' THEN 'castle' - WHEN historic = 'fort' THEN 'fort' - WHEN man_made = 'lighthouse' THEN 'lighthouse' - WHEN man_made = 'communications_tower' THEN 'tower_communication' - WHEN man_made = 'chimney' THEN 'tower_chimney' - WHEN power = 'generator' THEN 'wind_power' - WHEN amenity = 'place_of_worship' THEN 'place_of_worship' - WHEN man_made IN ('mast', 'tower') THEN 'tower_' || "tower:type" - WHEN mountain_pass = 'yes' THEN 'mountain_pass' - WHEN "natural" = 'peak' THEN 'peak' - END as type, + type, religion, - ele, + CASE + WHEN ele IS NOT NULL THEN ROUND(ele)::TEXT || ' m' + END as ele, scout, peak_isolation.isolation as isolation, 'no' as many FROM - points + pois LEFT JOIN - peak_isolation ON points.osm_id = peak_isolation.osm_id + peak_isolation ON pois.osm_id = peak_isolation.osm_id LEFT JOIN - mountain_pass_road ON points.osm_id = mountain_pass_road.osm_id + mountain_pass_road ON pois.osm_id = mountain_pass_road.osm_id WHERE ( - tourism IN ( - 'camp_site', - 'hostel' - ) OR - ( - tourism = 'caravan_site' AND - tents = 'yes' - ) OR - shop IN ( - 'supermarket', - 'convenience', - 'bicycle_shop' - ) OR - amenity IN ( - 'place_of_worship' - ) OR - historic IN ( - 'castle', - 'fort' - ) OR - man_made IN ( - 'lighthouse', - 'communications_tower' - ) OR - ( - man_made = 'chimney' AND - height >= 40 - ) OR - ( - man_made IN ('tower', 'mast') AND - "tower:type" IN ( - 'communication', - 'observation', - 'cooling' - ) AND - ("tower:type" != 'communication' OR height >= 80) - ) OR - ( - power = 'generator' AND - "generator:source" = 'wind' - ) OR - ( - mountain_pass = 'yes' AND - mountain_pass_road.road_osm_id IS NOT NULL - ) OR - ( - "natural" = 'peak' AND - peak_isolation.isolation >= 2500 - ) + type != 'mountain_pass' OR + mountain_pass_road.road_osm_id IS NOT NULL ) AND - (historic IS NULL OR historic != 'wayside_shrine') AND - (location IS NULL OR location NOT IN ('roof', 'rooftop')) + ( + peak_isolation.isolation IS NULL OR + peak_isolation.isolation >= 2500 + ) ) as poi ORDER BY CASE @@ -903,8 +501,7 @@ Layer: WHEN type = 'tower_cooling' THEN 12 WHEN type = 'tower_observation' THEN 13 WHEN type = 'tower_chimney' THEN 14 - WHEN type = 'place_of_worship' AND religion = 'christian' THEN 15 - WHEN type = 'place_of_worship' AND religion = 'muslim' THEN 16 + WHEN type = 'place_of_worship' AND religion IS NOT NULL THEN 16 WHEN type = 'place_of_worship' THEN 17 WHEN type = 'peak' THEN 18 ELSE 100 @@ -922,18 +519,13 @@ Layer: place, name FROM - planet_osm_point + places WHERE way && !bbox! AND - name IS NOT NULL AND - place IN ( - 'city', - 'town', - 'village' - ) + important ORDER BY CASE - WHEN (population ~ '^[0-9]{1,8}$') THEN population::INTEGER + WHEN population IS NOT NULL THEN population WHEN (place = 'city') THEN 100000 WHEN (place = 'town') THEN 1000 ELSE 1 @@ -952,15 +544,10 @@ Layer: ST_PointOnSurface(way) as way, name FROM - planet_osm_polygon + national_parks WHERE way && !bbox! AND - ( - boundary = 'national_park' OR - (boundary = 'protected_area' AND protect_class IN ('1','1a','1b','2','3','4','5','6')) - ) AND - name IS NOT NULL AND - way_area >= 2e6 + name IS NOT NULL ) AS data - id: roads-labels geometry: linestring @@ -971,30 +558,15 @@ Layer: ( SELECT way, - highway as type, - array_length(refs, 1) as height, - (SELECT MAX(char_length(ref)) FROM unnest(refs) AS u(ref)) as width, - array_to_string(refs, E'\n') as ref - FROM ( - SELECT - way, - highway, - access, - tunnel, - string_to_array(ref, ';') AS refs - FROM - planet_osm_line - WHERE - way && !bbox! AND - ref IS NOT NULL AND - highway IN ( - 'tertiary', - 'secondary', - 'primary' - ) AND - (access IS NULL OR access != 'private') AND - (tunnel IS NULL OR tunnel != 'yes') - ) AS splitrefs + type, + ref, + ref_height, + ref_width + FROM + roads + WHERE + way && !bbox! AND + ref IS NOT NULL ) AS data - id: water-labels geometry: line @@ -1006,43 +578,11 @@ Layer: SELECT way, name, - CASE - WHEN water IN ('lake', 'lagoon') THEN water - WHEN landuse IN ('reservoir', 'basin') then landuse - END as type - FROM - planet_osm_polygon - WHERE - way && !bbox! AND - "natural" = 'water' AND - ( - water IN ( - 'lake', - 'lagoon' - ) OR - landuse IN ( - 'reservoir', - 'basin' - ) - ) AND - name IS NOT NULL AND - way_area >= 2e6 - - UNION ALL - - SELECT - way, - name, - waterway as type + type FROM - planet_osm_line + water_labels WHERE - way && !bbox! AND - waterway IN ( - 'river' - ) AND - (tunnel IS NULL OR tunnel != 'yes') AND - name IS NOT NULL + way && !bbox! ) AS data - id: places-non-important geometry: point @@ -1056,13 +596,14 @@ Layer: place, name FROM - planet_osm_point + places WHERE way && !bbox! AND - name IS NOT NULL AND - place IN ( - 'hamlet' - ) + NOT important + ORDER BY + population DESC, + length(name) DESC, + name ) AS data - id: contour-labels geometry: linestring diff --git a/carto/map-it/styles.mss b/carto/map-it/styles.mss index 59d8225..e4c2e19 100644 --- a/carto/map-it/styles.mss +++ b/carto/map-it/styles.mss @@ -258,61 +258,59 @@ } } -#boundaries { - [boundary = 'administrative'] { - ::firstline { - background/line-join: round; - background/line-color: white; - background/line-width: 7; - } +#administrative-boundaries { + ::firstline { + background/line-join: round; + background/line-color: white; + background/line-width: 7; + } - ::wideline { - background/line-join: round; - background/line-color: white; - background/line-width: 4; + ::wideline { + background/line-join: round; + background/line-color: white; + background/line-width: 4; - opacity: 0.2; - line-color: @admin-background; - line-join: bevel; - line-width: 4; + opacity: 0.2; + line-color: @admin-background; + line-join: bevel; + line-width: 4; - [admin_level < 4] { - background/line-width: 7; - line-width: 7; - } + [admin_level < 4] { + background/line-width: 7; + line-width: 7; } + } - ::narrowline { - background/line-join: round; - background/line-color: white; - background/line-width: 1; - - opacity: 0.6; - thin/line-color: @admin-boundaries; - thin/line-width: 1; - thin/line-dasharray: 12,10; + ::narrowline { + background/line-join: round; + background/line-color: white; + background/line-width: 1; - [admin_level < 4] { - thin/line-width: 2; - thin/line-dasharray: 12,3,2,3,2,3; - } - } + opacity: 0.6; + thin/line-color: @admin-boundaries; + thin/line-width: 1; + thin/line-dasharray: 12,10; - ::firstline, - ::wideline, - ::narrowline { - comp-op: darken; + [admin_level < 4] { + thin/line-width: 2; + thin/line-dasharray: 12,3,2,3,2,3; } } - [boundary = 'national_park'] { - opacity: 0.4; - line-color: @national-park; - line-width: 6.0; - line-offset: -3.0; + ::firstline, + ::wideline, + ::narrowline { + comp-op: darken; } } +#national-parks { + opacity: 0.4; + line-color: @national-park; + line-width: 6.0; + line-offset: -3.0; +} + #cycling-routes { background/line-color: white; background/line-width: 1.9; @@ -742,19 +740,19 @@ marker-file: 'style/icons/maki/home-2-11.svg'; } - [type = 'supermarket'] { + [type = 'shop_supermarket'] { background/marker-width: 7; background/marker-file: 'style/icons/openstreetmap/shop2.svg'; marker-width: 7; marker-file: 'style/icons/openstreetmap/shop2.svg'; } - [type = 'convenience_store'] { + [type = 'shop_convenience'] { background/marker-width: 7; background/marker-file: 'style/icons/maki/convenience-11.svg'; marker-width: 7; marker-file: 'style/icons/maki/convenience-11.svg'; } - [type = 'bicycle_shop'] { + [type = 'shop_bicycle'] { background/marker-width: 9; background/marker-file: 'style/icons/maki/bicycle-11.svg'; marker-width: 9; @@ -911,23 +909,23 @@ shield-clip: false; // tertiary is the default - shield-file: url("style/symbols/shields/tertiary_[width]x[height].svg"); + shield-file: url("style/symbols/shields/tertiary_[ref_width]x[ref_height].svg"); shield-fill: @road-shield-tertiary-label; [type = 'secondary'] { - shield-file: url("style/symbols/shields/secondary_[width]x[height].svg"); + shield-file: url("style/symbols/shields/secondary_[ref_width]x[ref_height].svg"); shield-fill: @road-shield-secondary-label; } [type = 'primary'] { - shield-file: url("style/symbols/shields/primary_[width]x[height].svg"); + shield-file: url("style/symbols/shields/primary_[ref_width]x[ref_height].svg"); shield-fill: @road-shield-primary-label; } [type = 'trunk'] { - shield-file: url("style/symbols/shields/trunk_[width]x[height].svg"); + shield-file: url("style/symbols/shields/trunk_[ref_width]x[ref_height].svg"); shield-fill: @road-shield-trunk-label; } [type = 'motorway'] { - shield-file: url("style/symbols/shields/motorway_[width]x[height].svg"); + shield-file: url("style/symbols/shields/motorway_[ref_width]x[ref_height].svg"); shield-fill: @road-shield-motorway-label; } } diff --git a/import.Dockerfile b/import.Dockerfile index f5fdcfb..61101e1 100644 --- a/import.Dockerfile +++ b/import.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:12-slim as compilation +FROM debian:trixie-slim as compilation ENV DEBIAN_FRONTEND noninteractive @@ -13,7 +13,7 @@ WORKDIR /compilation COPY scripts/isolation.c . RUN gcc isolation.c -Wall -o isolation -lgdal -lm -O2 -FROM debian:12-slim as generation +FROM debian:trixie-slim as generation ENV DEBIAN_FRONTEND noninteractive @@ -36,7 +36,7 @@ COPY scripts/generate/legend.py . RUN chmod +x legend.py RUN legend.py legend.yaml > legend.osm -FROM debian:12-slim +FROM debian:trixie-slim LABEL maintainer="Hidde Wieringa " @@ -72,7 +72,7 @@ WORKDIR /data COPY --from=compilation /compilation/isolation /script COPY --from=generation /generation/legend.osm /legend/legend.osm -COPY style/map-it.style /script/map-it.style +COPY scripts/map-it.lua /script/map-it.lua COPY scripts/download.sh /script/download.sh COPY style/shade /style/shade RUN chmod +x /script/download.sh diff --git a/kosmtik.Dockerfile b/kosmtik.Dockerfile index e3167d9..1d72178 100644 --- a/kosmtik.Dockerfile +++ b/kosmtik.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:12-slim +FROM debian:trixie-slim ENV DEBIAN_FRONTEND noninteractive diff --git a/scripts/download.sh b/scripts/download.sh index 5676e3a..4e4875b 100644 --- a/scripts/download.sh +++ b/scripts/download.sh @@ -133,14 +133,15 @@ echo "Using $OSM2PGSQL_NUMPROC processes" echo "Starting import from $DATA_DIR/combined.osm.pbf" # No --hstore is used, because no tag data is needed -# Everything that is needed should be put into style/map-it.style +# Everything that is needed should be put into scripts/map-it.lua osm2pgsql \ --cache $OSM2PGSQL_CACHE \ --number-processes $OSM2PGSQL_NUMPROC \ --host "$PG_HOST" \ --database "$PG_DATABASE" \ --username "$PG_USER" \ - --style /script/map-it.style \ + --output flex \ + --style /script/map-it.lua \ $DATA_DIR/combined.osm.pbf \ || exit 1 @@ -326,7 +327,8 @@ osm2pgsql \ --host "$PG_HOST" \ --database "$PG_LEGEND_DATABASE" \ --username "$PG_USER" \ - --style /script/map-it.style \ + --output flex \ + --style /script/map-it.lua \ /tmp/legend_cleaned.osm psql $POSTGRES_LEGEND_ARGS -c "$(cat <= 2e6 then + water_labels:insert({ + way = object:as_multipolygon(), + name = tags.name, + type = 'lake', + }) + end + end + + if tags.waterway == 'river' + and tags.tunnel ~= 'yes' + and tags.name + then + water_labels:insert({ + way = object:as_linestring(), + name = tags.name, + type = 'river', + }) + end +end + +function process_dam(object) + local tags = object.tags + if tags.waterway == 'dam' then + local type = object.is_closed and 'polygon' or 'line' + dams:insert({ + way = object:as_linestring(), + type = type, + }) + end +end + +-- Administrative boundaries: Levels 0 to 6 are included which has (super-)country +-- and state administrative borders +local administrative_admin_level_values = osm2pgsql.make_check_values_func({'0', '1', '2', '3', '4', '5', '6'}) +function process_administrative_boundary(object) + local tags = object.tags + if tags.boundary == 'administrative' + and administrative_admin_level_values(tags.admin_level) + then + administrative_boundaries:insert({ + way = object:as_multilinestring(), + admin_level = tags.admin_level, + }) + end +end + +local national_park_protect_class_values = osm2pgsql.make_check_values_func({'1', '1a', '1b', '2', '3', '4', '5', '6'}) +function process_national_park(object) + local tags = object.tags + if (tags.boundary == 'national_park' + or (tags.boundary == 'protected_area' and national_park_protect_class_values(tags.protect_class))) + then + local way = object:as_multipolygon() + local area = way:spherical_area() + if area >= 5e5 then + national_parks:insert({ + way = way, + name = area >= 2e6 and tags.name or nil, + }) + end + end +end + +function process_ferry(object) + local tags = object.tags + if tags.route == 'ferry' then + ferries:insert({ + way = object:as_multilinestring(), + }) + end +end + +function process_power_line(object) + local tags = object.tags + if tags.power == 'line' then + power_lines:insert({ + way = object:as_multilinestring(), + }) + end +end + +function process_power_pole(object) + local tags = object.tags + if tags.power == 'tower' then + power_poles:insert({ + way = object:as_point(), + }) + end +end + +local tunnel_highway_values = osm2pgsql.make_check_values_func({ 'motorway_link', 'trunk_link', 'secondary_link', 'primary_link', 'motorway', 'trunk', 'cycleway', 'tertiary', 'secondary', 'primary' }) +local tunnel_railway_values = osm2pgsql.make_check_values_func({ 'rail', 'narrow_gauge' }) +local service_values = osm2pgsql.make_check_values_func({ 'crossover', 'spur', 'yard' }) +function process_tunnel(object) + local tags = object.tags + if tunnel_highway_values(tags.highway) + and tags.access ~= 'private' + and tags.tunnel == 'yes' + then + tunnels:insert({ + way = object:as_linestring(), + layer = tags.layer, + type = tags.highway, + }) + end + if tunnel_railway_values(tags.railway) + and tags.tunnel == 'yes' + and not service_values(tags.service) + then + tunnels:insert({ + way = object:as_linestring(), + layer = tags.layer, + type = tags.highway, + }) + end +end + +function process_aeroway(object) + local tags = object.tags + if tags.aeroway == 'runway' then + aeroways:insert({ + way = object:as_linestring(), + }) + end +end + +local road_railway_values = osm2pgsql.make_check_values_func({ 'rail', 'narrow_gauge', 'preserved' }) +local road_disallowed_highway_values = osm2pgsql.make_check_values_func({ 'platform', 'construction', 'proposed', 'steps' }) +local road_bicycle_values = osm2pgsql.make_check_values_func({ 'yes', 'designated', 'permissive' }) +local ref_highway_values = osm2pgsql.make_check_values_func({ 'primary', 'secondary', 'tertiary' }) +function process_road(object) + local tags = object.tags + if tags.highway + and not road_disallowed_highway_values(tags.highway) + and tags.access ~= 'private' + and tags.tunnel ~= 'yes' + then + local type = tags.highway + if tags.bicycle == 'designated' then + type = 'cycleway' + elseif tags.highway == 'road' then + type = 'unclassified' + elseif tags.highway == 'living_street' then + type = 'residential' + end + + local has_ref = tags.ref and ref_highway_values(tags.highway) + local refs = osm2pgsql.split_string(has_ref and tags.ref or nil) + local ref_height = 0 + local ref_width = 0 + for _, ref in pairs(refs) do + ref_height = ref_height + 1 + ref_width = math.max(ref_width, ref:len()) + end + roads:insert({ + way = object:as_linestring(), + type = type, + bicycle = road_bicycle_values(tags.bicycle), + tracktype = tags.tracktype, + layer = tags.layer, + ref = has_ref and table.concat(refs, "\n") or nil, + ref_width = has_ref and ref_width or nil, + ref_height = has_ref and ref_height or nil, + }) + end + if road_railway_values(tags.railway) + and not service_values(tags.service) + and tags.tunnel ~= 'yes' + then + roads:insert({ + way = object:as_linestring(), + type = 'railway', + railway = tags.railway, + bicycle = 'F', + tracktype = tags.tracktype, + layer = tags.layer, + }) + end +end + +function process_cycling_node(object) + local tags = object.tags + if tags.rcn_ref + and tags['network:type'] == 'node_network' + then + cycling_nodes:insert({ + way = object:as_point(), + ref = tags.rcn_ref, + }) + end +end + +function process_cycling_route(object) + local tags = object.tags + if tags.route == 'bicycle' then + cycling_routes:insert({ + way = object:as_multilinestring(), + }) + end +end + +local railway_values = osm2pgsql.make_check_values_func({'station', 'halt'}) +local disallowed_station_values = osm2pgsql.make_check_values_func({'subway', 'light_rail', 'monorail', 'funicular'}) +function process_transport(object) + local tags = object.tags + if tags.aeroway == 'aerodrome' then + transport:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'aerodrome', + }) + end + if railway_values(tags.railway) + and (not tags.station + or not disallowed_station_values(tags.station)) + then + transport:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'train_station', + }) + end + if tags.amenity == 'ferry_terminal' then + transport:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'ferry_terminal', + }) + end +end + +local shop_values = osm2pgsql.make_check_values_func({'supermarket', 'convenience', 'bicycle'}) +local historic_values = osm2pgsql.make_check_values_func({'castle', 'fort'}) +local man_made_values = osm2pgsql.make_check_values_func({'tower', 'mast'}) +local tower_type_values = osm2pgsql.make_check_values_func({'communication', 'observation', 'cooling'}) +local disallowed_tower_location_values = osm2pgsql.make_check_values_func({'roof', 'rooftop'}) +function process_poi(object) + local tags = object.tags + local height = tags.height and parse_height(tags.height) or nil + + if tags.tourism == 'camp_site' + or (tags.tourism == 'caravan_site' and tags.tents == 'yes') + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'camp_site', + scout = tags.scout, + }) + end + if tags.tourism == 'hostel' then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'hostel', + }) + end + if shop_values(tags.shop) then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'shop_' .. tags.shop, + }) + end + if historic_values(tags.historic) then + -- todo combine type + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = tags.historic, + }) + end + if tags.man_made == 'lighthouse' then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = tags.man_made, + }) + end + if tags.man_made == 'communications_tower' + and not disallowed_tower_location_values(tags.location) + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'tower_communication', + }) + end + if tags.man_made == 'chimney' + and (height and height >= 40) + and not disallowed_tower_location_values(tags.location) + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'tower_chimney', + }) + end + if man_made_values(tags.man_made) + and tower_type_values(tags["tower:type"]) + and (tags["tower:type"] ~= 'communication' or (height and height >= 80)) + and not disallowed_tower_location_values(tags.location) + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = "tower_" .. tags["tower:type"], + }) + end + if tags.power == 'generator' + and tags["generator:source"] == 'wind' + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type ='wind_power', + }) + end + if tags.mountain_pass == 'yes' then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'mountain_pass', + ele = tags.ele and tonumber(tags.ele) or nil, + }) + end + if tags.natural == 'peak' then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'peak', + ele = tags.ele and tonumber(tags.ele) or nil, + }) + end + if tags.amenity == 'place_of_worship' + and tags.historic ~= 'wayside_shrine' + then + pois:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'place_of_worship', + religion = tags.religion, + }) + end + + if railway_values(tags.railway) + and (not tags.station + or not disallowed_station_values(tags.station)) + then + transport:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'train_station', + }) + end + if tags.amenity == 'ferry_terminal' then + transport:insert({ + way = object.type == 'way' and object:as_linestring():centroid() or object:as_point(), + type = 'ferry_terminal', + }) + end +end + +local important_place_values = osm2pgsql.make_check_values_func({'city', 'town', 'village'}) +local non_important_place_values = osm2pgsql.make_check_values_func({'hamlet'}) +function process_place(object) + local tags = object.tags + local important_place = important_place_values(tags.place) + if (important_place or non_important_place_values(tags.place)) + and tags.name + then + places:insert({ + way = object:as_point(), + place = tags.place, + name = tags.name, + population = tonumber(tags.population), + important = tags.place == important_place, + }) + end +end + +function osm2pgsql.process_node(object) + process_power_pole(object) + process_cycling_node(object) + process_transport(object) + process_poi(object) + process_place(object) +end + +function osm2pgsql.process_way(object) + process_landuse_background(object) + process_landuse_foreground(object) + process_waterways(object) + process_water(object) + process_dam(object) + process_power_line(object) + process_tunnel(object) + process_aeroway(object) + process_road(object) + process_transport(object) + process_poi(object) + process_water_labels(object) +end + +function osm2pgsql.process_relation(object) + process_landuse_background(object) + process_landuse_foreground(object) + process_water(object) + process_administrative_boundary(object) + process_national_park(object) + process_ferry(object) + process_cycling_route(object) +end diff --git a/style/map-it.style b/style/map-it.style deleted file mode 100644 index 7c9c5cd..0000000 --- a/style/map-it.style +++ /dev/null @@ -1,243 +0,0 @@ -# This is the osm2pgsql .style file for map-it. -# This file is based on the osm2pgsql default.style file, as found in -# https://github.com/openstreetmap/osm2pgsql/blob/7b854278d7bc6932bbbc4e30f593f8158cc0c55e/default.style - -# A .style file has 4 columns that define how OSM objects end up in tables in -# the database and what columns are created. It interacts with the command-line -# hstore options. -# -# Columns -# ======= -# -# OsmType: This is either "node", "way" or "node,way" and indicates if this tag -# applies to nodes, ways, or both. -# -# Tag: The tag -# -# DataType: The type of the column to be created. Normally "text" -# -# Flags: Flags that indicate what table the OSM object is moved into. -# -# There are 6 possible flags. These flags are used both to indicate if a column -# should be created, and if ways with the tag are assumed to be areas. The area -# assumptions can be overridden with an area=yes/no tag -# -# polygon - Create a column for this tag, and objects with the tag are areas -# -# linear - Create a column for this tag -# -# nocolumn - Override the above and don't create a column for the tag, but do -# include objects with this tag -# -# phstore - Same as polygon,nocolumn for backward compatibility -# -# delete - Drop this tag completely and don't create a column for it. This also -# prevents the tag from being added to hstore columns -# -# nocache - Deprecated and does nothing -# -# If an object has a tag that indicates it is an area or has area=yes/1, -# osm2pgsql will try to turn it into an area. If it succeeds, it places it in -# the polygon table. If it fails (e.g. not a closed way) it places it in the -# line table. -# -# Nodes are never placed into the polygon or line table and are always placed in -# the point table. -# -# Hstore -# ====== -# -# The options --hstore, --hstore-match-only, and --hstore-all interact with -# the .style file. -# -# With --hstore any tags without a column will be added to the hstore column. -# This will also cause all objects to be kept. -# -# With --hstore-match-only the behavior for tags is the same, but objects are -# only kept if they have a non-NULL value in one of the columns. -# -# With --hstore-all all tags are added to the hstore column unless they appear -# in the style file with a delete flag, causing duplication between the normal -# columns and the hstore column. -# -# Special database columns -# ======================== -# -# There are some special database columns that if present in the .style file -# will be populated by osm2pgsql. -# -# These are -# -# z_order - datatype int4 -# -# way_area - datatype real. The area of the way, in the units of the projection -# (e.g. square mercator meters). Only applies to areas -# -# osm_user - datatype text -# osm_uid - datatype integer -# osm_version - datatype integer -# osm_changeset - datatype integer -# osm_timestamp - datatype timestamptz(0). -# Used with the --extra-attributes option to include metadata in the database. -# If importing with both --hstore and --extra-attributes the meta-data will -# end up in the tags hstore column regardless of the style file. - -# 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 -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 -node,way boundary text linear -node,way building text delete # Modified from 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 -node,way height text linear -node,way highway text linear -node,way historic text polygon -# node,way horse text linear -# node,way intermittent text linear -# node,way junction text linear -node,way landuse text polygon -node,way layer text linear -# node,way leisure text polygon -node,way location text linear -# node,way lock text linear -node,way man_made text polygon -# node,way military text polygon -# node,way motorcar text linear -node,way mountain_pass 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 network:type text linear -# node,way office 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 protect_class text linear -node,way railway text linear -node,way rcn_ref text linear -node,way ref text linear -node,way religion text linear -node,way route text linear -node,way service text linear -node,way shop text polygon -node,way station text linear -# node,way sport text polygon -node,way surface text linear -node,way tents text linear -# node,way toll text linear -node,way tourism text polygon -node,way scout text linear -node,way tower:type text linear -way tracktype text linear -node,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. -# Mainly for use with hstore -way abandoned:aeroway text polygon,nocolumn -way abandoned:amenity text polygon,nocolumn -way abandoned:building text polygon,nocolumn -way abandoned:landuse text polygon,nocolumn -way abandoned:power text polygon,nocolumn -way area:highway text polygon,nocolumn - -# 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