diff --git a/layers/place/city.sql b/layers/place/city.sql index af23866..d5304d3 100644 --- a/layers/place/city.sql +++ b/layers/place/city.sql @@ -3,9 +3,9 @@ -- etldoc: label="layer_city | z2-z7 | z8_z14_ " ] ; CREATE OR REPLACE FUNCTION layer_city(bbox geometry, zoom_level int, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, class city_class, "rank" int) AS $$ +RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, place city_place, "rank" int, capital int) AS $$ -- etldoc: osm_city_point -> layer_city:z2_7 - SELECT osm_id, geometry, name, COALESCE(NULLIF(name_en, ''), name) AS name_en, place AS class, "rank" + SELECT osm_id, geometry, name, COALESCE(NULLIF(name_en, ''), name) AS name_en, place, "rank", normalize_capital_level(capital) AS capital FROM osm_city_point WHERE geometry && bbox AND ((zoom_level = 2 AND "rank" = 1) @@ -14,10 +14,11 @@ RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, class c UNION ALL SELECT osm_id, geometry, name, COALESCE(NULLIF(name_en, ''), name) AS name_en, - place AS class, - COALESCE("rank", gridrank + 10) + place, + COALESCE("rank", gridrank + 10), + normalize_capital_level(capital) AS capital FROM ( - SELECT osm_id, geometry, name, name_en, place, "rank", + SELECT osm_id, geometry, name, name_en, place, "rank", capital, row_number() OVER ( PARTITION BY LabelGrid(geometry, 128 * pixel_width) ORDER BY "rank" ASC NULLS LAST, @@ -28,11 +29,12 @@ RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, class c -- etldoc: osm_city_point -> layer_city:z8_14_ FROM osm_city_point WHERE geometry && bbox - AND ((zoom_level = 8 AND place <= 'town'::city_class) - OR (zoom_level BETWEEN 9 AND 10 AND place <= 'village'::city_class) - OR (zoom_level BETWEEN 11 AND 13 AND place <= 'suburb'::city_class) + AND ((zoom_level = 8 AND place <= 'town'::city_place + OR (zoom_level BETWEEN 9 AND 10 AND place <= 'village'::city_place) + + OR (zoom_level BETWEEN 11 AND 13 AND place <= 'suburb'::city_place) OR (zoom_level >= 14) - ) + )) ) AS ranked_places WHERE (zoom_level = 8 AND (gridrank <= 4 OR "rank" IS NOT NULL)) OR (zoom_level = 9 AND (gridrank <= 8 OR "rank" IS NOT NULL)) diff --git a/layers/place/class.sql b/layers/place/class.sql new file mode 100644 index 0000000..fa34921 --- /dev/null +++ b/layers/place/class.sql @@ -0,0 +1,18 @@ +CREATE OR REPLACE FUNCTION place_class(place TEXT) +RETURNS TEXT AS $$ + SELECT CASE + WHEN place IN ('city', 'town', 'village', 'hamlet', 'isolated_dwelling') THEN 'settlement' + WHEN place IN ('suburb', 'neighbourhood') THEN 'subregion' + WHEN place IN ('locality', 'farm') THEN 'other' + ELSE NULL + END; +$$ LANGUAGE SQL IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION normalize_capital_level(capital TEXT) +RETURNS INT AS $$ + SELECT CASE + WHEN capital IN ('yes', '2') THEN 2 + WHEN capital = '4' THEN 4 + ELSE NULL + END; +$$ LANGUAGE SQL IMMUTABLE STRICT; diff --git a/layers/place/layer.sql b/layers/place/layer.sql new file mode 100644 index 0000000..a687194 --- /dev/null +++ b/layers/place/layer.sql @@ -0,0 +1,32 @@ + +-- etldoc: layer_place[shape=record fillcolor=lightpink, style="rounded,filled", +-- etldoc: label="layer_place | z0-z14_ " ] ; + +-- etldoc: layer_continent -> layer_place +-- etldoc: layer_country -> layer_place +-- etldoc: layer_state -> layer_place +-- etldoc: layer_city -> layer_place + +CREATE OR REPLACE FUNCTION layer_place(bbox geometry, zoom_level int, pixel_width numeric) +RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, class text, subclass text, "rank" int, capital INT) AS $$ + SELECT + osm_id, geometry, name, name_en, + 'continent' AS class, 'continent' AS subclass, 1 AS "rank", NULL::int AS capital + FROM osm_continent_point + WHERE geometry && bbox AND zoom_level < 4 + UNION ALL + SELECT + osm_id, geometry, name, name_en, + 'country' AS class, 'country' AS subclass,"rank", NULL::int AS capital + FROM layer_country(bbox, zoom_level) + UNION ALL + SELECT + osm_id, geometry, name, name_en, + 'state' AS class, 'state' AS subclass, "rank", NULL::int AS capital + FROM layer_state(bbox, zoom_level) + UNION ALL + SELECT + osm_id, geometry, name, name_en, + place_class(place::text) AS class, place::text AS subclass, "rank", capital + FROM layer_city(bbox, zoom_level, pixel_width) +$$ LANGUAGE SQL IMMUTABLE; diff --git a/layers/place/mapping.yaml b/layers/place/mapping.yaml index 2e34232..aa3b148 100644 --- a/layers/place/mapping.yaml +++ b/layers/place/mapping.yaml @@ -12,6 +12,23 @@ rank_field: &rank type: integer tables: + # etldoc: imposm3 -> osm_continent_point + continent_point: + type: point + fields: + - name: osm_id + type: id + - name: geometry + type: geometry + - *name + - *name_en + filters: + exclude_tags: + - [ "name", "__nil__" ] + mapping: + place: + - continent + # etldoc: imposm3 -> osm_country_point country_point: type: point @@ -73,6 +90,9 @@ tables: - key: population name: population type: integer + - key: capital + name: capital + type: string - *rank filters: exclude_tags: diff --git a/layers/place/merge_city_rank.sql b/layers/place/merge_city_rank.sql index 025f058..66ce265 100644 --- a/layers/place/merge_city_rank.sql +++ b/layers/place/merge_city_rank.sql @@ -18,7 +18,7 @@ WITH important_city_point AS ( ne.nameascii ILIKE osm.name OR ne.nameascii ILIKE osm.name_en ) - AND (osm.place = 'city'::city_class OR osm.place= 'town'::city_class OR osm.place = 'village'::city_class) + AND osm.place IN ('city', 'town', 'village') AND ST_DWithin(ne.geom, osm.geometry, 50000) ) UPDATE osm_city_point AS osm diff --git a/layers/place/place.sql b/layers/place/place.sql deleted file mode 100644 index 8e11d21..0000000 --- a/layers/place/place.sql +++ /dev/null @@ -1,16 +0,0 @@ - --- etldoc: layer_place[shape=record fillcolor=lightpink, style="rounded,filled", --- etldoc: label="layer_place | z0-z14_ " ] ; - --- etldoc: layer_country -> layer_place --- etldoc: layer_state -> layer_place --- etldoc: layer_city -> layer_place - -CREATE OR REPLACE FUNCTION layer_place(bbox geometry, zoom_level int, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, class text, "rank" int) AS $$ - SELECT osm_id, geometry, name, name_en, 'country' AS class, "rank" FROM layer_country(bbox, zoom_level) - UNION ALL - SELECT osm_id, geometry, name, name_en, 'state' AS class, "rank" FROM layer_state(bbox, zoom_level) - UNION ALL - SELECT osm_id, geometry, name, name_en, class::text, "rank" FROM layer_city(bbox, zoom_level, pixel_width) -$$ LANGUAGE SQL IMMUTABLE; diff --git a/layers/place/place.yaml b/layers/place/place.yaml index 2ac875d..02bedd7 100644 --- a/layers/place/place.yaml +++ b/layers/place/place.yaml @@ -25,16 +25,17 @@ layer: buffer_size: 128 datasource: geometry_field: geometry - query: (SELECT geometry, name, name_en, class, rank FROM layer_place(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t + query: (SELECT geometry, name, name_en, class, subclass, rank, capital FROM layer_place(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t schema: - ./types.sql + - ./class.sql - ./city.sql - ./country.sql - ./state.sql - ./merge_country_rank.sql - ./merge_city_rank.sql - ./merge_state_rank.sql - - ./place.sql + - ./layer.sql datasources: - type: imposm3 mapping_file: ./mapping.yaml diff --git a/layers/place/types.sql b/layers/place/types.sql index 48c575e..f7fdedf 100644 --- a/layers/place/types.sql +++ b/layers/place/types.sql @@ -1,9 +1,9 @@ DO $$ BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'city_class') THEN - CREATE TYPE city_class AS ENUM ('city', 'town', 'village', 'hamlet', 'suburb', 'neighbourhood', 'isolated_dwelling'); + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'city_place') THEN + CREATE TYPE city_place AS ENUM ('city', 'town', 'village', 'hamlet', 'suburb', 'neighbourhood', 'isolated_dwelling'); END IF; END $$; -ALTER TABLE osm_city_point ALTER COLUMN place TYPE city_class USING place::city_class; +ALTER TABLE osm_city_point ALTER COLUMN place TYPE city_place USING place::city_place;