Compare commits

..

135 Commits

Author SHA1 Message Date
2a39e1ebfe Merge branch 'master' into gh-master
# Conflicts:
#	Makefile
#	layers/landuse/landuse.sql
#	layers/poi/poi.sql
2021-04-24 22:47:18 +02:00
Jeremias Volker
76d5d753d8
Fix own OSM instructions (#1101)
Before it was throwing `ERROR:  make generate-bbox-file area=<area-id>` and `Area source has not been specified. Auto-detecting...
ID 'my' was not found in Geofabrik.` `make: *** [download] Error 1`

* Use more meaningful area name

* rename user data example

Co-authored-by: Tomas Pohanka <TomPohys@gmail.com>
2021-04-20 14:59:43 +02:00
Eva Jelinkova
f4a1a2537a
Water - add ogc_fid for NE sources, edit etldoc (#1098)
1) Adding ogc_fid column into materialized views of NE lakes (for having option to filter or compare)
2) Edit bug in etldoc

* add ogc_fid for NE sources, edit etldoc

* etl_diagram update
2021-04-12 12:09:45 +02:00
Rémy Léone
231a1d192c
update docker-compose version (#1091)
update docker-compose version from 2.3 to 3
2021-04-09 13:42:58 +02:00
Yuri Astrakhan
1f6eb7b4a3
Improve logging - show BBOX if exists (#1096)
The generate-bbox target will now show the value of BBOX if it is already generated.
2021-03-30 21:02:34 +02:00
Rémy Léone
d5480d2369
Update naming convention for networks (#1093)
* Update naming convention for networks

* move to postgres
2021-03-30 08:46:42 +02:00
zstadler
2943e9dc8d
Avoid grep errors in clean-unnecessary-docker (#1089)
When `make clean-unnecessary-docker` is run twice, or when there are no docker images tagges as "<none>", make fails because grep fails:

```
Deleting unnecessary container(s)...
Deleting unnecessary image(s)...
make: *** [Makefile:562: clean-unnecessary-docker] Error 1
```

Using `awk` to _also_ search for "<none>", instead of `grep`, solves this issue.
2021-03-16 17:20:25 +01:00
Tomas Pohanka
fadc4a3ba6
Explicit mention for using iso_a2 attribute. (#1073)
Resolve #939
2021-03-16 11:21:25 +01:00
Tomas Pohanka
bf9e6a19cd
osm_route_member bugfix (#1088)
`!=` is not handling `NULL` values.

Then all networks are `road` and not e.g. `us-interstate` or `ca-transcanada`.
2021-03-16 10:55:26 +01:00
Frédéric Rodrigo
50d569dfee
Remove useless indices on osm_transportation_merge_linestring_genX (#1079)
On creation of materialized views `osm_transportation_merge_linestring_gen_zX`, an index is created each time the new view and not used else where than the next generalization step.
It does not worth it to to a scan on the table to create index that will be used only once, while the next generalisation step can also be done in one full scan.
So, removing these indices.
2021-03-05 09:42:27 +01:00
Adam Laža
d69ae015ad
Mount /export dir in docker-compose.yaml (#1071)
Mount /export dir in docker-compose.yaml
This PR allows `using make generate-tiles-pg` without editing `.env`.
Resolves #1070
Related to PR #1069
2021-02-05 14:58:42 +01:00
Jeroen Hoek
295688eb80
Add place=quarter to city subdivisions (#1065)
This adds `place=quarter` which was introduced in 2011 as a subdivision
of villages/towns/cities as a value that sits between `place=suburb` and
`place=neighbourhood`. It has by now been used over 40,000 times and is
rendered in the OSM-Carto.
2021-01-18 14:47:25 +01:00
Adam Laža
c4c3089f40
Update openmaptiles.yaml - set center to 0,0,1 (#1063) 2021-01-14 18:13:00 +01:00
Adam Laža
4b26c63574
Upgrade version to 3.12.1 (#1062)
* Release 3.12 prerequisite

* Upgrade version.

Co-authored-by: Tomáš <tompohys@gmail.com>
2021-01-14 17:21:43 +01:00
tilmanb
077ec78f63
typo and spelling fixes in the output (#1060)
This simply fixes some spelling and/or grammar errors in the quickstart script output
2021-01-10 16:55:52 +01:00
Adam Laža
461043960e
Bugfix landcover osm (#1061)
* Release 3.12 prerequisite

* Add missing osm_id column to osm_landcover_polygon

Co-authored-by: Tomáš <tompohys@gmail.com>
2021-01-08 15:44:11 +01:00
Sergii Golubev
2aa9630b41
add forgotten 'garages' landuse to the docs (#1059)
In https://github.com/openmaptiles/openmaptiles/pull/720 I've forgotten to add the `garages` class to the docs. This PR is fixing that issue,
2020-12-29 14:26:14 +02:00
Tomas Pohanka
485eb6892c
Release 3.12 prerequisite (#1056) 2020-12-16 14:38:58 +02:00
Adam Laža
5772e61244
Bugfix in osm_landcover_gen_z10. (#1054)
Add missing `NOT` in WHERE condition.
It causes there are duplicated features of subclass `wood` and `forest` and features of other subclasses are missing.
2020-12-14 12:47:45 +02:00
Adam Laža
512b3435ad
Bugfix update_aerodrome_label_point() (#1051)
Bug introduced in #944.
Missing exclamation mark in not equal operator caused that tags were not updated thus there were missing `name_int`, `name:latin` and `name:nonlatin`.
2020-12-08 17:27:12 +02:00
Dalibor Janák
b2b8716840
Update links in readme (#1050)
Updated not existing links to openmaptiles.com.
2020-12-08 16:57:40 +02:00
Taro Matsuzawa aka. btm
924558d7d9
Enable pgquery (#1048)
I try to use pgquery, it needs some configuration in .env file.
I think if we use pgquery instead of mapnik, the performace will be good.
2020-12-08 15:56:01 +02:00
Andrii Korzh
01d53a26c6
Fix detected area filename (#1049)
User can be confused that script detected non existing file.
2020-12-07 17:30:16 +02:00
Adam Laža
77f5d76e37
Refactor schema, one _gen_z view per zoom. (#1045)
* Refactor layer aeroway.

* Refactor layer boundary.

* Refactor layer landcover.

* Refactor layer landuse.

* Refactor layer park.

* Refactor layer transportation.

* Refactor layer water.

* Refactor layer waterway.

* Re-generate water* layers etl_diagrams.

* Regenerate etl_diagrams for waterway.

* Cast NULL to text.
2020-11-26 13:54:00 +01:00
Tomas Pohanka
0c6fe2d9ba
Building aggregation fix (#1044)
This PR solving the speed and memory issue with buildings aggregation on zoom level 13. The problem was to create ST_ClusterDBScan which failed after try to cluster a larger area. Now it will make cluster only in "small" polygon using 'country_osm_grid` which covers the world's lands. 

This PR solving #1022 and #974
2020-11-24 12:27:06 +02:00
Tomas Pohanka
24b9328a5f
Remove unused generalization from waterway (#1043)
During the import-osm step, there are three generalized tables for the waterway that are not used for subsequent processing.
Thanks @lazaa32 for the notice.
2020-11-24 11:30:00 +02:00
Adam Laža
da689f9e42
Fix landcover generalization. (#1042)
This PR brings few modification which make it possible to generalize landcover on larger areas. Tested on Europe.

- Use ST_SnapToGrid to avoid ERROR:  GEOSUnaryUnion: TopologyException: found non-noded intersection between LINESTRING.
- Cluster only landcover subclasses: wood and forest.
- Use less generalized tables as a starting point for next step generalization.
2020-11-24 10:33:06 +02:00
Tomas Pohanka
0776cd3eed
README - Rename target for bbox-file by new tool 5.3 (#1040)
Changed in Use 5.3 - new bbox value (#1012)
2020-11-13 14:34:41 +02:00
Tomas Pohanka
3ef364552e
add state name to national borders (#1039)
This PR adds state name to national borders (`admin_level=2`)

From zoom level 3 there is an added `adm0_l` and `adm0_r` attribute for national borders.

There is 3 main steps: 
1) union border lines from OSM and keep separate LineString between intersects
2) create polygons from step 1), create a point in each state polygon, add to this point a state abbreviation from NaturalEarth Data
3) create a short parallel line on the left and right of a small part of the border in 70m distance, and add information about which state overlap this short line.
2020-11-12 12:14:13 +02:00
Tomas Pohanka
d180988f5f
Move "qa" tools from OMT to OMT-T (#1031)
With the new release of OMT-T (5.3) are available tools [`layer-stat`](https://github.com/openmaptiles/openmaptiles-tools/pull/293). 

With the new release of OMT-T can be replaced `make` target `generate-qareports` by `generate-qa`

Used as:
```
make generate-qa STAT_FUNCTION=frequency LAYER=transportation ATTRIBUTE=class
```
2020-11-12 11:23:06 +02:00
Eva Jelinkova
0aa6648bd9
adding brunnel into z<9 (#1038)
Following https://github.com/openmaptiles/openmaptiles/pull/1027, solving https://github.com/openmaptiles/openmaptiles/issues/999.

Adding brunnel attributes to merge tables of `transportation` layer, now it is possible to style/filter tunnels, bridges and fords in all zoom levels. Tested on Switzerland and Europe. Changes in generation speed and filesize minimal.
2020-11-11 15:37:09 +02:00
Tomas Pohanka
4a1b0afa26
reworked landcover layer (#1035)
Instead of using [Douglas-Peucker algorithm](https://postgis.net/docs/ST_SimplifyPreserveTopology.html) which is using for generalized tables [imposm](https://imposm.org/docs/imposm3/latest/mapping.html#generalized-tables) it is used [Visvalingam-Whyatt algorithm](https://postgis.net/docs/ST_SimplifyVW.html).

Solution:
remove imposm generalized tables (during `import-osm`) and create generalization in `import-sql` step for zooms 7-14. Zooms 0-6 are from Natural Earth data.

Upper zoom levels (7 and 8) are ok to merge with no big impact on creation speed. In Canada from z9 it took too long. Between zoom levels 10 - 13 there can be union polygons with less than 300 edge points (empirical number based on a test on Canada forest, can be discussed). Polygons with more than 300 edge points are just simplified. Zoom 14 is from the original dataset `osm_landcover_polygon`.

There is also removed `osm_id` which is never used and not passed into vector tiles.
2020-11-11 15:11:48 +02:00
Adam Laža
0dc8c3256c
Rename generic layer.sql to actual_layer_name .sql (#1034)
Following layers had generic `layer.sql` name.

- `aerodrome_label`
- `aeroway`
- `housenumber`
- `mountain_peak`
- `park`
- `place`
- `poi`
- `transportation`
- `transportation_name`
- `water_name`

This PR renames `layer.sql` to `aerodrome_label.sql`, `aeroway.sql`...
2020-11-09 11:43:35 +02:00
Eva Jelinkova
a36db48a3e
Revert "#766 remove housenumbers inside polygon and same number (#983)" (#1033)
This reverts commit 1685eaccbd0ab9f8e4b32bcd4f4a20fd502a5d13.
2020-11-04 21:53:15 +01:00
Eva Jelinkova
8ba2e18dea
Revert "Housenumbers - diff update, multipolygons (#990)" (#1032)
This reverts commit f7d7a0ced3279597dba49f530b8668f934757988.
2020-11-04 21:07:09 +01:00
Yuri Astrakhan
97ffabcb49
Use 5.3 - new bbox value (#1012)
Migrate to tools 5.3 and use the new bbox value.

* Use 5.3 - new bbox value
* Return correct bbox for meta-generate
mbtiles-tools meta-generate is now able to use bbox from *.bbox file

Thanks @nyurik
2020-10-26 18:39:49 +02:00
Tomas Pohanka
72af34612a
Add gates to airports (#1029) 2020-10-19 12:24:16 +03:00
zstadler
09b68ed1c2
Allow BBOX to be set in .env file (#1013)
* Allow setting `BBOX` to be set in `.env` file

Currently, the `BBOX` setting in `.env` is ignored for all areas except `planet`.
On the other hand, the `planet` area is an overkill for any `BBOX` setting other than the default - `-180.0,-85.0511,180.0,85.0511`.

With this PR, `quickstart.sh` would not override a modified `BBOX` value in `.env`. 

Also, this provides a way to avoid the pessimistic `BBOX` computation for `osmfr` extracts, as described in https://github.com/openmaptiles/openmaptiles-tools/pull/297#issuecomment-700792702

#### Currently
- If the user does not do anything, `quickstart.sh` and `make generate-tiles` create an `mbtiles` file for the full extent of the data source. This applies to `planet` and other data sources.
- If a user sets the `BBOX` value in `.env` and a `planet` data source is used, `quickstart.sh` and `make generate-tiles` create an `mbtiles` file for the extent set in the `.env` file.
- If a user sets the `BBOX` value in `.env` and a non-`planet` data source is used, it is ignored - `quickstart.sh` and `make generate-tiles` create an `mbtiles` file for the full extent of the data source.

#### Problem statement
While users of a `planet` data source have a simple way to override the default extend of the tile generation, users of other data sources have no simple way of doing that. In fact, for such users the `BBOX` setting in the `.env` file is ignored and therefore misleading.

#### Proposal
- If the user does not do anything, `quickstart.sh` and `make generate-tiles` create an `mbtiles` file for the full extent of the data source. This applies to `planet` and other data sources.
- If a user sets the `BBOX` value in `.env`, `quickstart.sh` and `make generate-tiles` create an `mbtiles` file for the extent set in the `.env` file. This applies to `planet` and other data sources.
2020-10-15 11:38:11 +03:00
Eva Jelinkova
341c4df171
Brunnel changes in transportation and transportation_name layers (#1027)
https://github.com/openmaptiles/openmaptiles/issues/999

- Point 1 solved only partially - there is `brunnel` value added into zooms 9, 10, 11. For zooms 8 and smaller it would need change in osm_transportation_merge_ tables - I am going to try it but maybe its SQL costs will be to high.

- Point 2 solved.
2020-10-14 15:26:43 +03:00
Tomas Pohanka
b7429ce6f5
union ocean regular squares into complex polygon (#1021)
The ocean layer (table osm_ocean_polygon insert by `make import-data`) is made from squares that have a 10m buffer. 

This creates extra geometry in vector tiles as:

Union of full ocean squares should decrease the size of the water layer.

there are 8042 polygons (squares, 5 points, more then 100km<sup>2</sup>), which was reduced to 22 polygons - 1184kB vs 40kB respectively. 

In mbtiles should be the size reduction even more significant, due to the creation of more polygons based on a 10m buffer of each square.
2020-10-14 14:56:04 +03:00
Tomas Pohanka
72165933be
add ST_IsValid where ST_PointOnSurface (#1025)
Same as #1015 for another ST_PointOnSurface
2020-10-13 16:28:20 +03:00
Tomas Pohanka
88c13f713f
Korean and Japanese Latin (#1026)
Korean moved from `ko_rm` to `ko-Latn`. Same as Japanese deprecated `ja_rm` in advance of `ja-Latn`, but still have twice more records. For Japanese add Hiragana form.

fix #537 
listed in #930
2020-10-13 15:52:15 +03:00
Frédéric Rodrigo
cfc243e848
Add protocol to postserve --serve paramter (#1007)
The current option of postserve in the docker-compose produce an invalid tilejson.
```json
"tiles": ["localhost:8090/tiles/{z}/{x}/{y}.pbf"]
```
`tiles` should be URL. The protocol is missing.

Not sure about the best way to fix this. Just adding `http://` to the docker-compose.yaml does not allow https usage. But setting protocol in `OMT_HOST` seems weird.

Could add an extra OMT_PROTOCOL with `http` as default.
2020-10-12 16:45:09 +03:00
Eva Jelinkova
7a7e9326b9
adding ST_IsValid to housnumber geometry (#1015)
Adding check of geometry in layers/housenumber/housenumber_centroid.sql.
2020-10-12 15:05:20 +03:00
Eva Jelinkova
3d21523fbe
aerialway class for the transportation layer (#1011)
Co-authored-by: Tomas Pohanka <TomPohys@gmail.com>
2020-10-12 12:44:33 +02:00
Frédéric Rodrigo
36b7533d3b
Add timers to trigger function (#1006)
Add timer to all trigger refresh functions to help point where the time is spend on update.
2020-10-08 16:57:16 +03:00
zstadler
e8bf4aa94a
Update makefile for hierarchical area names (#1009)
- Use `find` instead of `wildcard` to detect existing `.osm.pbf` files
- Use `patsubst` to extract an `area` from a filename
- Clarify messssage, especially for errors

Resolve https://github.com/openmaptiles/openmaptiles/issues/1008
2020-10-01 08:10:01 +03:00
Frédéric Rodrigo
883a997dcf
Remove large unused index osm_highway_linestring_highway_idx (#1002)
The index `osm_highway_linestring_highway_idx` is not used. There is also a used partial index `osm_highway_linestring_highway_partial_idx`.

I cross check the usage of the index from postgres query stats and all SQL query code where the table `osm_highway_linestring` is refered.

This index is relatively big.
2020-09-30 11:30:18 +03:00
Frédéric Rodrigo
a3ce04fe23
Add landuse=salt_pond as water (#1000)
Add salt pond as water.

Most of salt pond are already tagged with natural=water even if it's not required. So the load added by this tag is very light.
2020-09-29 07:53:35 +03:00
zstadler
424c4ee8a3
Remove workaround for quickstart.sh (#998) 2020-09-28 22:28:34 +03:00
Frédéric Rodrigo
c8f919e9d6
Better update of osm_important_waterway_linestring, use frist and last version of osm object (#997)
Current implementation of osm_important_waterway_linestring have two bugs:
* The distinct on is_old keep the oldest version of the old object, and the oldest version of the new object, but need the last version of the new object.
* Delete the old version of the object and rebuild the using the new version of the object. But we need to remove matchings the old and the new version of the object, then rebuild the two.

Then only delete and update using first and last version of the object, intermediate versions are ignored.

Similar implementation of what is done in #996.
2020-09-28 17:07:37 +03:00
Frédéric Rodrigo
8bb77b67a1
Diff update osm transportation name network linestring (#996)
Replacing materialized view by a tables with update from trigger on change only.

Differential update of `osm_transportation_name_linestring`, `osm_transportation_name_linestring` and `osm_transportation_name_linestring_genX`).

At the end of the transaction the dependent rows are updated.

The goal is to update more quickly the content of derivated tables by just updating the changing content. It replaces the update of materialized view because their need a full recompute (with lock issue).

It is the last part of the replacement of materialized view for the transportation layer.

It addresses #814 and a part of #809.
2020-09-28 15:56:10 +03:00
Frédéric Rodrigo
47cdfc2c8b
Move where condition from osm_transportation_name_linestring to materialized view osm_transportation_name_network (fix) (#993)
On PR #991 the differential update was not updated like the main code.

Make similar change to the update code.
2020-09-23 11:10:59 +03:00
zstadler
d8b5e8e82d
openmaptiles-tools: consider MIN_ZOOM/MAX_ZOOM env (#992)
Allow MIN_ZOOM, and MAX_ZOOM to be overwritten from shell for `quickstart.sh`, `make generate-dc-config`, and other `docker-compose openmaptiles-tools` uses.

For example,
```
export MAX_ZOOM=14; ./quickstart.sh monaco
```
ignores the `MAX_ZOOM=14` environment variable and uses the `MAX_ZOOM=7` value from `.env` file

This PR will also make this code unecessary
5c640daf4f/.github/workflows/tests.yml (L26-L28)
2020-09-23 10:09:22 +03:00
swiss-knight
0245b21634
NOOP: Minor Makefile clean up (#994)
Minor fix.
2020-09-22 11:27:45 +03:00
Eva Jelinkova
f7d7a0ced3
Housenumbers - diff update, multipolygons (#990)
Following https://github.com/openmaptiles/openmaptiles/pull/983 - removing points also on multipolygons and checking only new geometry when updated.
2020-09-21 14:47:55 +03:00
zstadler
45f5b53c9c
Stitch transportation_name by all language tags (#989)
When OSM roads in the `transportation_name` layer are stitched together, their grouping does not consider all `name:*` tags.
As a result, roads with different `name:*` tags may be stitched together.

The `waterway` layer performs the grouping properly, for the same purpose:
1685eaccbd/layers/waterway/update_important_waterway.sql (L34)

Co-authored-by: Frédéric Rodrigo <fred.rodrigo@gmail.com>
2020-09-21 12:38:13 +03:00
Frédéric Rodrigo
5c640daf4f
Move where condition from osm_transportation_name_linestring to materialized view osm_transportation_name_network (#991)
Reduce the size of the materialized view osm_transportation_name_network by moving the weare clause.
osm_transportation_name_network is only used for osm_transportation_name_linestring.

Co-authored-by: zstadler <zeev.stadler@gmail.com>
2020-09-21 10:02:20 +03:00
Frédéric Rodrigo
550b1f8f90
Replace materialized view osm_transportation_name_network by a table with diff update (#987)
Replacing materialized view by a tables with update from trigger on change only.

The osm_id of object changing on table osm_route_member and osm_highway_linestring are logged.
At the end of the transaction the dependent row of osm_transportation_name_network are updated.

The goal is to update more quickly the content of derivated tables by just updating the changing content. It replaces the update of materialized view because their need a full recompute (with lock issue).

Note, it is only a part of the materialized view of the transportation layer, I am also working on the other parts, other parts are in #892 (omaterialized view on sm_transportation_name_linestring and osm_transportation_name_linestring_genX).

It addresses #814 and a part of #809.
2020-09-18 16:49:55 +03:00
Taro Matsuzawa aka. btm
1685eaccbd
#766 remove housenumbers inside polygon and same number (#983) 2020-09-16 17:06:48 +02:00
zstadler
fb7c1ef42b
Update Makefile (#984)
Update `make help` according to #750
2020-09-15 08:18:18 +03:00
zstadler
c82c706bc3
Clean output of list-views and list-table (#985)
Avoid printing a fixed `public,` prefix in the output of `make list-views` and `make list-table`.
As `make help` says, `list-views` and `list-table` list only the public schema views and tables.

New output:

```
viewname
boundary_z0
boundary_z1
boundary_z10
boundary_z11
boundary_z12
boundary_z13
boundary_z3
boundary_z4
boundary_z5
boundary_z6
boundary_z7
boundary_z8
boundary_z9
geography_columns
geometry_columns
...
```

Existing output:

```
schemaname,viewname
public,boundary_z0
public,boundary_z1
public,boundary_z10
public,boundary_z11
public,boundary_z12
public,boundary_z13
public,boundary_z3
public,boundary_z4
public,boundary_z5
public,boundary_z6
public,boundary_z7
public,boundary_z8
public,boundary_z9
public,geography_columns
public,geometry_columns
...
```
2020-09-14 15:07:35 -04:00
Frédéric Rodrigo
df56b75719
Clean update_route_member.sql (#981)
Clean and do refactoring on `update_route_member.sql` as first step to replace materialized view osm_transportation_name_network by tables with diff update. See #892.
2020-09-14 19:13:32 +03:00
Taro Matsuzawa aka. btm
7b2df3b64f
write how to generate dc-config (#982)
Added document about how to generate dc-config in QUICKSTART.md.
2020-09-14 18:20:24 +03:00
Jorge Sanz
bd444c0d1a
Show more state borders at low zoom levels (#979)
* Change NE 50m by NE 10m state provinces dataset

* update documentation

Fixes #977 

This PR implements the change discussed at #977 to replace Natural Earth 10m states and provinces by the 50m version, since the 10m only covers state borders for US, Canada, Brazil, and Australia.

A few remarks:

* This change only affects zooms 1 to 4, not making any change in borders based in the `OSM Borders`  source. 
* The `min_zoom<=7` shows the first level regions (level 4 in OSM) as you can check for example for France, Italy, or Spain.
* I don't think it's necessary to simplify the geometries, it would mean adding a new materialized view, or a slower tile generation process.
* This change does not need any change in the styles, even someone could argue it could be interesting to add the country code in this layer as a new field, allowing style editors to filter features by country, but I would prefer to leave that change for another PR.
2020-09-10 09:41:43 +03:00
Eva Jelinkova
1356d724d4
adding disputed_name to NE sources (#976)
`disputed_name` is filled for disputed lines of NaturalEarth sources - it contains `ogc_fid` as suggested in https://github.com/openmaptiles/openmaptiles/issues/964. This way it is possible to filter disputed lines in style.
2020-09-03 21:09:15 +03:00
zstadler
de95843e02
Allow setting TILESET_FILE by shell or Makefile (#975)
Following the 10efc29280 (r41977444) comment
2020-09-02 13:14:55 -04:00
Jorge Sanz
194b2fbb70
Add state labels at low zoom levels (#969)
* Remove state labels zoom, rank, and country conditions from layer function

* Don't add labels for zooms 0 and 1

If we check Bright, Positron, or Dark styles, they all show a huge lack of data about states and regions. At zoom 2, for big countries like Canada, Brazil, China or Australia there are big patches of white space (aka cartographer's *horror vacui* 😅)
2020-09-02 09:02:43 +03:00
David Zhao
a4671b84f0
Expose COPY_CONCURRENCY to users (#972)
Allow users to override how the number of threads used when generating map vector tiles.
2020-09-01 14:46:53 +03:00
naveenkumar
4807ccee24
adding hi(hindi),ta(tamil) and te(telugu) language (#973) 2020-09-01 12:25:17 +03:00
Frédéric Rodrigo
04d1b66e67
Incremental update marine point (#952)
Replacing update on the whole table with an update only on changed rows.

The goal is to update more quickly by just updating the changing content.
The update now focus on osm_id of changed rows, it use index. Add a where clause tags != update_tags(tags, geometry) to ensure only update when changed.

It requires one more trigger and a table to store changed osm_id.

The UPDATE is keep in a function to be reusable for initial setup and trigger update.

It is a based on the already merged https://github.com/openmaptiles/openmaptiles/pull/944

It is a separated PR as less obvious than previous. It replaces the reset of the `rank` field to NULL by missing value resulting of `LEFT JOIN`. It avoid triggering a new update on the table by reset the value then re-seting it to initial or new value.

It addresses #814.

Thanks @frodrigo
2020-08-30 16:16:54 +03:00
Frédéric Rodrigo
82616eaac0
Make update_city_point use incremental update #814 (#951)
Replacing update on the whole table with an update only on changed rows.

The goal is to update more quickly by just updating the changing content.
The update now focus on osm_id of changed rows, it use index. Add a where clause tags != update_tags(tags, geometry) to ensure only update when changed.

It requires one more trigger and a table to store changed osm_id.

The UPDATE is keep in a function to be reusable for initial setup and trigger update.

It is a based on the already merged https://github.com/openmaptiles/openmaptiles/pull/944

It is a separated PR as less obvious than previous. It replaces the reset of the `rank` field to NULL by missing value resulting of `LEFT JOIN`. It avoid triggering a new update on the table by reset the value then re-seting it to initial or new value.

It addresses #814.

Thanks @frodrigo
2020-08-30 15:29:50 +03:00
Frédéric Rodrigo
bb2a4328f3
Make more simple incremental update (#944)
Replacing update on the whole table with an update only on changed rows.

The goal is to update more quickly by just updating the changing content.
The update now focus on osm_id of changed rows, it use index. Add a where clause tags != update_tags(tags, geometry) en ensure only update when changed.

It requires one more trigger and a table to store changed osm_id.

The UPDATE is keep in a function to be reusable for initial setup and trigger update.

I try many code layout before done it in this way with the goal to keep the code for initial pass and for update. It should have low impact on initial data load. Better performance for row update can be achieve with BEFORE UPDATE, but require to duplicate the logic.

It is not based on the already merged https://github.com/openmaptiles/openmaptiles/pull/896 because calling and update within a function for each updated row was not efficient for larger table (like housenumber).

It addresses #814.


* Remake update_peak_point use incremental update #814

* Make update_aerodrome_label_point use incremental update #814

* Make housenumber_centroid use incremental update #814

* Make update_continent_point use incremental update #814

* Make update_island_point use incremental update #814

* Make update_island_polygon use incremental update #814

* Remove dead code in update_state_point.sql

* Make update_state_point use incremental update #814

* Remove dead code in update_country_point.sql

* Make update_country_point use incremental update #814

* Make osm_poi_polygon use incremental update #814

Thanks @frodrigo
2020-08-28 11:03:27 +02:00
Frédéric Rodrigo
10efc29280
Make tileset def openmaptiles.yaml a variable (#968)
Move the hard coded `openmaptiles.yaml` from Makefile to a variable. Allows use other tileset definition.
A step forward easy alternative layer definition.
2020-08-27 12:43:09 -04:00
1d39075f03 Further refinement 2020-08-11 01:24:55 +02:00
df3f592513 Refinements in POI_Ranking 2020-08-10 22:53:19 +02:00
14238e9863 Attempt at cleaning up the excessive office/industrial POIs, and cleaning up the subtype code while we're at it. (SQL bugs likely) 2020-08-10 18:24:23 +02:00
c121c69a66 Fixed SQL and mapping bugs. 2020-08-10 17:41:59 +02:00
3dd9ccb551 Bugfix, missed second invocation of poi_class. Should find a proper place to precalculate subtype 2020-08-10 16:37:19 +02:00
52c91af85c Merge remote-tracking branch 'origin/master' 2020-08-10 15:45:35 +02:00
d6485e7dd5 Reworked the POI mapping so that a subtype is available. Needed for wind_turbine, but might also prove useful later. 2020-08-10 15:45:30 +02:00
zstadler
1daacf354e
Use line buffering by awk in make import-sql (#962)
Resolve https://github.com/openmaptiles/openmaptiles/issues/958
2020-08-10 10:41:14 +02:00
root
fe4ea645e9 Make test.sh executable.. 2020-08-09 18:46:53 +02:00
08e4e8b0bb Another attempted fix for wind_turbines 2020-08-09 18:45:50 +02:00
b5b34e1d09 Fixed wind-turbine 2020-08-09 15:31:03 +02:00
323e0dc8f6 Bugfix 2020-08-09 15:04:03 +02:00
c030eaa7be Refinements 2020-08-09 13:41:37 +02:00
c092dd360c Cleaned up more code from landmark that wasn't used. Experimenting with power generator:source stuff 2020-08-08 22:08:02 +02:00
bd1325109a Cleaned up more code from landmark that wasn't used. Experimenting with power generator:source stuff 2020-08-08 21:24:00 +02:00
277829f9a0 Fix SQL error. (eventually..) 2020-08-08 14:55:04 +02:00
cbe2ef41c4 Fix SQL error. (someday we'll get it right...) 2020-08-08 14:06:41 +02:00
58ce31b809 Fix SQL error 2020-08-08 13:07:02 +02:00
0ee30f3840 Fix SQL error 2020-08-08 00:57:26 +02:00
f3b680e143 Refined 2020-08-07 18:24:19 +02:00
029d755ea1 Added landuse for bicycle and motorcycle parkings, split up some POIs and added some (to be aligned with the iconset!) 2020-08-07 15:38:32 +02:00
Frédéric Rodrigo
232379b3ca
Do insensitive case compare using lower() and not ILIKE (#961)
* Replace ILIKE by lower() for insensitive case compare

* Refactoring SQL insensitive case compare
2020-08-06 09:14:47 +02:00
zstadler
6a512af90f
Special cache handling for Docker Toolbox on Windows (#957)
resolves https://github.com/openmaptiles/openmaptiles/issues/807
2020-08-03 18:12:09 +02:00
zstadler
751551f910
Add $OMT_HOST support to make start-postserve (#956)
Resolve https://github.com/openmaptiles/openmaptiles/issues/955
2020-07-28 18:28:04 +02:00
zstadler
897846380a
Rephrase area detection messages (#954)
Thanks @zstadler.
2020-07-28 07:25:52 +02:00
Frédéric Rodrigo
9bb17792a6
Remove alignment of AS in SQL and few others (#932)
* Remove alignment of AS in SQL

* Remove alignment of CREATE TABLE in SQL
2020-07-22 13:48:25 +02:00
Frédéric Rodrigo
13aaa404d9
Fix More fail safe incremental update on water_lakeline and water_point (#949) (#950) 2020-07-22 12:17:33 +02:00
Frédéric Rodrigo
098f2d1ce2
Fix peak doc (#941) 2020-07-21 18:05:46 +02:00
Frédéric Rodrigo
dd1b2d3b15
More fail safe incremental update on water_lakeline and water_point (#949)
Improve 97216c5c191bf0df3705134cff234ed980f8ac78 and #853

In case of replay update it may fails because of already existing primary key on osm_id.

Add a on conflict clause to make it fail safe.
2020-07-21 17:35:49 +02:00
1915af7542 Fixing errors #2 2020-07-03 17:47:43 +02:00
6782ed5f63 Fixing errors #1 2020-07-03 17:16:01 +02:00
d638b3ef17 Initial attempt at moving forests with names into their own 'landmarks' layer. (this is heavely copied and pasted from POI) 2020-07-03 15:23:51 +02:00
58d997b3ea Lesson learned: it was not related to landuse-changes... 2020-07-03 01:32:15 +02:00
c3cb7ef43f Everything landuse related seemed to be broken, validating the cause of it:
Revert "Added POIs"

This reverts commit 0b18f340
2020-07-02 19:26:57 +02:00
bcb1c905c7 Revert "Testing addition of landuse.name"
This reverts commit 3994345d
2020-07-02 15:59:18 +02:00
0b18f340ae Added POIs 2020-07-02 15:58:59 +02:00
3994345d27 Testing addition of landuse.name 2020-07-02 15:32:22 +02:00
566f4c47d5 Merge remote-tracking branch 'github/master'
# Conflicts:
#	Makefile
2020-07-01 15:18:59 +02:00
7519c5889f removed quotation marks 2020-07-01 15:14:17 +02:00
0cee7fd6fc Make DC User and Password configurable 2020-07-01 14:45:12 +02:00
5208f1adbd Make DC User and Password configurable 2020-07-01 14:41:18 +02:00
Tomas Pohanka
c86f4a557a
Build aggregation on zoom level 13 (#936)
* Building aggregation at zoom 13
2020-06-18 14:01:06 +02:00
Frédéric Rodrigo
6ac544fc96
Make update_osm_peak_point use incremental update #814 (#896)
Thanks a lot @frodrigo.
2020-06-17 19:58:12 +02:00
Yuri Astrakhan
2b95d1cffa
Fix & optimize incorrect function declarations (#918)
* All functions that access database must be declared as `STABLE`, not `IMMUTABLE` -- because database can change at any moment, e.g. during an update
* there are a few functions that could be made `STRICT` -- passing `NULL` as a parameter will always result in a `NULL`, but for some reason that causes a significant decrease in perf.
* tagged one function as parallel safe

NOTE: somehow `ST_AsMVT()` method of tile generation is showing 70-90% slowdown with this patch. I am not sure of why this is happening. If the reason is the `IMMUTABLE` -> `STABLE` change, we may have to dig deeper into PG optimization
2020-06-17 12:15:26 -04:00
Yuri Astrakhan
ad8bd41567
Do not wait for integrity test (#934)
It's ok if integrity test fails -- makes the whole testing process faster by 10 minutes at a cost of some extra CPU cycles.
2020-06-14 11:02:44 -04:00
Tomas Pohanka
8f31655564
Change GitHub Actions to dedicated server (#929)
* Change GitHub Action to the dedicated server Ralph

* bugfix - let quickstart generate-tiles up to zoom 14
2020-06-12 11:04:33 +02:00
Yuri Astrakhan
f889853cb6
aerodrome_label: Remove unused function parameter (#919)
Minor optimization - in function `layer_aerodrome_label(bbox, zoom_level, pixel_width)` last parameter is not being used, so removing.
2020-06-11 14:24:55 -04:00
Yuri Astrakhan
447a8380e0
Fix incorrect Imposm config updates (#922)
* Current code incorrectly passes `IMPOSM_CONFIG_FILE` to the `generate-tiles` image, but should pass it to the tools.
* add a test to ensure imposm config exists
* add a test to ensure area is set during updates
2020-06-09 10:00:10 -04:00
Yuri Astrakhan
491bb10bd7
Expose MAX_PARALLEL_PSQL to users (#927)
Allow users to override how many import-sql files are loaded in parallel at the same time.

This change should be a noop
2020-06-09 09:53:02 -04:00
zstadler
5e65ac8c52
Add area-base filtering for park names in lower zoom levels (#911)
Resolve https://github.com/openmaptiles/openmaptiles/issues/776

Thanks @zstadler for this PR.
2020-06-09 10:53:18 +02:00
zstadler
ffd237d5c8
Fix clean-unnecessary-docker make target (#921)
Add missing `-q` flag
2020-06-08 12:40:04 -04:00
Yuri Astrakhan
0b1511d60d
NOOP water - Move updating sql into separate file (#920)
Use `update_water.sql` for all queries that update db
to be consistent with the other layers.
2020-06-08 12:32:09 -04:00
Yuri Astrakhan
60a3e1ea70
Fix Makefile duplicate runs (#923)
Make sure that core targets (i.e. part of the `all` target like build-sql and build yaml files) do not run multiple times if they already exist.

Makefile for some reason does not like it when a real target depends on a PHONY target, and re-runs it. I added an `if` statement to skip building targets if their result already exists.
2020-06-08 12:26:11 -04:00
Yuri Astrakhan
6457419e0d
NOOP: Format all layer's SQL code (#917)
I would like to reformat all of our SQL to have a concise coding style.
This makes it far easier to understand the code for a casual contributor,
and lets us spot errors more easily.

Most importantly, it makes it much easier to grep (search) the code because it is more likely to be in the same syntax

Some key changes:
* SQL keywords are always UPPERCASE, e.g. `SELECT WHEN AS END ...`
* types, variables, aliases, and field names (identifiers) are always lower case
* `LANGUAGE 'plpgsql'` is now `LANGUAGE plpgsql` (no quotes)
* a few minor spacing/semicolon cleanups

P.S. Per @TomPohys request, `TABLE` is spelled using upper case despite being a type for consistency with PG Docs. Same for `LANGUAGE SQL` vs `LANGUAGE plpgsql`.
2020-06-08 12:19:55 -04:00
Yuri Astrakhan
805d95df09
Fix import-borders if runs multiple times (#916)
Running './quickstart monaco' twice in a row will cause an error the second time.
2020-06-05 12:48:48 -04:00
Yuri Astrakhan
1a9f6132c3
New generate-dc-config target, rm QUICKSTART_MIN/MAX_ZOOM (#915)
* Set `MAX_ZOOM` to 7 by default.
* Remove `QUICKSTART_MIN/MAX_ZOOM` - unneeded complexity with two env vars. We can just use `MIN_ZOOM` and `MAX_ZOOM`. See also #261
* Generate dc-config yaml file with a new `make generate-dc-config` step. It will compute BBOX based on the downloaded data file. This step is not needed for planet generation.
* Generate Imposm replication file only when `DIFF_MODE` is `true`. Not needed otherwise. If the data source does not support it, it will throw an error.
2020-06-04 15:45:04 -04:00
Yuri Astrakhan
1486b7e0cb
Rework download area support (#908)
Closes #904
* Make all data-related targets like `download*`, `import-osm`, `import-borders`, and `generate-tiles` into `area`-aware -- making it possible for multiple data files to coexist inside the `./data` dir.
* Add `make download area=... [url=...]` command to automatically download any kind of area by checking Geofabrik, BBBike, and OSM.fr, optionally from a custom URL. Supports `area=planet` too.
* Do not re-download area with `make download-*` if it already exists.
* Automatically rename `<area>-latest.osm.pbf` into `<area>.osm.pbf`
* If `area=...` parameter is not given to `make`, see if there is exactly one `*.osm.pbf` file, and if so, use `*` as the `area`.
* Configure many variables in the .env file, overriding the defaults in tools
* If `<area>.osm.pbf` exists, but `<area>.dc-config.pbf` is missing, generate it using `download-osm make-dc` command.

Also:
* closes #614
* closes #647
* partially addresses #261
2020-06-03 15:37:45 -04:00
Yuri Astrakhan
fca53ef0ee
Minor makefile/quickstart cleanup (#907)
* Make a few spacing adjustments for ease-of-reading and consistency
* fix bbbike naming and other source urls
* remove unneeded `override`
* added `list-bbbike` target
2020-06-01 12:54:30 -04:00
Yuri Astrakhan
546f26e68a
MVT: use gzip and generate for v3.0 (#906)
This only changes the generated `getmvt(...)` function used by mvt users.

Beginning with tools 5.1, postgis docker images uses postgis v3.0, and includes gzip extension
2020-06-01 12:46:34 -04:00
Yuri Astrakhan
1a31b9212e
Minor fix import-borders file param (#905)
just like import-osm, import-borders can accept PBF_FILE param
2020-06-01 12:33:26 -04:00
Yuri Astrakhan
907fc58ee2
Use tools v5.2 (#903)
* Use [tools v5.2](https://github.com/openmaptiles/openmaptiles-tools/releases/tag/v5.2.0)
* Use `mbtiles-tools meta-generate` instead of the removed `generate-metadata` script.
* Remove `show-metadata` make target - it was just added and is not needed.

## Relevant changes
* Upgrade [osml10n PG extension](https://github.com/giggls/mapnik-german-l10n) to the faster v2.5.9 (significant performance improvements merged upstream by @nyurik)
2020-06-01 12:15:36 -04:00
124 changed files with 8749 additions and 4321 deletions

41
.env
View File

@ -1,7 +1,10 @@
# This file defines default environment variables for all images # This file defines default environment variables for all images
# Layers definition and meta data
TILESET_FILE=openmaptiles.yaml
# Use 3-part patch version to ignore patch updates, e.g. 5.0.0 # Use 3-part patch version to ignore patch updates, e.g. 5.0.0
TOOLS_VERSION=5.1 TOOLS_VERSION=5.3
# Make sure these values are in sync with the ones in .env-postgres file # Make sure these values are in sync with the ones in .env-postgres file
PGDATABASE=openmaptiles PGDATABASE=openmaptiles
@ -10,13 +13,17 @@ PGPASSWORD=openmaptiles
PGHOST=postgres PGHOST=postgres
PGPORT=5432 PGPORT=5432
QUICKSTART_MIN_ZOOM=0 # BBOX may get overwritten by the computed bbox of the specific area:
QUICKSTART_MAX_ZOOM=7 # make generate-bbox-file
DIFF_MODE=false # By default, the Makefile will use the content of data/$(area).bbox file if it exists.
BBOX=-180.0,-85.0511,180.0,85.0511 BBOX=-180.0,-85.0511,180.0,85.0511
# Which zooms to generate in make generate-tiles
MIN_ZOOM=0 MIN_ZOOM=0
MAX_ZOOM=14 MAX_ZOOM=7
# Use true (case sensitive) to allow data updates
DIFF_MODE=false
# Hide some output from Mapnik tile generation for clarity # Hide some output from Mapnik tile generation for clarity
FILTER_MAPNIK_OUTPUT=1 FILTER_MAPNIK_OUTPUT=1
@ -24,3 +31,25 @@ FILTER_MAPNIK_OUTPUT=1
# Some area data like openstreetmap.fr can contain invalid references # Some area data like openstreetmap.fr can contain invalid references
# that must be cleaned up before using it for borders -- set it to true. # that must be cleaned up before using it for borders -- set it to true.
BORDERS_CLEANUP=false BORDERS_CLEANUP=false
# The current setup assumes this file is placed inside the data/ dir
MBTILES_FILE=tiles.mbtiles
# This is the current repl_config.json location, pre-configured in the tools Dockerfile
# Makefile and quickstart replace it with the dynamically generated one, but we keep it here in case some other method is used to run.
IMPOSM_CONFIG_FILE=/usr/src/app/config/repl_config.json
# import-borders temp files - set them here to defaults, and override in the Makefile based on the area
BORDERS_CLEANUP_FILE=data/borders/cleanup.pbf
BORDERS_PBF_FILE=data/borders/filtered.pbf
BORDERS_CSV_FILE=data/borders/lines.csv
# Number of parallel processes to use when importing sql files
MAX_PARALLEL_PSQL=5
# Number of parallel threads to use when generating vector map tiles
COPY_CONCURRENCY=10
# Variables for generate tiles using PGquery
PGHOSTS_LIST=
NO_GZIP=1
USE_KEY_COLUMN=1

View File

@ -20,13 +20,10 @@ jobs:
- name: Run quickstart for a small area - name: Run quickstart for a small area
env: env:
area: monaco area: monaco
QUICKSTART_MIN_ZOOM: 0 MIN_ZOOM: 0
QUICKSTART_MAX_ZOOM: 14 MAX_ZOOM: 14
QUIET: 1
run: | run: |
# For now, change the quickstart values directly in the .env file
# TODO: We should probably use env vars instead
sed -i 's/QUICKSTART_MAX_ZOOM=7/QUICKSTART_MAX_ZOOM=14/g' .env
export QUIET=1
./quickstart.sh $area ./quickstart.sh $area
- name: Save quickstart.log - name: Save quickstart.log
@ -42,10 +39,7 @@ jobs:
performance: performance:
name: Evaluate performance name: Evaluate performance
runs-on: ubuntu-latest runs-on: self-hosted
# Even though we technically don't need to wait for integrity test to finish,
# there is no point to run long perf test until we know the code is OK
needs: integrity_test
env: env:
## Smaller tests (runs everything in about 30 minutes) ## Smaller tests (runs everything in about 30 minutes)
## Two test areas: equatorial-guinea and liechtenstein ## Two test areas: equatorial-guinea and liechtenstein
@ -109,7 +103,7 @@ jobs:
with: with:
path: perf_cache path: perf_cache
# If profiling result cache has incompatible format, increase this "v" number # If profiling result cache has incompatible format, increase this "v" number
key: "v11-${{ steps.calc.outputs.hash }}-${{ env.TEST_DATA_URL }}" key: "v12-${{ steps.calc.outputs.hash }}-${{ env.TEST_DATA_URL }}"
- name: Load test data into DB and run performance test - name: Load test data into DB and run performance test
id: main id: main
@ -173,7 +167,7 @@ jobs:
create_db() { create_db() {
make clean make clean
make init-dirs make init-dirs
cp ../ci_cache/perf-test-areas-latest.osm.pbf data/perf-test-areas-latest.osm.pbf cp ../ci_cache/perf-test-areas-latest.osm.pbf data/perf-test-areas.osm.pbf
make destroy-db make destroy-db
make all make all
make start-db make start-db

372
Makefile
View File

@ -1,41 +1,51 @@
#
# First section - common variable initialization
#
# Ensure that errors don't hide inside pipes # Ensure that errors don't hide inside pipes
SHELL = /bin/bash SHELL = /bin/bash
.SHELLFLAGS = -o pipefail -c .SHELLFLAGS = -o pipefail -c
# Make all .env variables available for make targets
include .env
# Layers definition and meta data
TILESET_FILE ?= openmaptiles.yaml
# Options to run with docker and docker-compose - ensure the container is destroyed on exit # Options to run with docker and docker-compose - ensure the container is destroyed on exit
# Containers run as the current user rather than root (so that created files are not root-owned) # Containers run as the current user rather than root (so that created files are not root-owned)
DC_OPTS?=--rm -u $(shell id -u):$(shell id -g) DC_OPTS ?= --rm --user=$(shell id -u):$(shell id -g)
DC_USER?=openmaptiles
DC_PASSWORD?=openmaptiles
# If set to a non-empty value, will use postgis-preloaded instead of postgis docker image # If set to a non-empty value, will use postgis-preloaded instead of postgis docker image
USE_PRELOADED_IMAGE?= USE_PRELOADED_IMAGE ?=
# If set, this file will be imported in the import-osm target
PBF_FILE?=
# Local port to use with postserve # Local port to use with postserve
PPORT?=8090 PPORT ?= 8090
export PPORT export PPORT
# Local port to use with tileserver # Local port to use with tileserver
TPORT?=8081 TPORT ?= 8081
export TPORT export TPORT
# Allow a custom docker-compose project name # Allow a custom docker-compose project name
ifeq ($(strip $(DC_PROJECT)),) ifeq ($(strip $(DC_PROJECT)),)
override DC_PROJECT:=$(notdir $(shell pwd)) DC_PROJECT := $(notdir $(shell pwd))
DOCKER_COMPOSE:= docker-compose DOCKER_COMPOSE := docker-compose
else else
DOCKER_COMPOSE:= docker-compose --project-name $(DC_PROJECT) DOCKER_COMPOSE := docker-compose --project-name $(DC_PROJECT)
endif endif
# Make some operations quieter (e.g. inside the test script) # Make some operations quieter (e.g. inside the test script)
ifeq ($(strip $(QUIET)),) ifeq ($(strip $(QUIET)),)
QUIET_FLAG:= QUIET_FLAG :=
else else
QUIET_FLAG:=--quiet QUIET_FLAG := --quiet
endif endif
# Use `xargs --no-run-if-empty` flag, if supported # Use `xargs --no-run-if-empty` flag, if supported
XARGS:=xargs $(shell xargs --no-run-if-empty </dev/null 2>/dev/null && echo --no-run-if-empty) XARGS := xargs $(shell xargs --no-run-if-empty </dev/null 2>/dev/null && echo --no-run-if-empty)
# If running in the test mode, compare files rather than copy them # If running in the test mode, compare files rather than copy them
TEST_MODE?=no TEST_MODE?=no
@ -47,12 +57,139 @@ else
GRAPH_PARAMS=./layers GRAPH_PARAMS=./layers
endif endif
# Set OpenMapTiles host
OMT_HOST := http://$(firstword $(subst :, ,$(subst tcp://,,$(DOCKER_HOST))) localhost)
export OMT_HOST
# This defines an easy $(newline) value to act as a "\n". Make sure to keep exactly two empty lines after newline.
define newline
endef
#
# Determine area to work on
# If $(area) parameter is not set, and only one *.osm.pbf file is found in ./data, use it as $(area).
# Otherwise, all make targets requiring an area will show an error.
# Note: If no *.osm.pbf files are found, once the users call "make download area=..."
# they will not need to use an "area=" parameter again because there will be just a single file.
#
# historically we have been using $(area) rather than $(AREA), so make both work
area ?= $(AREA)
# Ensure the $(area) param is set, or try to automatically determine it based on available data files
ifeq ($(strip $(area)),)
# An $(area) parameter is not set. If only one *.osm.pbf file is found in ./data, use it as $(area).
data_files := $(shell find data -name '*.osm.pbf' 2>/dev/null)
ifneq ($(word 2,$(data_files)),)
define assert_area_is_given
@echo ""
@echo "ERROR: The 'area' parameter or environment variable have not been set, and there several 'area' options:"
@$(patsubst data/%.osm.pbf,echo " '%'";,$(data_files))
@echo ""
@echo "To specify an area use:"
@echo " make $@ area=<area-id>"
@echo ""
@exit 1
endef
else
ifeq ($(word 1,$(data_files)),)
define assert_area_is_given
@echo ""
@echo "ERROR: The 'area' parameter (or env var) has not been set, and there are no data/*.osm.pbf files"
@echo ""
@echo "To specify an area use"
@echo " make $@ area=<area-id>"
@echo ""
@echo "To download an area, use make download area=<area-id>"
@echo "To list downloadable areas, use make list-geofabrik and/or make list-bbbike"
@exit 1
@echo ""
endef
else
# Keep just the name of the data file, without the .osm.pbf extension
area := $(patsubst data/%.osm.pbf,%,$(data_files))
# Rename area-latest.osm.pbf to area.osm.pbf
# TODO: This if statement could be removed in a few months once everyone is using the file without the `-latest`?
ifneq ($(area),$(area:-latest=))
$(shell mv "data/$(area).osm.pbf" "data/$(area:-latest=).osm.pbf")
area := $(area:-latest=)
$(warning ATTENTION: File data/$(area)-latest.osm.pbf was renamed to $(area).osm.pbf.)
AREA_INFO := Detected area=$(area) based on finding a 'data/$(area)-latest.osm.pbf' file - renamed to '$(area).osm.pbf'. Use 'area' parameter or environment variable to override.
else
AREA_INFO := Detected area=$(area) based on finding a 'data/$(area).osm.pbf' file. Use 'area' parameter or environment variable to override.
endif
endif
endif
endif
ifneq ($(strip $(AREA_INFO)),)
define assert_area_is_given
@echo "$(AREA_INFO)"
endef
endif
# If set, this file will be downloaded in download-osm and imported in the import-osm targets
PBF_FILE ?= data/$(area).osm.pbf
# For download-osm, allow URL parameter to download file from a given URL. Area param must still be provided.
ifneq ($(strip $(url)),)
DOWNLOAD_AREA := $(url)
else
DOWNLOAD_AREA := $(area)
endif
# import-borders uses these temp files during border parsing/import
export BORDERS_CLEANUP_FILE ?= data/borders/$(area).cleanup.pbf
export BORDERS_PBF_FILE ?= data/borders/$(area).filtered.pbf
export BORDERS_CSV_FILE ?= data/borders/$(area).lines.csv
# The file is placed into the $EXPORT_DIR=/export (mapped to ./data)
export MBTILES_FILE ?= $(area).mbtiles
MBTILES_LOCAL_FILE = data/$(MBTILES_FILE)
ifeq ($(strip $(DIFF_MODE)),true)
# import-osm implementation requires IMPOSM_CONFIG_FILE to be set to a valid file
# For static (no-updates) import, we don't need to override the default value
# For the update mode, set location of the dynamically-generated area-based config file
export IMPOSM_CONFIG_FILE = data/$(area).repl.json
endif
# Load area-specific bbox file that gets generated by the download-osm --bbox
AREA_BBOX_FILE ?= data/$(area).bbox
ifneq (,$(wildcard $(AREA_BBOX_FILE)))
cat := $(if $(filter $(OS),Windows_NT),type,cat)
BBOX := $(shell $(cat) ${AREA_BBOX_FILE})
export BBOX
endif
ifeq ($(strip $(area)),)
define assert_area_is_given
@echo ""
@echo "ERROR: $(AREA_ERROR)"
@echo ""
@echo " make $@ area=<area-id>"
@echo ""
@echo "To download an area, use make download <area-id>"
@echo "To list downloadable areas, use make list-geofabrik and/or make list-bbbike"
@exit 1
endef
else
ifneq ($(strip $(AREA_INFO)),)
define assert_area_is_given
@echo "$(AREA_INFO)"
endef
endif
endif
#
# TARGETS
#
.PHONY: all .PHONY: all
all: init-dirs build/openmaptiles.tm2source/data.yml build/mapping.yaml build-sql all: init-dirs build/openmaptiles.tm2source/data.yml build/mapping.yaml build-sql
# Set OpenMapTiles host
OMT_HOST:=http://$(firstword $(subst :, ,$(subst tcp://,,$(DOCKER_HOST))) localhost)
.PHONY: help .PHONY: help
help: help:
@echo "==============================================================================" @echo "=============================================================================="
@ -63,20 +200,23 @@ help:
@echo " " @echo " "
@echo "Hints for designers:" @echo "Hints for designers:"
@echo " make start-maputnik # start Maputnik Editor + dynamic tile server [ see $(OMT_HOST):8088 ]" @echo " make start-maputnik # start Maputnik Editor + dynamic tile server [ see $(OMT_HOST):8088 ]"
@echo " make start-postserve # start dynamic tile server [ see $(OMT_HOST):$(PPORT)} ]" @echo " make start-postserve # start dynamic tile server [ see $(OMT_HOST):$(PPORT) ]"
@echo " make start-tileserver # start maptiler/tileserver-gl [ see $(OMT_HOST):$(TPORT) ]" @echo " make start-tileserver # start maptiler/tileserver-gl [ see $(OMT_HOST):$(TPORT) ]"
@echo " " @echo " "
@echo "Hints for developers:" @echo "Hints for developers:"
@echo " make # build source code" @echo " make # build source code"
@echo " make list-geofabrik # list actual geofabrik OSM extracts for download" @echo " make list-geofabrik # list actual geofabrik OSM extracts for download"
@echo " make download-geofabrik area=albania # download OSM data from geofabrik, and create config file" @echo " make list-bbbike # list actual BBBike OSM extracts for download"
@echo " make download-osmfr area=asia/qatar # download OSM data from openstreetmap.fr, and create config file" @echo " make download area=albania # download OSM data from any source and create config file"
@echo " make download-bbike area=Amsterdam # download OSM data from bbike.org, and create config file" @echo " make download-geofabrik area=albania # download OSM data from geofabrik.de and create config file"
@echo " make download-osmfr area=asia/qatar # download OSM data from openstreetmap.fr and create config file"
@echo " make download-bbbike area=Amsterdam # download OSM data from bbbike.org and create config file"
@echo " make generate-bbox-file # compute bounding box of a data file and store it in a file"
@echo " make psql # start PostgreSQL console" @echo " make psql # start PostgreSQL console"
@echo " make psql-list-tables # list all PostgreSQL tables" @echo " make psql-list-tables # list all PostgreSQL tables"
@echo " make vacuum-db # PostgreSQL: VACUUM ANALYZE" @echo " make vacuum-db # PostgreSQL: VACUUM ANALYZE"
@echo " make analyze-db # PostgreSQL: ANALYZE" @echo " make analyze-db # PostgreSQL: ANALYZE"
@echo " make generate-qareports # generate reports [./build/qareports]" @echo " make generate-qa # statistics for a given layer's field"
@echo " make generate-devdoc # generate devdoc including graphs for all layers [./layers/...]" @echo " make generate-devdoc # generate devdoc including graphs for all layers [./layers/...]"
@echo " make bash # start openmaptiles-tools /bin/bash terminal" @echo " make bash # start openmaptiles-tools /bin/bash terminal"
@echo " make destroy-db # remove docker containers and PostgreSQL data volume" @echo " make destroy-db # remove docker containers and PostgreSQL data volume"
@ -86,8 +226,8 @@ help:
@echo " make clean-unnecessary-docker # clean unnecessary docker image(s) and container(s)" @echo " make clean-unnecessary-docker # clean unnecessary docker image(s) and container(s)"
@echo " make refresh-docker-images # refresh openmaptiles docker images from Docker HUB" @echo " make refresh-docker-images # refresh openmaptiles docker images from Docker HUB"
@echo " make remove-docker-images # remove openmaptiles docker images" @echo " make remove-docker-images # remove openmaptiles docker images"
@echo " make pgclimb-list-views # list PostgreSQL public schema views" @echo " make list-views # list PostgreSQL public schema views"
@echo " make pgclimb-list-tables # list PostgreSQL public schema tables" @echo " make list-tables # list PostgreSQL public schema tables"
@echo " cat .env # list PG database and MIN_ZOOM and MAX_ZOOM information" @echo " cat .env # list PG database and MIN_ZOOM and MAX_ZOOM information"
@echo " cat quickstart.log # transcript of the last ./quickstart.sh run" @echo " cat quickstart.log # transcript of the last ./quickstart.sh run"
@echo " make help # help about available commands" @echo " make help # help about available commands"
@ -95,29 +235,39 @@ help:
.PHONY: init-dirs .PHONY: init-dirs
init-dirs: init-dirs:
@mkdir -p build/sql @mkdir -p build/sql/parallel
@mkdir -p data @mkdir -p build/openmaptiles.tm2source
@mkdir -p data/borders
@mkdir -p cache @mkdir -p cache
build/openmaptiles.tm2source/data.yml: init-dirs build/openmaptiles.tm2source/data.yml: init-dirs
mkdir -p build/openmaptiles.tm2source ifeq (,$(wildcard build/openmaptiles.tm2source/data.yml))
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-tm2source openmaptiles.yaml --host="postgres" --port=5432 --database="openmaptiles" --user="openmaptiles" --password="openmaptiles" > $@ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-tm2source $(TILESET_FILE) --host="postgres" --port=5432 --database="openmaptiles" --user="$(DC_USER)" --password="$(DC_PASSWORD)" > $@
endif
build/mapping.yaml: init-dirs build/mapping.yaml: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-imposm3 openmaptiles.yaml > $@ ifeq (,$(wildcard build/mapping.yaml))
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-imposm3 $(TILESET_FILE) > $@
endif
.PHONY: build-sql .PHONY: build-sql
build-sql: init-dirs build-sql: init-dirs
ifeq (,$(wildcard build/sql/run_last.sql))
@mkdir -p build/sql/parallel
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c \ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c \
'generate-sql openmaptiles.yaml --dir ./build/sql \ 'generate-sql $(TILESET_FILE) --dir ./build/sql \
&& generate-sqltomvt openmaptiles.yaml --key --postgis-ver 2.4.8 --function --fname=getmvt >> "./build/sql/run_last.sql"' && generate-sqltomvt $(TILESET_FILE) \
--key --gzip --postgis-ver 3.0.1 \
--function --fname=getmvt >> ./build/sql/run_last.sql'
endif
.PHONY: clean .PHONY: clean
clean: clean:
rm -rf build rm -rf build
.PHONY: destroy-db .PHONY: destroy-db
destroy-db: override DC_PROJECT:=$(shell echo $(DC_PROJECT) | tr A-Z a-z) # TODO: Use https://stackoverflow.com/a/27852388/177275
destroy-db: DC_PROJECT := $(shell echo $(DC_PROJECT) | tr A-Z a-z)
destroy-db: destroy-db:
$(DOCKER_COMPOSE) down -v --remove-orphans $(DOCKER_COMPOSE) down -v --remove-orphans
$(DOCKER_COMPOSE) rm -fv $(DOCKER_COMPOSE) rm -fv
@ -149,74 +299,126 @@ stop-db:
list-geofabrik: init-dirs list-geofabrik: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm list geofabrik $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm list geofabrik
OSM_SERVERS:=geofabrik osmfr bbbike .PHONY: list-bbbike
ALL_DOWNLOADS:=$(addprefix download-,$(OSM_SERVERS)) list-bbbike: init-dirs
OSM_SERVER=$(patsubst download-%,%,$@) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm list bbbike
#
# download, download-geofabrik, download-osmfr, and download-bbbike are handled here
# The --imposm-cfg will fail for some of the sources, but we ignore that error -- only needed for diff mode
#
OSM_SERVERS := geofabrik osmfr bbbike
ALL_DOWNLOADS := $(addprefix download-,$(OSM_SERVERS)) download
OSM_SERVER=$(patsubst download,,$(patsubst download-%,%,$@))
.PHONY: $(ALL_DOWNLOADS) .PHONY: $(ALL_DOWNLOADS)
$(ALL_DOWNLOADS): init-dirs $(ALL_DOWNLOADS): init-dirs
ifeq ($(strip $(area)),) @$(assert_area_is_given)
ifneq ($(strip $(url)),)
$(if $(OSM_SERVER),$(error url parameter can only be used with non-specific download target:$(newline) make download area=$(area) url="$(url)"$(newline)))
endif
ifeq (,$(wildcard $(PBF_FILE)))
ifeq ($(strip $(DIFF_MODE)),true)
@echo "Downloading $(DOWNLOAD_AREA) with replication support into $(PBF_FILE) and $(IMPOSM_CONFIG_FILE) from $(if $(OSM_SERVER),$(OSM_SERVER),any source)"
@$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm $(OSM_SERVER) "$(DOWNLOAD_AREA)" \
--imposm-cfg "$(IMPOSM_CONFIG_FILE)" \
--bbox "$(AREA_BBOX_FILE)" \
--output "$(PBF_FILE)"
else
@echo "Downloading $(DOWNLOAD_AREA) into $(PBF_FILE) from $(if $(OSM_SERVER),$(OSM_SERVER),any source)"
@$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm $(OSM_SERVER) "$(DOWNLOAD_AREA)" \
--bbox "$(AREA_BBOX_FILE)" \
--output "$(PBF_FILE)"
endif
@echo "" @echo ""
@echo "ERROR: Unable to download an area if area is not given."
@echo "Usage:"
@echo " make download-$(OSM_SERVER) area=<area-id>"
@echo ""
$(if $(filter %-geofabrik,$@),@echo "Use make list-geofabrik to get a list of all available areas";echo "")
@exit 1
else else
@echo "=============== download-$(OSM_SERVER) =======================" ifeq ($(strip $(DIFF_MODE)),true)
@echo "Download area: $(area)" ifeq (,$(wildcard $(IMPOSM_CONFIG_FILE)))
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c \ $(error \
'download-osm $(OSM_SERVER) $(area) \ $(newline) Data files $(PBF_FILE) already exists, but $(IMPOSM_CONFIG_FILE) does not. \
--minzoom $$QUICKSTART_MIN_ZOOM \ $(newline) You probably downloaded the data file before setting DIFF_MODE=true. \
--maxzoom $$QUICKSTART_MAX_ZOOM \ $(newline) You can delete the data file $(PBF_FILE) and re-run make download \
--make-dc /import/docker-compose-config.yml -- -d /import' $(newline) to re-download and generate config, or manually create $(IMPOSM_CONFIG_FILE) \
ls -la ./data/$(notdir $(area))* $(newline) See example https://github.com/openmaptiles/openmaptiles-tools/blob/v5.2/bin/config/repl_config.json \
@echo "" $(newline))
else
@echo "Data files $(PBF_FILE) and replication config $(IMPOSM_CONFIG_FILE) already exists, skipping the download."
endif
else
@echo "Data files $(PBF_FILE) already exists, skipping the download."
endif
endif
.PHONY: generate-bbox-file
generate-bbox-file:
@$(assert_area_is_given)
ifeq (,$(wildcard $(AREA_BBOX_FILE)))
@$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm bbox "$(PBF_FILE)" "$(AREA_BBOX_FILE)"
else
@echo "Configuration file $(AREA_BBOX_FILE) already exists, no need to regenerate. BBOX=$(BBOX)"
endif endif
.PHONY: psql .PHONY: psql
psql: start-db-nowait psql: start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && psql.sh' $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && psql.sh'
# Special cache handling for Docker Toolbox on Windows
ifeq ($(MSYSTEM),MINGW64)
DC_CONFIG_CACHE := -f docker-compose.yml -f docker-compose-$(MSYSTEM).yml
DC_OPTS_CACHE := $(strip $(filter-out --user=%,$(DC_OPTS)))
else
DC_OPTS_CACHE := $(DC_OPTS)
endif
.PHONY: import-osm .PHONY: import-osm
import-osm: all start-db-nowait import-osm: all start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-osm $(PBF_FILE)' @$(assert_area_is_given)
$(DOCKER_COMPOSE) $(DC_CONFIG_CACHE) run $(DC_OPTS_CACHE) openmaptiles-tools sh -c 'pgwait && import-osm $(PBF_FILE)'
.PHONY: update-osm .PHONY: update-osm
update-osm: all start-db-nowait update-osm: all start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-update' @$(assert_area_is_given)
$(DOCKER_COMPOSE) $(DC_CONFIG_CACHE) run $(DC_OPTS_CACHE) openmaptiles-tools sh -c 'pgwait && import-update'
.PHONY: import-diff .PHONY: import-diff
import-diff: all start-db-nowait import-diff: all start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-diff' @$(assert_area_is_given)
$(DOCKER_COMPOSE) $(DC_CONFIG_CACHE) run $(DC_OPTS_CACHE) openmaptiles-tools sh -c 'pgwait && import-diff'
.PHONY: import-data .PHONY: import-data
import-data: start-db import-data: start-db
$(DOCKER_COMPOSE) run $(DC_OPTS) import-data $(DOCKER_COMPOSE) $(DC_CONFIG_CACHE) run $(DC_OPTS_CACHE) import-data
.PHONY: import-borders .PHONY: import-borders
import-borders: start-db-nowait import-borders: start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-borders' @$(assert_area_is_given)
# If CSV borders file already exists, use it without re-parsing
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c \
'pgwait && import-borders $$([ -f "$(BORDERS_CSV_FILE)" ] && echo load $(BORDERS_CSV_FILE) || echo import $(PBF_FILE))'
.PHONY: import-sql .PHONY: import-sql
import-sql: all start-db-nowait import-sql: all start-db-nowait
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-sql' | \ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-sql' | \
awk -v s=": WARNING:" '$$0~s{print; print "\n*** WARNING detected, aborting"; exit(1)} 1' awk -v s=": WARNING:" '1{print; fflush()} $$0~s{print "\n*** WARNING detected, aborting"; exit(1)}'
.PHONY: show-metadata
show-metadata: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools mbtiles-tools meta-all ./data/tiles.mbtiles
.PHONY: generate-tiles .PHONY: generate-tiles
ifneq ($(wildcard data/docker-compose-config.yml),)
DC_CONFIG_TILES:=-f docker-compose.yml -f ./data/docker-compose-config.yml
endif
generate-tiles: all start-db generate-tiles: all start-db
rm -rf data/tiles.mbtiles @$(assert_area_is_given)
echo "Generating tiles ..."; \ @echo "Generating tiles into $(MBTILES_LOCAL_FILE) (will delete if already exists)..."
$(DOCKER_COMPOSE) $(DC_CONFIG_TILES) run $(DC_OPTS) generate-vectortiles @rm -rf "$(MBTILES_LOCAL_FILE)"
$(DOCKER_COMPOSE) run $(DC_OPTS) generate-vectortiles
@echo "Updating generated tile metadata ..." @echo "Updating generated tile metadata ..."
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-metadata ./data/tiles.mbtiles $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools \
mbtiles-tools meta-generate "$(MBTILES_LOCAL_FILE)" $(TILESET_FILE) --auto-minmax --show-ranges
.PHONY: generate-tiles-pg
generate-tiles-pg: all start-db
@$(assert_area_is_given)
@echo "Generating tiles into $(MBTILES_LOCAL_FILE) (will delete if already exists)..."
@rm -rf "$(MBTILES_LOCAL_FILE)"
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-tiles
@echo "Updating generated tile metadata ..."
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools \
mbtiles-tools meta-generate "$(MBTILES_LOCAL_FILE)" $(TILESET_FILE) --auto-minmax --show-ranges
.PHONY: start-tileserver .PHONY: start-tileserver
start-tileserver: init-dirs start-tileserver: init-dirs
@ -275,17 +477,22 @@ start-maputnik: stop-maputnik start-postserve
stop-maputnik: stop-maputnik:
-docker rm -f maputnik_editor -docker rm -f maputnik_editor
.PHONY: generate-qareports # STAT_FUNCTION=frequency|toplength|variance
generate-qareports: start-db .PHONY: generate-qa
./qa/run.sh generate-qa: all start-db-nowait
@echo " "
@echo "e.g. make generate-qa STAT_FUNCTION=frequency LAYER=transportation ATTRIBUTE=class"
@echo " "
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools \
layer-stats $(STAT_FUNCTION) $(TILESET_FILE) $(LAYER) $(ATTRIBUTE) -m 0 -n 14 -v
# generate all etl and mapping graphs # generate all etl and mapping graphs
.PHONY: generate-devdoc .PHONY: generate-devdoc
generate-devdoc: init-dirs generate-devdoc: init-dirs
mkdir -p ./build/devdoc && \ mkdir -p ./build/devdoc && \
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c \ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c \
'generate-etlgraph openmaptiles.yaml $(GRAPH_PARAMS) && \ 'generate-etlgraph $(TILESET_FILE) $(GRAPH_PARAMS) && \
generate-mapping-graph openmaptiles.yaml $(GRAPH_PARAMS)' generate-mapping-graph $(TILESET_FILE) $(GRAPH_PARAMS)'
.PHONY: bash .PHONY: bash
bash: init-dirs bash: init-dirs
@ -293,7 +500,7 @@ bash: init-dirs
.PHONY: import-wikidata .PHONY: import-wikidata
import-wikidata: init-dirs import-wikidata: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools import-wikidata --cache /cache/wikidata-cache.json openmaptiles.yaml $(DOCKER_COMPOSE) $(DC_CONFIG_CACHE) run $(DC_OPTS_CACHE) openmaptiles-tools import-wikidata --cache /cache/wikidata-cache.json $(TILESET_FILE)
.PHONY: reset-db-stats .PHONY: reset-db-stats
reset-db-stats: init-dirs reset-db-stats: init-dirs
@ -302,12 +509,12 @@ reset-db-stats: init-dirs
.PHONY: list-views .PHONY: list-views
list-views: init-dirs list-views: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools psql.sh -v ON_ERROR_STOP=1 -A -F"," -P pager=off -P footer=off \ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools psql.sh -v ON_ERROR_STOP=1 -A -F"," -P pager=off -P footer=off \
-c "select schemaname, viewname from pg_views where schemaname='public' order by viewname;" -c "select viewname from pg_views where schemaname='public' order by viewname;"
.PHONY: list-tables .PHONY: list-tables
list-tables: init-dirs list-tables: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools psql.sh -v ON_ERROR_STOP=1 -A -F"," -P pager=off -P footer=off \ $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools psql.sh -v ON_ERROR_STOP=1 -A -F"," -P pager=off -P footer=off \
-c "select schemaname, tablename from pg_tables where schemaname='public' order by tablename;" -c "select tablename from pg_tables where schemaname='public' order by tablename;"
.PHONY: psql-list-tables .PHONY: psql-list-tables
psql-list-tables: init-dirs psql-list-tables: init-dirs
@ -353,14 +560,23 @@ remove-docker-images:
.PHONY: clean-unnecessary-docker .PHONY: clean-unnecessary-docker
clean-unnecessary-docker: clean-unnecessary-docker:
@echo "Deleting unnecessary container(s)..." @echo "Deleting unnecessary container(s)..."
@docker ps -a --filter "status=exited" | $(XARGS) docker rm @docker ps -a -q --filter "status=exited" | $(XARGS) docker rm
@echo "Deleting unnecessary image(s)..." @echo "Deleting unnecessary image(s)..."
@docker images | grep \<none\> | awk -F" " '{print $$3}' | $(XARGS) docker rmi @docker images | awk -F" " '/<none>/{print $$3}' | $(XARGS) docker rmi
.PHONY: test-perf-null .PHONY: test-perf-null
test-perf-null: init-dirs test-perf-null: init-dirs
$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools test-perf openmaptiles.yaml --test null --no-color $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools test-perf $(TILESET_FILE) --test null --no-color
.PHONY: build-test-pbf .PHONY: build-test-pbf
build-test-pbf: init-dirs build-test-pbf: init-dirs
docker-compose run $(DC_OPTS) openmaptiles-tools /tileset/.github/workflows/build-test-data.sh docker-compose run $(DC_OPTS) openmaptiles-tools /tileset/.github/workflows/build-test-data.sh
.PHONY: debug
debug: ## Use this target when developing Makefile itself to verify loaded environment variables
@$(assert_area_is_given)
@echo file_exists = $(wildcard $(AREA_BBOX_FILE))
@echo AREA_BBOX_FILE = $(AREA_BBOX_FILE) , $$AREA_ENV_FILE
@echo BBOX = $(BBOX) , $$BBOX
@echo MIN_ZOOM = $(MIN_ZOOM) , $$MIN_ZOOM
@echo MAX_ZOOM = $(MAX_ZOOM) , $$MAX_ZOOM

View File

@ -363,12 +363,13 @@ This is generating `.mbtiles` for your area : [ MIN_ZOOM: "0" - MAX_ZOOM: "7"
./quickstart.sh yukon # Yukon, Canada ./quickstart.sh yukon # Yukon, Canada
``` ```
### Using your own OSM data ### Using your own OSM data
Mbtiles can be generated from an arbitrary osm.pbf (e.g. for a region that is not covered by an existing extract) by making the `data/` directory and placing an *-latest.osm.pbf inside. Inside of folder have to be `docker-compose-config.yml` file too, otherwize whole folder `data/` will be deleted and `download-osm` will try to download osm.pbf file from `geofabric`, `osmfr` or `bbbike`. Mbtiles can be generated from an arbitrary osm.pbf (e.g. for a region that is not covered by an existing extract) by making the `data/` directory and placing an *.osm.pbf (e.g. `mydata.osm.pbf`) inside.
``` ```
mkdir -p data mkdir -p data
mv my-latest.osm.pbf data/ mv mydata.osm.pbf data/
./quickstart.sh my make generate-bbox-file area=mydata
./quickstart.sh mydata
``` ```
### Check postserve ### Check postserve
@ -384,20 +385,26 @@ and the generated maps are going to be available in webbrowser on [localhost:808
This is only a quick preview, because your mbtiles only generated to zoom level 7 ! This is only a quick preview, because your mbtiles only generated to zoom level 7 !
### Change MIN_ZOOM and MAX_ZOOM ### Set which zooms to generate
modify the settings in the `.env` file, the defaults : modify the settings in the `.env` file, the defaults:
* QUICKSTART_MIN_ZOOM=0 * `MIN_ZOOM=0`
* QUICKSTART_MAX_ZOOM=7 * `MAX_ZOOM=7`
and re-start `./quickstart.sh `
* the new config file re-generating to here ./data/docker-compose-config.yml
* Known problems:
* If you use same area - then the ./data/docker-compose-config.yml not re-generating, so you have to modify by hand!
Hints: Hints:
* Small increments! Never starts with the MAX_ZOOM = 14 * Small increments! Never starts with the `MAX_ZOOM = 14`
* The suggested MAX_ZOOM = 14 - use only with small extracts * The suggested `MAX_ZOOM = 14` - use only with small extracts
### Set the bounding box to generate
By default, tile generation is done for the full extent of the area.
If you want to generate a tiles for a smaller extent, modify the settings in the `.env` file, the default:
* `BBOX=-180.0,-85.0511,180.0,85.0511`
Delete the `./data/<area>.bbox` file, and re-start `./quickstart.sh <area>`
Hint:
* The [boundingbox.klokantech.com](https://boundingbox.klokantech.com/) site can be used to find a bounding box (CSV format) using a map.
### Check other commands ### Check other commands
@ -424,7 +431,7 @@ Hints for developers:
make psql-list-tables # list all PostgreSQL tables make psql-list-tables # list all PostgreSQL tables
make psql-vacuum-analyze # PostgreSQL: VACUUM ANALYZE make psql-vacuum-analyze # PostgreSQL: VACUUM ANALYZE
make psql-analyze # PostgreSQL: ANALYZE make psql-analyze # PostgreSQL: ANALYZE
make generate-qareports # generate reports [./build/qareports] make generate-qa # statistics for a given layer's field
make generate-devdoc # generate devdoc [./build/devdoc] make generate-devdoc # generate devdoc [./build/devdoc]
make tools-dev # start import-sql /bin/bash terminal make tools-dev # start import-sql /bin/bash terminal
make db-destroy # remove docker containers, PG data volume make db-destroy # remove docker containers, PG data volume

View File

@ -1,6 +1,6 @@
## OpenMapTiles [![Build Status](https://github.com/openmaptiles/openmaptiles/workflows/OMT_CI/badge.svg?branch=master)](https://github.com/openmaptiles/openmaptiles/actions) ## OpenMapTiles [![Build Status](https://github.com/openmaptiles/openmaptiles/workflows/OMT_CI/badge.svg?branch=master)](https://github.com/openmaptiles/openmaptiles/actions)
OpenMapTiles is an extensible and open tile schema based on the OpenStreetMap. This project is used to generate vector tiles for online zoomable maps. OpenMapTiles is about creating a beautiful basemaps with general layers containing topographic information. More information [openmaptiles.org](https://openmaptiles.org/) and [openmaptiles.com](https://openmaptiles.com/). OpenMapTiles is an extensible and open tile schema based on the OpenStreetMap. This project is used to generate vector tiles for online zoomable maps. OpenMapTiles is about creating a beautiful basemaps with general layers containing topographic information. More information [openmaptiles.org](https://openmaptiles.org/) and [maptiler.com/data/](https://www.maptiler.com/data/).
We encourage you to collaborate, reuse and adapt existing layers, or add your own layers. You may use our approach for your own vector tile project. Feel free to fork the repo and experiment. The repository is built on top of the [openmaptiles/openmaptiles-tools](https://github.com/openmaptiles/openmaptiles-tools) to simplify vector tile creation. We encourage you to collaborate, reuse and adapt existing layers, or add your own layers. You may use our approach for your own vector tile project. Feel free to fork the repo and experiment. The repository is built on top of the [openmaptiles/openmaptiles-tools](https://github.com/openmaptiles/openmaptiles-tools) to simplify vector tile creation.
@ -8,7 +8,7 @@ Please keep in mind that OpenMapTiles schema should display general topographic
- :link: Schema https://openmaptiles.org/schema - :link: Schema https://openmaptiles.org/schema
- :link: Docs https://openmaptiles.org/docs - :link: Docs https://openmaptiles.org/docs
- :link: Production package: https://openmaptiles.com/production-package/ - :link: Data for download: https://www.maptiler.com/data/
- :link: Hosting https://www.maptiler.com/cloud/ - :link: Hosting https://www.maptiler.com/cloud/
- :link: Create own layer https://github.com/openmaptiles/openmaptiles-skiing - :link: Create own layer https://github.com/openmaptiles/openmaptiles-skiing
- :link: Discuss at the #openmaptiles channel at [OSM Slack](https://osmus-slack.herokuapp.com/) - :link: Discuss at the #openmaptiles channel at [OSM Slack](https://osmus-slack.herokuapp.com/)
@ -83,10 +83,10 @@ make
``` ```
You can execute the following manual steps (for better understanding) You can execute the following manual steps (for better understanding)
or use the provided `quickstart.sh` script. or use the provided `quickstart.sh` script to automatically download and import given area. If area is not given, albania will be imported.
``` ```
./quickstart.sh ./quickstart.sh <area>
``` ```
### Prepare the Database ### Prepare the Database
@ -103,10 +103,10 @@ Import external data from [OpenStreetMapData](http://osmdata.openstreetmap.de/),
make import-data make import-data
``` ```
[Download OpenStreetMap data extracts](http://download.geofabrik.de/) and store the PBF file in the `./data` directory. Download OpenStreetMap data extracts from any source like [Geofabrik](http://download.geofabrik.de/), and store the PBF file in the `./data` directory. To use a specific download source, use `download-geofabrik`, `download-bbbike`, or `download-osmfr`, or use `download` to make it auto-pick the area. You can use `area=planet` for the entire OSM dataset (very large). Note that if you have more than one `data/*.osm.pbf` file, every `make` command will always require `area=...` parameter (or you can just `export area=...` first).
```bash ```bash
make download-geofabrik area=albania make download area=albania
``` ```
[Import OpenStreetMap data](https://github.com/openmaptiles/openmaptiles-tools/tree/master/docker/import-osm) with the mapping rules from [Import OpenStreetMap data](https://github.com/openmaptiles/openmaptiles-tools/tree/master/docker/import-osm) with the mapping rules from
@ -135,11 +135,11 @@ make
make import-sql make import-sql
``` ```
Now you are ready to **generate the vector tiles**. Using environment variables Now you are ready to **generate the vector tiles**. By default, `./.env` specifies the entire planet BBOX for zooms 0-7, but running `generate-bbox-file` will analyze the data file and set the `BBOX` param to limit tile generation.
you can limit the bounding box and zoom levels of what you want to generate (`docker-compose.yml`).
``` ```
make generate-tiles make generate-bbox-file # compute data bbox -- not needed for the whole planet
make generate-tiles # generate tiles
``` ```
## License ## License

View File

@ -0,0 +1,11 @@
# This version must match the MAKE_DC_VERSION in docker-compose.yml
version: "3"
volumes:
cache:
services:
openmaptiles-tools:
volumes:
- cache:/cache

View File

@ -1,11 +1,11 @@
# This version must match the MAKE_DC_VERSION value below # This version must match the MAKE_DC_VERSION value below
version: "2.3" version: "3"
volumes: volumes:
pgdata: pgdata:
networks: networks:
postgres_conn: postgres:
driver: bridge driver: bridge
services: services:
@ -16,7 +16,7 @@ services:
volumes: volumes:
- pgdata:/var/lib/postgresql/data - pgdata:/var/lib/postgresql/data
networks: networks:
- postgres_conn - postgres
ports: ports:
- "5432" - "5432"
env_file: .env-postgres env_file: .env-postgres
@ -25,7 +25,7 @@ services:
image: "openmaptiles/import-data:${TOOLS_VERSION}" image: "openmaptiles/import-data:${TOOLS_VERSION}"
env_file: .env env_file: .env
networks: networks:
- postgres_conn - postgres
openmaptiles-tools: openmaptiles-tools:
image: "openmaptiles/openmaptiles-tools:${TOOLS_VERSION}" image: "openmaptiles/openmaptiles-tools:${TOOLS_VERSION}"
@ -33,14 +33,27 @@ services:
environment: environment:
# Must match the version of this file (first line) # Must match the version of this file (first line)
# download-osm will use it when generating a composer file # download-osm will use it when generating a composer file
MAKE_DC_VERSION: "2.3" MAKE_DC_VERSION: "3"
# Allow DIFF_MODE to be overwritten from shell # Allow DIFF_MODE, MIN_ZOOM, and MAX_ZOOM to be overwritten from shell
DIFF_MODE: ${DIFF_MODE} DIFF_MODE: ${DIFF_MODE}
MIN_ZOOM: ${MIN_ZOOM}
MAX_ZOOM: ${MAX_ZOOM}
#Provide BBOX from *.bbox file if exists, else from .env
BBOX: ${BBOX}
# Imposm configuration file describes how to load updates when enabled
IMPOSM_CONFIG_FILE: ${IMPOSM_CONFIG_FILE}
# Which files to use during import-borders processing
BORDERS_CLEANUP_FILE: ${BORDERS_CLEANUP_FILE}
BORDERS_PBF_FILE: ${BORDERS_PBF_FILE}
BORDERS_CSV_FILE: ${BORDERS_CSV_FILE}
# Control import-sql processes
MAX_PARALLEL_PSQL: ${MAX_PARALLEL_PSQL}
networks: networks:
- postgres_conn - postgres
volumes: volumes:
- .:/tileset - .:/tileset
- ./data:/import - ./data:/import
- ./data:/export
- ./build/sql:/sql - ./build/sql:/sql
- ./build:/mapping - ./build:/mapping
- ./cache:/cache - ./cache:/cache
@ -52,8 +65,13 @@ services:
- ./data:/export - ./data:/export
- ./build/openmaptiles.tm2source:/tm2source - ./build/openmaptiles.tm2source:/tm2source
networks: networks:
- postgres_conn - postgres
env_file: .env env_file: .env
environment:
FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT}
MBTILES_NAME: ${MBTILES_FILE}
# Control tilelive-copy threads
COPY_CONCURRENCY: ${COPY_CONCURRENCY}
generate-vectortiles: generate-vectortiles:
image: "openmaptiles/generate-vectortiles:${TOOLS_VERSION}" image: "openmaptiles/generate-vectortiles:${TOOLS_VERSION}"
@ -61,20 +79,26 @@ services:
- ./data:/export - ./data:/export
- ./build/openmaptiles.tm2source:/tm2source - ./build/openmaptiles.tm2source:/tm2source
networks: networks:
- postgres_conn - postgres
env_file: .env env_file: .env
environment: environment:
FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT}
MBTILES_NAME: ${MBTILES_FILE}
BBOX: ${BBOX} BBOX: ${BBOX}
MIN_ZOOM: ${MIN_ZOOM} MIN_ZOOM: ${MIN_ZOOM}
MAX_ZOOM: ${MAX_ZOOM} MAX_ZOOM: ${MAX_ZOOM}
FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT} # Control tilelive-copy threads
COPY_CONCURRENCY: ${COPY_CONCURRENCY}
#
postserve: postserve:
image: "openmaptiles/openmaptiles-tools:${TOOLS_VERSION}" image: "openmaptiles/openmaptiles-tools:${TOOLS_VERSION}"
command: "postserve openmaptiles.yaml --verbose --port ${PPORT:-8090}" command: "postserve ${TILESET_FILE} --verbose --serve=${OMT_HOST:-http://localhost}:${PPORT:-8090}"
env_file: .env env_file: .env
environment:
TILESET_FILE: ${TILESET_FILE}
networks: networks:
- postgres_conn - postgres
ports: ports:
- "${PPORT:-8090}:${PPORT:-8090}" - "${PPORT:-8090}:${PPORT:-8090}"
volumes: volumes:

View File

@ -0,0 +1,43 @@
-- etldoc: layer_aerodrome_label[shape=record fillcolor=lightpink, style="rounded,filled", label="layer_aerodrome_label | <z10_> z10+" ] ;
CREATE OR REPLACE FUNCTION layer_aerodrome_label(bbox geometry,
zoom_level integer)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
tags hstore,
class text,
iata text,
icao text,
ele int,
ele_ft int
)
AS
$$
SELECT
-- etldoc: osm_aerodrome_label_point -> layer_aerodrome_label:z10_
osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
CASE
%%FIELD_MAPPING: class %%
ELSE 'other'
END AS class,
NULLIF(iata, '') AS iata,
NULLIF(icao, '') AS icao,
substring(ele FROM E'^(-?\\d+)(\\D|$)')::int AS ele,
round(substring(ele FROM E'^(-?\\d+)(\\D|$)')::int * 3.2808399)::int AS ele_ft
FROM osm_aerodrome_label_point
WHERE geometry && bbox
AND zoom_level >= 10;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -41,10 +41,10 @@ layer:
key_field: osm_id key_field: osm_id
key_field_as_attribute: no key_field_as_attribute: no
srid: 900913 srid: 900913
query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, iata, icao, ele, ele_ft FROM layer_aerodrome_label (!bbox!, z(!scale_denominator!), !pixel_width!)) AS t query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, iata, icao, ele, ele_ft FROM layer_aerodrome_label(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./update_aerodrome_label_point.sql - ./update_aerodrome_label_point.sql
- ./layer.sql - ./aerodrome_label.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,41 +0,0 @@
-- etldoc: layer_aerodrome_label[shape=record fillcolor=lightpink, style="rounded,filled", label="layer_aerodrome_label | <z10_> z10+" ] ;
CREATE OR REPLACE FUNCTION layer_aerodrome_label(
bbox geometry,
zoom_level integer,
pixel_width numeric)
RETURNS TABLE(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
tags hstore,
class text,
iata text,
icao text,
ele int,
ele_ft int) AS
$$
-- etldoc: osm_aerodrome_label_point -> layer_aerodrome_label:z10_
SELECT
osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
CASE
%%FIELD_MAPPING: class %%
ELSE 'other'
END AS class,
NULLIF(iata, '') AS iata,
NULLIF(icao, '') AS icao,
substring(ele from E'^(-?\\d+)(\\D|$)')::int AS ele,
round(substring(ele from E'^(-?\\d+)(\\D|$)')::int*3.2808399)::int AS ele_ft
FROM osm_aerodrome_label_point
WHERE geometry && bbox AND zoom_level >= 10;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -1,51 +1,91 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_aerodrome_label_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_aerodrome_label_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_aerodrome_label_point;
DROP TRIGGER IF EXISTS trigger_refresh ON aerodrome_label.updates; DROP TRIGGER IF EXISTS trigger_refresh ON aerodrome_label.updates;
-- etldoc: osm_aerodrome_label_point -> osm_aerodrome_label_point
CREATE OR REPLACE FUNCTION update_aerodrome_label_point() RETURNS VOID AS $$
BEGIN
UPDATE osm_aerodrome_label_point
SET geometry = ST_Centroid(geometry)
WHERE ST_GeometryType(geometry) <> 'ST_Point';
UPDATE osm_aerodrome_label_point
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END;
$$ LANGUAGE plpgsql;
SELECT update_aerodrome_label_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS aerodrome_label; CREATE SCHEMA IF NOT EXISTS aerodrome_label;
CREATE TABLE IF NOT EXISTS aerodrome_label.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS aerodrome_label.osm_ids
CREATE OR REPLACE FUNCTION aerodrome_label.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_aerodrome_label_point -> osm_aerodrome_label_point
CREATE OR REPLACE FUNCTION update_aerodrome_label_point(full_update boolean) RETURNS void AS
$$
UPDATE osm_aerodrome_label_point
SET geometry = ST_Centroid(geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM aerodrome_label.osm_ids))
AND ST_GeometryType(geometry) <> 'ST_Point';
UPDATE osm_aerodrome_label_point
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM aerodrome_label.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
$$ LANGUAGE SQL;
SELECT update_aerodrome_label_point(true);
-- Handle updates
CREATE OR REPLACE FUNCTION aerodrome_label.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO aerodrome_label.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO aerodrome_label.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO aerodrome_label.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS aerodrome_label.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION aerodrome_label.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO aerodrome_label.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION aerodrome_label.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION aerodrome_label.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh aerodrome_label'; RAISE LOG 'Refresh aerodrome_label';
PERFORM update_aerodrome_label_point(); PERFORM update_aerodrome_label_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM aerodrome_label.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM aerodrome_label.updates; DELETE FROM aerodrome_label.updates;
RETURN null;
END; RAISE LOG 'Refresh aerodrome_label done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_aerodrome_label_point
FOR EACH ROW
EXECUTE PROCEDURE aerodrome_label.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_aerodrome_label_point AFTER INSERT OR UPDATE OR DELETE
ON osm_aerodrome_label_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE aerodrome_label.flag(); EXECUTE PROCEDURE aerodrome_label.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON aerodrome_label.updates AFTER INSERT
ON aerodrome_label.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE aerodrome_label.refresh(); EXECUTE PROCEDURE aerodrome_label.refresh();

View File

@ -0,0 +1,70 @@
-- etldoc: layer_aeroway[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_aeroway |<z10> z10|<z11> z11|<z12> z12|<z13> z13|<z14_> z14+" ];
CREATE OR REPLACE FUNCTION layer_aeroway(bbox geometry, zoom_level int)
RETURNS TABLE
(
geometry geometry,
class text,
ref text
)
AS
$$
SELECT geometry, aeroway AS class, ref
FROM (
-- etldoc: osm_aeroway_linestring_gen_z10 -> layer_aeroway:z10
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen_z10
WHERE zoom_level = 10
UNION ALL
-- etldoc: osm_aeroway_linestring_gen_z11 -> layer_aeroway:z11
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen_z11
WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_aeroway_linestring_gen_z12 -> layer_aeroway:z12
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen_z12
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aeroway_linestring -> layer_aeroway:z13
-- etldoc: osm_aeroway_linestring -> layer_aeroway:z14_
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring
WHERE zoom_level >= 13
UNION ALL
-- etldoc: osm_aeroway_polygon_gen_z10 -> layer_aeroway:z10
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen_z10
WHERE zoom_level = 10
UNION ALL
-- etldoc: osm_aeroway_polygon_gen_z11 -> layer_aeroway:z11
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen_z11
WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_aeroway_polygon_gen_z12 -> layer_aeroway:z12
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen_z12
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aeroway_polygon_gen_z13 -> layer_aeroway:z13
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen_z13
WHERE zoom_level = 13
UNION ALL
-- etldoc: osm_aeroway_polygon -> layer_aeroway:z14_
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon
WHERE zoom_level >= 14
UNION ALL
-- etldoc: osm_aeroway_point -> layer_aeroway:z14_
SELECT geometry, aeroway, ref
FROM osm_aeroway_point
WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -19,11 +19,12 @@ layer:
- helipad - helipad
- taxiway - taxiway
- apron - apron
- gate
datasource: datasource:
geometry_field: geometry geometry_field: geometry
query: (SELECT geometry, ref, class FROM layer_aeroway(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, ref, class FROM layer_aeroway(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./layer.sql - ./aeroway.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 166 KiB

View File

@ -1,45 +0,0 @@
-- etldoc: layer_aeroway[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_aeroway |<z10> z10|<z11> z11|<z12> z12|<z13> z13|<z14_> z14+" ];
CREATE OR REPLACE FUNCTION layer_aeroway(bbox geometry, zoom_level int)
RETURNS TABLE(geometry geometry, class text, ref text) AS $$
SELECT geometry, aeroway AS class, ref FROM (
-- etldoc: osm_aeroway_linestring_gen3 -> layer_aeroway:z10
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen3 WHERE zoom_level = 10
UNION ALL
-- etldoc: osm_aeroway_linestring_gen2 -> layer_aeroway:z11
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen2 WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_aeroway_linestring_gen1 -> layer_aeroway:z12
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring_gen1 WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aeroway_linestring -> layer_aeroway:z13
-- etldoc: osm_aeroway_linestring -> layer_aeroway:z14_
SELECT geometry, aeroway, ref
FROM osm_aeroway_linestring WHERE zoom_level >= 13
UNION ALL
-- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z10
-- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z11
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen3 WHERE zoom_level BETWEEN 10 AND 11
UNION ALL
-- etldoc: osm_aeroway_polygon_gen2 -> layer_aeroway:z12
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen2 WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aeroway_polygon_gen1 -> layer_aeroway:z13
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon_gen1 WHERE zoom_level = 13
UNION ALL
-- etldoc: osm_aeroway_polygon -> layer_aeroway:z14_
SELECT geometry, aeroway, ref
FROM osm_aeroway_polygon WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox;
$$
LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;

View File

@ -1,34 +1,40 @@
generalized_tables: generalized_tables:
# etldoc: imposm3 -> osm_aeroway_linestring_gen3 # etldoc: osm_aeroway_linestring_gen_z11 -> osm_aeroway_linestring_gen_z10
aeroway_linestring_gen3: aeroway_linestring_gen_z10:
source: aeroway_linestring_gen2 source: aeroway_linestring_gen_z11
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_aeroway_linestring_gen2 # etldoc: osm_aeroway_linestring_gen_z12 -> osm_aeroway_linestring_gen_z11
aeroway_linestring_gen2: aeroway_linestring_gen_z11:
source: aeroway_linestring_gen1 source: aeroway_linestring_gen_z12
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_aeroway_linestring_gen1 # etldoc: osm_aeroway_linestring -> osm_aeroway_linestring_gen_z12
aeroway_linestring_gen1: aeroway_linestring_gen_z12:
source: aeroway_linestring source: aeroway_linestring
sql_filter: ST_IsValid(geometry) sql_filter: ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
# etldoc: imposm3 -> osm_aeroway_polygon_gen3 # etldoc: osm_aeroway_polygon_gen_z11 -> osm_aeroway_polygon_gen_z10
aeroway_polygon_gen3: aeroway_polygon_gen_z10:
source: aeroway_polygon_gen2 source: aeroway_polygon_gen_z11
sql_filter: area>power(ZRES9,2)
tolerance: ZRES10
# etldoc: osm_aeroway_polygon_gen_z12 -> osm_aeroway_polygon_gen_z11
aeroway_polygon_gen_z11:
source: aeroway_polygon_gen_z12
sql_filter: area>power(ZRES10,2) sql_filter: area>power(ZRES10,2)
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_aeroway_polygon_gen2 # etldoc: osm_aeroway_polygon_gen_z13 -> osm_aeroway_polygon_gen_z12
aeroway_polygon_gen2: aeroway_polygon_gen_z12:
source: aeroway_polygon_gen1 source: aeroway_polygon_gen_z13
sql_filter: area>power(ZRES11,2) sql_filter: area>power(ZRES11,2)
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_aeroway_polygon_gen1 # etldoc: osm_aeroway_polygon -> osm_aeroway_polygon_gen_z13
aeroway_polygon_gen1: aeroway_polygon_gen_z13:
source: aeroway_polygon source: aeroway_polygon
sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry) sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
@ -80,3 +86,19 @@ tables:
aeroway: aeroway:
- runway - runway
- taxiway - taxiway
# etldoc: imposm3 -> osm_aeroway_point
aeroway_point:
type: point
columns:
- *ref
- name: osm_id
type: id
- name: geometry
type: geometry
- name: aeroway
key: aeroway
type: string
mapping:
aeroway:
- gate

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,10 @@ layer:
The `admin_level` corresponds to the lowest `admin_level` The `admin_level` corresponds to the lowest `admin_level`
the line participates in. the line participates in.
At low zoom levels the Natural Earth boundaries are mapped to the equivalent admin levels. At low zoom levels the Natural Earth boundaries are mapped to the equivalent admin levels.
adm0_l: |
State name on the left of the border. For country boundaries only (`admin_level = 2`).
adm0_r: |
State name on the right of the border. For country boundaries only (`admin_level = 2`).
disputed: disputed:
description: | description: |
Mark with `1` if the border is disputed. Mark with `1` if the border is disputed.
@ -46,8 +50,9 @@ layer:
buffer_size: 4 buffer_size: 4
datasource: datasource:
geometry_field: geometry geometry_field: geometry
query: (SELECT geometry, admin_level, disputed, disputed_name, claimed_by, maritime FROM layer_boundary(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, admin_level, adm0_l, adm0_r, disputed, disputed_name, claimed_by, maritime FROM layer_boundary(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./boundary_name.sql
- ./boundary.sql - ./boundary.sql
datasources: datasources:
- type: imposm3 - type: imposm3

View File

@ -0,0 +1,99 @@
DROP TABLE IF EXISTS osm_border_linestring_adm CASCADE;
-- etldoc: osm_border_linestring -> osm_border_linestring_adm
CREATE TABLE IF NOT EXISTS osm_border_linestring_adm AS (
WITH
-- Prepare lines from osm to be merged
multiline AS (
SELECT ST_Node(ST_Collect(geometry)) AS geometry,
maritime,
disputed
FROM osm_border_linestring
WHERE admin_level = 2
AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring)
GROUP BY maritime,
disputed
),
mergedline AS (
SELECT (ST_Dump(
ST_LineMerge(geometry))).geom AS geometry,
maritime,
disputed
FROM multiline
),
-- Create polygons from all boundaries to preserve real shape of country
polyg AS (
SELECT (ST_Dump(
ST_Polygonize(geometry))).geom AS geometry
FROM (
SELECT (ST_Dump(
ST_LineMerge(geometry))).geom AS geometry
FROM (SELECT ST_Node(
ST_Collect(geometry)) AS geometry
FROM osm_border_linestring
WHERE admin_level = 2
) nodes
) linemerge
),
centroids AS (
SELECT polyg.geometry,
ne.adm0_a3
FROM polyg,
ne_10m_admin_0_countries AS ne
WHERE ST_Within(
ST_PointOnSurface(polyg.geometry), ne.geometry)
),
country_osm_polyg AS (
SELECT country.adm0_a3,
border.geometry
FROM polyg border,
centroids country
WHERE ST_Within(country.geometry, border.geometry)
),
rights AS (
SELECT adm0_r,
geometry,
maritime,
disputed
FROM (
SELECT b.adm0_a3 AS adm0_r,
a.geometry,
a.maritime,
a.disputed
FROM mergedline AS a
LEFT JOIN country_osm_polyg AS b
-- Create short line on the right of the boundary (mergedline) and find state where line lies.
ON ST_Within(
ST_OffsetCurve(
(ST_LineSubString(a.geometry, 0.3,0.3004)), 70, 'quad_segs=4 join=mitre'), b.geometry)
) line_rights
)
SELECT adm0_l,
adm0_r,
geometry,
maritime,
2::integer AS admin_level,
disputed
FROM (
SELECT b.adm0_a3 AS adm0_l,
r.adm0_r AS adm0_r,
r.geometry,
r.maritime,
r.disputed
FROM rights AS r
LEFT JOIN country_osm_polyg AS b
-- Create short line on the left of the boundary (mergedline) and find state where line lies.
ON ST_Within(
ST_OffsetCurve(
(ST_LineSubString(r.geometry, 0.4,0.4004)), -70, 'quad_segs=4 join=mitre'), b.geometry)
) both_lines
);
CREATE INDEX IF NOT EXISTS osm_border_linestring_adm_geom_idx
ON osm_border_linestring_adm
USING GIST (geometry);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 KiB

After

Width:  |  Height:  |  Size: 668 KiB

View File

@ -1,70 +1,82 @@
generalized_tables: generalized_tables:
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen11 # etldoc: osm_border_disp_linestring_gen_z2 -> osm_border_disp_linestring_gen_z1
border_disp_linestring_gen11: border_disp_linestring_gen_z1:
source: border_disp_linestring source: border_disp_linestring_gen_z2
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 9600 tolerance: ZRES2
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen10 # etldoc: osm_border_disp_linestring_gen_z3 -> osm_border_disp_linestring_gen_z2
border_disp_linestring_gen10: border_disp_linestring_gen_z2:
source: border_disp_linestring source: border_disp_linestring_gen_z3
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 4800 tolerance: ZRES3
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen9 # etldoc: osm_border_disp_linestring_gen_z4 -> osm_border_disp_linestring_gen_z3
border_disp_linestring_gen9: border_disp_linestring_gen_z3:
source: border_disp_linestring source: border_disp_linestring_gen_z4
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 2400 tolerance: ZRES4
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen8 # etldoc: osm_border_disp_linestring_gen_z5 -> osm_border_disp_linestring_gen_z4
border_disp_linestring_gen8: border_disp_linestring_gen_z4:
source: border_disp_linestring source: border_disp_linestring_gen_z5
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 1200 tolerance: ZRES5
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen7 # etldoc: osm_border_disp_linestring_gen_z6 -> osm_border_disp_linestring_gen_z5
border_disp_linestring_gen7: border_disp_linestring_gen_z5:
source: border_disp_linestring source: border_disp_linestring_gen_z6
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 600 tolerance: ZRES6
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen6 # etldoc: osm_border_disp_linestring_gen_z7 -> osm_border_disp_linestring_gen_z6
border_disp_linestring_gen6: border_disp_linestring_gen_z6:
source: border_disp_linestring source: border_disp_linestring_gen_z7
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 300 tolerance: ZRES7
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen5 # etldoc: osm_border_disp_linestring_gen_z8 -> osm_border_disp_linestring_gen_z7
border_disp_linestring_gen5: border_disp_linestring_gen_z7:
source: border_disp_linestring source: border_disp_linestring_gen_z8
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 160 tolerance: ZRES8
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen4 # etldoc: osm_border_disp_linestring_gen_z9 -> osm_border_disp_linestring_gen_z8
border_disp_linestring_gen4: border_disp_linestring_gen_z8:
source: border_disp_linestring source: border_disp_linestring_gen_z9
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 80 tolerance: ZRES9
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen3 # etldoc: osm_border_disp_linestring_gen_z10 -> osm_border_disp_linestring_gen_z9
border_disp_linestring_gen3: border_disp_linestring_gen_z9:
source: border_disp_linestring source: border_disp_linestring_gen_z10
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 40 tolerance: ZRES10
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen2 # etldoc: osm_border_disp_linestring_gen_z11 -> osm_border_disp_linestring_gen_z10
border_disp_linestring_gen2: border_disp_linestring_gen_z10:
source: border_disp_linestring source: border_disp_linestring_gen_z11
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 20 tolerance: ZRES11
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen1 # etldoc: osm_border_disp_linestring_gen_z12 -> osm_border_disp_linestring_gen_z11
border_disp_linestring_gen1: border_disp_linestring_gen_z11:
source: border_disp_linestring_gen_z12
sql_filter: admin_level = 2
tolerance: ZRES12
# etldoc: osm_border_disp_linestring_gen_z13 -> osm_border_disp_linestring_gen_z12
border_disp_linestring_gen_z12:
source: border_disp_linestring_gen_z13
sql_filter: admin_level = 2
tolerance: ZRES13
# etldoc: osm_border_disp_linestring -> osm_border_disp_linestring_gen_z13
border_disp_linestring_gen_z13:
source: border_disp_linestring source: border_disp_linestring
sql_filter: admin_level = 2 sql_filter: admin_level = 2
tolerance: 10 tolerance: ZRES14
# etldoc: osm_border_disp_relation -> osm_border_disp_linestring # etldoc: osm_border_disp_relation -> osm_border_disp_linestring
border_disp_linestring: border_disp_linestring:
@ -110,4 +122,3 @@ tables:
#admin_level: ['2'] #admin_level: ['2']
admin_level: [__any__] admin_level: [__any__]
claimed_by: [__any__] claimed_by: [__any__]

View File

@ -1,95 +1,120 @@
-- etldoc: layer_building[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: layer_building[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_building | <z13> z13 | <z14_> z14+ " ] ; -- etldoc: label="layer_building | <z13> z13 | <z14_> z14+ " ] ;
CREATE INDEX IF NOT EXISTS osm_building_relation_building_idx ON osm_building_relation(building) WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon'; CREATE INDEX IF NOT EXISTS osm_building_relation_building_idx ON osm_building_relation (building) WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon';
CREATE INDEX IF NOT EXISTS osm_building_relation_member_idx ON osm_building_relation(member) WHERE role = 'outline'; CREATE INDEX IF NOT EXISTS osm_building_relation_member_idx ON osm_building_relation (member) WHERE role = 'outline';
CREATE OR REPLACE VIEW osm_all_buildings AS ( CREATE OR REPLACE VIEW osm_all_buildings AS
-- etldoc: osm_building_relation -> layer_building:z14_ (
-- Buildings built from relations SELECT
SELECT member AS osm_id, geometry, -- etldoc: osm_building_relation -> layer_building:z14_
COALESCE(CleanNumeric(height), CleanNumeric(buildingheight)) as height, -- Buildings built from relations
COALESCE(CleanNumeric(min_height), CleanNumeric(buildingmin_height)) as min_height, member AS osm_id,
COALESCE(CleanNumeric(levels), CleanNumeric(buildinglevels)) as levels, geometry,
COALESCE(CleanNumeric(min_level), CleanNumeric(buildingmin_level)) as min_level, COALESCE(CleanNumeric(height), CleanNumeric(buildingheight)) AS height,
nullif(material, '') AS material, COALESCE(CleanNumeric(min_height), CleanNumeric(buildingmin_height)) AS min_height,
nullif(colour, '') AS colour, COALESCE(CleanNumeric(levels), CleanNumeric(buildinglevels)) AS levels,
FALSE as hide_3d COALESCE(CleanNumeric(min_level), CleanNumeric(buildingmin_level)) AS min_level,
FROM nullif(material, '') AS material,
osm_building_relation WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon' nullif(colour, '') AS colour,
UNION ALL FALSE AS hide_3d
FROM osm_building_relation
WHERE building = ''
AND ST_GeometryType(geometry) = 'ST_Polygon'
UNION ALL
-- etldoc: osm_building_polygon -> layer_building:z14_ SELECT
-- Standalone buildings -- etldoc: osm_building_polygon -> layer_building:z14_
SELECT obp.osm_id, obp.geometry, -- Standalone buildings
COALESCE(CleanNumeric(obp.height), CleanNumeric(obp.buildingheight)) as height, obp.osm_id,
COALESCE(CleanNumeric(obp.min_height), CleanNumeric(obp.buildingmin_height)) as min_height, obp.geometry,
COALESCE(CleanNumeric(obp.levels), CleanNumeric(obp.buildinglevels)) as levels, COALESCE(CleanNumeric(obp.height), CleanNumeric(obp.buildingheight)) AS height,
COALESCE(CleanNumeric(obp.min_level), CleanNumeric(obp.buildingmin_level)) as min_level, COALESCE(CleanNumeric(obp.min_height), CleanNumeric(obp.buildingmin_height)) AS min_height,
nullif(obp.material, '') AS material, COALESCE(CleanNumeric(obp.levels), CleanNumeric(obp.buildinglevels)) AS levels,
nullif(obp.colour, '') AS colour, COALESCE(CleanNumeric(obp.min_level), CleanNumeric(obp.buildingmin_level)) AS min_level,
obr.role IS NOT NULL AS hide_3d nullif(obp.material, '') AS material,
FROM nullif(obp.colour, '') AS colour,
osm_building_polygon obp obr.role IS NOT NULL AS hide_3d
LEFT JOIN osm_building_relation obr ON FROM osm_building_polygon obp
obp.osm_id >= 0 AND LEFT JOIN osm_building_relation obr ON
obr.member = obp.osm_id AND obp.osm_id >= 0 AND
obr.role = 'outline' obr.member = obp.osm_id AND
WHERE ST_GeometryType(obp.geometry) IN ('ST_Polygon', 'ST_MultiPolygon') obr.role = 'outline'
); WHERE ST_GeometryType(obp.geometry) IN ('ST_Polygon', 'ST_MultiPolygon')
);
CREATE OR REPLACE FUNCTION layer_building(bbox geometry, zoom_level int) CREATE OR REPLACE FUNCTION layer_building(bbox geometry, zoom_level int)
RETURNS TABLE(geometry geometry, osm_id bigint, render_height int, render_min_height int, colour text, hide_3d boolean) AS $$ RETURNS TABLE
SELECT geometry, osm_id, render_height, render_min_height, (
geometry geometry,
osm_id bigint,
render_height int,
render_min_height int,
colour text,
hide_3d boolean
)
AS
$$
SELECT geometry,
osm_id,
render_height,
render_min_height,
COALESCE(colour, CASE material COALESCE(colour, CASE material
-- Ordered by count from taginfo -- Ordered by count from taginfo
WHEN 'cement_block' THEN '#6a7880' WHEN 'cement_block' THEN '#6a7880'
WHEN 'brick' THEN '#bd8161' WHEN 'brick' THEN '#bd8161'
WHEN 'plaster' THEN '#dadbdb' WHEN 'plaster' THEN '#dadbdb'
WHEN 'wood' THEN '#d48741' WHEN 'wood' THEN '#d48741'
WHEN 'concrete' THEN '#d3c2b0' WHEN 'concrete' THEN '#d3c2b0'
WHEN 'metal' THEN '#b7b1a6' WHEN 'metal' THEN '#b7b1a6'
WHEN 'stone' THEN '#b4a995' WHEN 'stone' THEN '#b4a995'
WHEN 'mud' THEN '#9d8b75' WHEN 'mud' THEN '#9d8b75'
WHEN 'steel' THEN '#b7b1a6' -- same as metal WHEN 'steel' THEN '#b7b1a6' -- same as metal
WHEN 'glass' THEN '#5a81a0' WHEN 'glass' THEN '#5a81a0'
WHEN 'traditional' THEN '#bd8161' -- same as brick WHEN 'traditional' THEN '#bd8161' -- same as brick
WHEN 'masonry' THEN '#bd8161' -- same as brick WHEN 'masonry' THEN '#bd8161' -- same as brick
WHEN 'Brick' THEN '#bd8161' -- same as brick WHEN 'Brick' THEN '#bd8161' -- same as brick
WHEN 'tin' THEN '#b7b1a6' -- same as metal WHEN 'tin' THEN '#b7b1a6' -- same as metal
WHEN 'timber_framing' THEN '#b3b0a9' WHEN 'timber_framing' THEN '#b3b0a9'
WHEN 'sandstone' THEN '#b4a995' -- same as stone WHEN 'sandstone' THEN '#b4a995' -- same as stone
WHEN 'clay' THEN '#9d8b75' -- same as mud WHEN 'clay' THEN '#9d8b75' -- same as mud
END) AS colour, END) AS colour,
CASE WHEN hide_3d THEN TRUE END AS hide_3d CASE WHEN hide_3d THEN TRUE END AS hide_3d
FROM ( FROM (
-- etldoc: osm_building_polygon_gen1 -> layer_building:z13 SELECT
SELECT -- etldoc: osm_building_block_gen_z13 -> layer_building:z13
osm_id, geometry, osm_id,
NULL::int AS render_height, NULL::int AS render_min_height, geometry,
NULL::text AS material, NULL::text AS colour, NULL::int AS render_height,
FALSE AS hide_3d NULL::int AS render_min_height,
FROM osm_building_polygon_gen1 NULL::text AS material,
WHERE zoom_level = 13 AND geometry && bbox NULL::text AS colour,
UNION ALL FALSE AS hide_3d
-- etldoc: osm_building_polygon -> layer_building:z14_ FROM osm_building_block_gen_z13
SELECT DISTINCT ON (osm_id) WHERE zoom_level = 13
osm_id, geometry, AND geometry && bbox
ceil(COALESCE(height, levels*3.66, 5))::int AS render_height, UNION ALL
floor(COALESCE(min_height, min_level*3.66, 0))::int AS render_min_height, SELECT
material, -- etldoc: osm_building_polygon -> layer_building:z14_
colour, DISTINCT ON (osm_id) osm_id,
hide_3d geometry,
FROM osm_all_buildings ceil(COALESCE(height, levels * 3.66, 5))::int AS render_height,
WHERE floor(COALESCE(min_height, min_level * 3.66, 0))::int AS render_min_height,
(levels IS NULL OR levels < 1000) AND material,
(min_level IS NULL OR min_level < 1000) AND colour,
(height IS NULL OR height < 3000) AND hide_3d
(min_height IS NULL OR min_height < 3000) AND FROM osm_all_buildings
zoom_level >= 14 AND geometry && bbox WHERE (levels IS NULL OR levels < 1000)
) AS zoom_levels AND (min_level IS NULL OR min_level < 1000)
ORDER BY render_height ASC, ST_YMin(geometry) DESC; AND (height IS NULL OR height < 3000)
$$ AND (min_height IS NULL OR min_height < 3000)
LANGUAGE SQL IMMUTABLE; AND zoom_level >= 14
AND geometry && bbox
) AS zoom_levels
ORDER BY render_height ASC, ST_YMin(geometry) DESC;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE
;
-- not handled: where a building outline covers building parts -- not handled: where a building outline covers building parts

View File

@ -20,6 +20,7 @@ layer:
hide_3d: | hide_3d: |
If True, building (part) should not be rendered in 3D. Currently, [building outlines](https://wiki.openstreetmap.org/wiki/Simple_3D_buildings) are marked as hide_3d. If True, building (part) should not be rendered in 3D. Currently, [building outlines](https://wiki.openstreetmap.org/wiki/Simple_3D_buildings) are marked as hide_3d.
schema: schema:
- ./update_building.sql
- ./building.sql - ./building.sql
datasources: datasources:
- type: imposm3 - type: imposm3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,9 +1,9 @@
generalized_tables: #generalized_tables:
# etldoc: imposm3 -> osm_building_polygon_gen1 # # etldoc: imposm3 -> osm_building_polygon_gen1
building_polygon_gen1: # building_polygon_gen1:
source: building_polygon # source: building_polygon
sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry) # sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry)
tolerance: ZRES14 # tolerance: ZRES14
tables: tables:
# etldoc: imposm3 -> osm_building_polygon # etldoc: imposm3 -> osm_building_polygon

View File

@ -0,0 +1,185 @@
DROP TRIGGER IF EXISTS trigger_refresh ON buildings.updates;
DROP TRIGGER IF EXISTS trigger_flag ON osm_building_polygon;
-- Creating aggregated building blocks with removed small polygons and small
-- holes. Aggregated polygons are simplified by Visvalingam-Whyatt algorithm.
-- Aggregating is made block by block using country_osm_grid polygon table.
-- Function returning recordset for matview.
-- Returning recordset of buildings aggregates by zres 14, with removed small
-- holes and with removed small buildings/blocks.
CREATE OR REPLACE FUNCTION osm_building_block_gen1()
RETURNS table
(
osm_id bigint,
geometry geometry
)
AS
$$
DECLARE
zres14 float := Zres(14);
zres12 float := Zres(12);
zres14vw float := Zres(14) * Zres(14);
polyg_world record;
BEGIN
FOR polyg_world IN
SELECT ST_Transform(country.geometry, 3857) AS geometry
FROM country_osm_grid country
LOOP
FOR osm_id, geometry IN
WITH dta AS ( -- CTE is used because of optimization
SELECT o.osm_id,
o.geometry,
ST_ClusterDBSCAN(o.geometry, eps := zres14, minpoints := 1) OVER () cid
FROM osm_building_polygon o
WHERE ST_Intersects(o.geometry, polyg_world.geometry)
)
SELECT (array_agg(dta.osm_id))[1] AS osm_id,
ST_Buffer(
ST_Union(
ST_Buffer(
ST_SnapToGrid(dta.geometry, 0.000001)
, zres14, 'join=mitre')
)
, -zres14, 'join=mitre') AS geometry
FROM dta
GROUP BY cid
LOOP
-- removing holes smaller than
IF ST_NumInteriorRings(geometry) > 0 THEN -- only from geometries wih holes
geometry := (
-- there are some multi-geometries in this layer
SELECT ST_Collect(gn)
FROM (
-- in some cases are "holes" NULL, because all holes are smaller than
SELECT COALESCE(
-- exterior ring
ST_MakePolygon(ST_ExteriorRing(dmp.geom), holes),
ST_MakePolygon(ST_ExteriorRing(dmp.geom))
) gn
FROM ST_Dump(geometry) dmp, -- 1 dump polygons
LATERAL (
SELECT array_agg(ST_Boundary(rg.geom)) holes -- 2 create array
FROM ST_DumpRings(dmp.geom) rg -- 3 from rings
WHERE rg.path[1] > 0 -- 5 except inner ring
AND ST_Area(rg.geom) >= power(zres12, 2) -- 4 bigger than
) holes
) new_geom
);
END IF;
IF ST_Area(geometry) < power(zres12, 2) THEN
CONTINUE;
END IF;
-- simplify
geometry := ST_SimplifyVW(geometry, zres14vw);
RETURN NEXT;
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql STABLE
STRICT
PARALLEL SAFE;
DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen1_dup CASCADE;
CREATE MATERIALIZED VIEW osm_building_block_gen1_dup AS
SELECT *
FROM osm_building_block_gen1();
CREATE INDEX ON osm_building_block_gen1_dup USING gist (geometry);
-- etldoc: osm_building_polygon -> osm_building_block_gen_z13
DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen_z13;
CREATE MATERIALIZED VIEW osm_building_block_gen_z13 AS
(
WITH
counts AS (
SELECT count(osm_id) AS counts,
osm_id
FROM osm_building_block_gen1_dup
GROUP BY osm_id
),
duplicates AS (
SELECT counts.osm_id
FROM counts
WHERE counts.counts > 1
)
SELECT osm.osm_id,
ST_Union(
ST_MakeValid(osm.geometry)) AS geometry
FROM osm_building_block_gen1_dup osm,
duplicates
WHERE osm.osm_id = duplicates.osm_id
GROUP BY osm.osm_id
UNION ALL
SELECT osm.osm_id,
osm.geometry
FROM osm_building_block_gen1_dup osm,
counts
WHERE counts.counts = 1
AND osm.osm_id = counts.osm_id
);
CREATE INDEX ON osm_building_block_gen_z13 USING gist (geometry);
CREATE UNIQUE INDEX ON osm_building_block_gen_z13 USING btree (osm_id);
-- Handle updates
CREATE SCHEMA IF NOT EXISTS buildings;
CREATE TABLE IF NOT EXISTS buildings.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION buildings.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO buildings.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION buildings.refresh() RETURNS trigger AS
$$
DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh buildings block';
REFRESH MATERIALIZED VIEW osm_building_block_gen1_dup;
REFRESH MATERIALIZED VIEW osm_building_block_gen_z13;
-- noinspection SqlWithoutWhere
DELETE FROM buildings.updates;
RAISE LOG 'Update buildings block done in %', age(clock_timestamp(), t);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE
ON osm_building_polygon
FOR EACH STATEMENT
EXECUTE PROCEDURE buildings.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT
ON buildings.updates
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE buildings.refresh();

View File

@ -0,0 +1,23 @@
-- etldoc: layer_housenumber[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_housenumber | <z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_housenumber(bbox geometry, zoom_level integer)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
housenumber text
)
AS
$$
SELECT
-- etldoc: osm_housenumber_point -> layer_housenumber:z14_
osm_id,
geometry,
housenumber
FROM osm_housenumber_point
WHERE zoom_level >= 14
AND geometry && bbox;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -13,7 +13,7 @@ layer:
query: (SELECT geometry, housenumber FROM layer_housenumber(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, housenumber FROM layer_housenumber(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./housenumber_centroid.sql - ./housenumber_centroid.sql
- ./layer.sql - ./housenumber.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,51 +1,91 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_housenumber_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_housenumber_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_housenumber_point;
DROP TRIGGER IF EXISTS trigger_refresh ON housenumber.updates; DROP TRIGGER IF EXISTS trigger_refresh ON housenumber.updates;
-- etldoc: osm_housenumber_point -> osm_housenumber_point
CREATE OR REPLACE FUNCTION convert_housenumber_point() RETURNS VOID AS $$
BEGIN
UPDATE osm_housenumber_point
SET geometry =
CASE WHEN ST_NPoints(ST_ConvexHull(geometry))=ST_NPoints(geometry)
THEN ST_Centroid(geometry)
ELSE ST_PointOnSurface(geometry)
END
WHERE ST_GeometryType(geometry) <> 'ST_Point';
END;
$$ LANGUAGE plpgsql;
SELECT convert_housenumber_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS housenumber; CREATE SCHEMA IF NOT EXISTS housenumber;
CREATE TABLE IF NOT EXISTS housenumber.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS housenumber.osm_ids
CREATE OR REPLACE FUNCTION housenumber.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_housenumber_point -> osm_housenumber_point
CREATE OR REPLACE FUNCTION convert_housenumber_point(full_update boolean) RETURNS void AS
$$
UPDATE osm_housenumber_point
SET geometry =
CASE
WHEN ST_NPoints(ST_ConvexHull(geometry)) = ST_NPoints(geometry)
THEN ST_Centroid(geometry)
ELSE ST_PointOnSurface(geometry)
END
WHERE (full_update OR osm_id IN (SELECT osm_id FROM housenumber.osm_ids))
AND ST_GeometryType(geometry) <> 'ST_Point'
AND ST_IsValid(geometry);
$$ LANGUAGE SQL;
SELECT convert_housenumber_point(true);
-- Handle updates
CREATE OR REPLACE FUNCTION housenumber.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO housenumber.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO housenumber.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO housenumber.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS housenumber.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION housenumber.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO housenumber.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION housenumber.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION housenumber.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh housenumber'; RAISE LOG 'Refresh housenumber';
PERFORM convert_housenumber_point(); PERFORM convert_housenumber_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM housenumber.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM housenumber.updates; DELETE FROM housenumber.updates;
RETURN null;
END; RAISE LOG 'Refresh housenumber done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_housenumber_point
FOR EACH ROW
EXECUTE PROCEDURE housenumber.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_housenumber_point AFTER INSERT OR UPDATE OR DELETE
ON osm_housenumber_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE housenumber.flag(); EXECUTE PROCEDURE housenumber.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON housenumber.updates AFTER INSERT
ON housenumber.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE housenumber.refresh(); EXECUTE PROCEDURE housenumber.refresh();

View File

@ -1,12 +0,0 @@
-- etldoc: layer_housenumber[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_housenumber | <z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_housenumber(bbox geometry, zoom_level integer)
RETURNS TABLE(osm_id bigint, geometry geometry, housenumber text) AS $$
-- etldoc: osm_housenumber_point -> layer_housenumber:z14_
SELECT osm_id, geometry, housenumber FROM osm_housenumber_point
WHERE zoom_level >= 14 AND geometry && bbox;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 366 KiB

View File

@ -0,0 +1,349 @@
DROP TABLE IF EXISTS osm_landcover_gen_z7;
DROP TABLE IF EXISTS osm_landcover_gen_z8;
DROP TABLE IF EXISTS osm_landcover_gen_z9;
DROP TABLE IF EXISTS osm_landcover_gen_z10;
DROP TABLE IF EXISTS osm_landcover_gen_z11;
DROP TABLE IF EXISTS osm_landcover_gen_z12;
DROP TABLE IF EXISTS osm_landcover_gen_z13;
DROP TABLE IF EXISTS simplify_vw_z7 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z8 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z9 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z10 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z11 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z12 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z13 CASCADE;
-- etldoc: osm_landcover_polygon -> osm_landcover_gen_z13
CREATE TABLE simplify_vw_z13 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(13),2)),
0.001)) AS geometry
FROM osm_landcover_polygon
WHERE ST_Area(geometry) > power(zres(10),2)
);
CREATE INDEX ON simplify_vw_z13 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z13 AS
(
SELECT subclass,
ST_MakeValid(
(ST_dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z13
WHERE ST_NPoints(geometry) < 50
AND subclass IN ('wood', 'forest')) union_geom50
GROUP BY subclass,
cid
UNION ALL
SELECT subclass, ST_MakeValid((ST_dump(ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z13
WHERE ST_NPoints(geometry) >= 50
AND ST_NPoints(geometry) < 300
AND subclass IN ('wood', 'forest')) union_geom300
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z13
WHERE (ST_NPoints(geometry) >= 300 AND subclass IN ('wood', 'forest'))
OR (subclass NOT IN ('wood', 'forest'))
);
CREATE INDEX ON osm_landcover_gen_z13 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z13 -> osm_landcover_gen_z12
CREATE TABLE simplify_vw_z12 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(12),2)),
0.001)) AS geometry
FROM simplify_vw_z13
WHERE ST_Area(geometry) > power(zres(9),2)
);
CREATE INDEX ON simplify_vw_z12 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z12 AS
(
SELECT subclass,
ST_MakeValid(
(ST_dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z12
WHERE ST_NPoints(geometry) < 50
AND subclass IN ('wood', 'forest')) union_geom50
GROUP BY subclass,
cid
UNION ALL
SELECT subclass, ST_MakeValid((ST_dump(ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z12
WHERE ST_NPoints(geometry) >= 50
AND ST_NPoints(geometry) < 300
AND subclass IN ('wood', 'forest')) union_geom300
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z12
WHERE (ST_NPoints(geometry) >= 300 AND subclass IN ('wood', 'forest'))
OR (subclass NOT IN ('wood', 'forest'))
);
CREATE INDEX ON osm_landcover_gen_z12 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z12 -> osm_landcover_gen_z11
CREATE TABLE simplify_vw_z11 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(11),2)),
0.001)) AS geometry
FROM simplify_vw_z12
WHERE ST_Area(geometry) > power(zres(8),2)
);
CREATE INDEX ON simplify_vw_z11 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z11 AS
(
SELECT subclass,
ST_MakeValid(
(ST_dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z11
WHERE ST_NPoints(geometry) < 50
AND subclass IN ('wood', 'forest')) union_geom50
GROUP BY subclass,
cid
UNION ALL
SELECT subclass, ST_MakeValid((ST_dump(ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z11
WHERE ST_NPoints(geometry) >= 50
AND ST_NPoints(geometry) < 300
AND subclass IN ('wood', 'forest')) union_geom300
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z11
WHERE (ST_NPoints(geometry) >= 300 AND subclass IN ('wood', 'forest'))
OR (subclass NOT IN ('wood', 'forest'))
);
CREATE INDEX ON osm_landcover_gen_z11 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z11 -> osm_landcover_gen_z10
CREATE TABLE simplify_vw_z10 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(10),2)),
0.001)) AS geometry
FROM simplify_vw_z11
WHERE ST_Area(geometry) > power(zres(8),2)
);
CREATE INDEX ON simplify_vw_z10 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z10 AS
(
SELECT subclass,
ST_MakeValid(
(ST_dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z10
WHERE ST_NPoints(geometry) < 50
AND subclass IN ('wood', 'forest')) union_geom50
GROUP BY subclass,
cid
UNION ALL
SELECT subclass, ST_MakeValid((ST_dump(ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z10
WHERE ST_NPoints(geometry) >= 50
AND ST_NPoints(geometry) < 300
AND subclass IN ('wood', 'forest')) union_geom300
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z10
WHERE (ST_NPoints(geometry) >= 300 AND subclass IN ('wood', 'forest'))
OR (subclass NOT IN ('wood', 'forest'))
);
CREATE INDEX ON osm_landcover_gen_z10 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z10 -> osm_landcover_gen_z9
CREATE TABLE simplify_vw_z9 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(9),2)),
0.001)) AS geometry
FROM simplify_vw_z10
WHERE ST_Area(geometry) > power(zres(7),2)
);
CREATE INDEX ON simplify_vw_z9 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z9 AS
(
SELECT subclass,
ST_MakeValid(
(ST_dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z9
WHERE ST_NPoints(geometry) < 50
AND subclass IN ('wood', 'forest')) union_geom50
GROUP BY subclass,
cid
UNION ALL
SELECT subclass, ST_MakeValid((ST_dump(ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z9
WHERE ST_NPoints(geometry) >= 50
AND ST_NPoints(geometry) < 300
AND subclass IN ('wood', 'forest')) union_geom300
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
ST_MakeValid(
(ST_Dump(
ST_Union(geometry))).geom) AS geometry
FROM (
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) over () AS cid, geometry
FROM simplify_vw_z9
WHERE ST_NPoints(geometry) >= 300
AND subclass IN ('wood', 'forest')) union_geom_rest
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z9
WHERE subclass NOT IN ('wood', 'forest')
);
CREATE INDEX ON osm_landcover_gen_z9 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z9 -> osm_landcover_gen_z8
CREATE TABLE simplify_vw_z8 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(8),2)),
0.001)) AS geometry
FROM simplify_vw_z9
WHERE ST_Area(geometry) > power(zres(6),2)
);
CREATE INDEX ON simplify_vw_z8 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z8 AS
(
SELECT subclass,
ST_MakeValid(
(ST_Dump(
ST_Union(geometry))).geom) AS geometry
FROM
(
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) OVER () AS cid,
geometry
FROM simplify_vw_z8
) union_geom
GROUP BY subclass,
cid
UNION ALL
SELECT subclass,
geometry
FROM simplify_vw_z8
WHERE subclass NOT IN ('wood', 'forest')
);
CREATE INDEX ON osm_landcover_gen_z8 USING GIST (geometry);
-- etldoc: osm_landcover_gen_z8 -> osm_landcover_gen_z7
CREATE TABLE simplify_vw_z7 AS
(
SELECT subclass,
ST_MakeValid(
ST_SnapToGrid(
ST_SimplifyVW(geometry, power(zres(7),2)),
0.001)) AS geometry
FROM simplify_vw_z8
WHERE ST_Area(geometry) > power(zres(5),2)
);
CREATE INDEX ON simplify_vw_z7 USING GIST (geometry);
CREATE TABLE osm_landcover_gen_z7 AS
(
SELECT subclass,
ST_MakeValid(
(ST_Dump(
ST_Union(geometry))).geom) AS geometry
FROM
(
SELECT subclass,
ST_ClusterDBSCAN(geometry, eps := 0, minpoints := 1) OVER () AS cid,
geometry
FROM simplify_vw_z7
) union_geom
GROUP BY subclass,
cid
);
CREATE INDEX ON osm_landcover_gen_z7 USING GIST (geometry);
DROP TABLE IF EXISTS simplify_vw_z7 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z8 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z9 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z10 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z11 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z12 CASCADE;
DROP TABLE IF EXISTS simplify_vw_z13 CASCADE;

View File

@ -9,127 +9,365 @@
--); --);
--CREATE INDEX IF NOT EXISTS landcover_grouped_gen2_geometry_idx ON landcover_grouped_gen2 USING gist(geometry); --CREATE INDEX IF NOT EXISTS landcover_grouped_gen2_geometry_idx ON landcover_grouped_gen2 USING gist(geometry);
CREATE OR REPLACE FUNCTION landcover_class(subclass VARCHAR) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION landcover_class(subclass varchar) RETURNS text AS
SELECT CASE
%%FIELD_MAPPING: class %%
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE PARALLEL SAFE; %%FIELD_MAPPING: class %%
END;
$$ LANGUAGE SQL IMMUTABLE
-- STRICT
PARALLEL SAFE;
-- etldoc: ne_110m_glaciated_areas -> landcover_z0 -- ne_50m_antarctic_ice_shelves_polys
CREATE OR REPLACE VIEW landcover_z0 AS ( -- etldoc: ne_50m_antarctic_ice_shelves_polys -> ne_50m_antarctic_ice_shelves_polys_gen_z4
SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_110m_glaciated_areas DROP MATERIALIZED VIEW IF EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z4 CASCADE;
); CREATE MATERIALIZED VIEW ne_50m_antarctic_ice_shelves_polys_gen_z4 AS
(
SELECT
ST_Simplify(geometry, ZRes(6)) as geometry,
'ice_shelf'::text AS subclass
FROM ne_50m_antarctic_ice_shelves_polys
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z4_idx ON ne_50m_antarctic_ice_shelves_polys_gen_z4 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z2 AS ( -- ne_110m_glaciated_areas
-- etldoc: ne_50m_glaciated_areas -> landcover_z2 -- etldoc: ne_110m_glaciated_areas -> ne_110m_glaciated_areas_gen_z1
SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_50m_glaciated_areas DROP MATERIALIZED VIEW IF EXISTS ne_110m_glaciated_areas_gen_z1 CASCADE;
UNION ALL CREATE MATERIALIZED VIEW ne_110m_glaciated_areas_gen_z1 AS
-- etldoc: ne_50m_antarctic_ice_shelves_polys -> landcover_z2 (
SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass FROM ne_50m_antarctic_ice_shelves_polys SELECT
); ST_Simplify(geometry, ZRes(3)) as geometry,
'glacier'::text AS subclass
FROM ne_110m_glaciated_areas
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_110m_glaciated_areas_gen_z1_idx ON ne_110m_glaciated_areas_gen_z1 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z5 AS ( -- etldoc: ne_110m_glaciated_areas_gen_z1 -> ne_110m_glaciated_areas_gen_z0
-- etldoc: ne_10m_glaciated_areas -> landcover_z5 DROP MATERIALIZED VIEW IF EXISTS ne_110m_glaciated_areas_gen_z0 CASCADE;
SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_10m_glaciated_areas CREATE MATERIALIZED VIEW ne_110m_glaciated_areas_gen_z0 AS
UNION ALL (
-- etldoc: ne_10m_antarctic_ice_shelves_polys -> landcover_z5 SELECT
SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass FROM ne_10m_antarctic_ice_shelves_polys ST_Simplify(geometry, ZRes(2)) as geometry,
); subclass
FROM ne_110m_glaciated_areas_gen_z1
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_110m_glaciated_areas_gen_z0_idx ON ne_110m_glaciated_areas_gen_z0 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z7 AS ( -- etldoc: ne_50m_antarctic_ice_shelves_polys_gen_z4 -> ne_50m_antarctic_ice_shelves_polys_gen_z3
-- etldoc: osm_landcover_polygon_gen7 -> landcover_z7 DROP MATERIALIZED VIEW IF EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z3 CASCADE;
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen7 CREATE MATERIALIZED VIEW ne_50m_antarctic_ice_shelves_polys_gen_z3 AS
); (
SELECT
ST_Simplify(geometry, ZRes(5)) as geometry,
subclass
FROM ne_50m_antarctic_ice_shelves_polys_gen_z4
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z3_idx ON ne_50m_antarctic_ice_shelves_polys_gen_z3 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z8 AS ( -- etldoc: ne_50m_antarctic_ice_shelves_polys_gen_z3 -> ne_50m_antarctic_ice_shelves_polys_gen_z2
-- etldoc: osm_landcover_polygon_gen6 -> landcover_z8 DROP MATERIALIZED VIEW IF EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z2 CASCADE;
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen6 CREATE MATERIALIZED VIEW ne_50m_antarctic_ice_shelves_polys_gen_z2 AS
); (
SELECT
ST_Simplify(geometry, ZRes(4)) as geometry,
subclass
FROM ne_50m_antarctic_ice_shelves_polys_gen_z3
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_antarctic_ice_shelves_polys_gen_z2_idx ON ne_50m_antarctic_ice_shelves_polys_gen_z2 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z9 AS ( -- ne_50m_glaciated_areas
-- etldoc: osm_landcover_polygon_gen5 -> landcover_z9 -- etldoc: ne_50m_glaciated_areas -> ne_50m_glaciated_areas_gen_z4
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen5 DROP MATERIALIZED VIEW IF EXISTS ne_50m_glaciated_areas_gen_z4 CASCADE;
); CREATE MATERIALIZED VIEW ne_50m_glaciated_areas_gen_z4 AS
(
SELECT
ST_Simplify(geometry, ZRes(6)) as geometry,
'glacier'::text AS subclass
FROM ne_50m_glaciated_areas
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_glaciated_areas_gen_z4_idx ON ne_50m_glaciated_areas_gen_z4 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z10 AS ( -- etldoc: ne_50m_glaciated_areas_gen_z4 -> ne_50m_glaciated_areas_gen_z3
-- etldoc: osm_landcover_polygon_gen4 -> landcover_z10 DROP MATERIALIZED VIEW IF EXISTS ne_50m_glaciated_areas_gen_z3 CASCADE;
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen4 CREATE MATERIALIZED VIEW ne_50m_glaciated_areas_gen_z3 AS
); (
SELECT
ST_Simplify(geometry, ZRes(5)) as geometry,
subclass
FROM ne_50m_glaciated_areas_gen_z4
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_glaciated_areas_gen_z3_idx ON ne_50m_glaciated_areas_gen_z3 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z11 AS ( -- etldoc: ne_50m_glaciated_areas_gen_z3 -> ne_50m_glaciated_areas_gen_z2
-- etldoc: osm_landcover_polygon_gen3 -> landcover_z11 DROP MATERIALIZED VIEW IF EXISTS ne_50m_glaciated_areas_gen_z2 CASCADE;
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen3 CREATE MATERIALIZED VIEW ne_50m_glaciated_areas_gen_z2 AS
); (
SELECT
ST_Simplify(geometry, ZRes(4)) as geometry,
subclass
FROM ne_50m_glaciated_areas_gen_z3
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_glaciated_areas_gen_z2_idx ON ne_50m_glaciated_areas_gen_z2 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z12 AS ( -- ne_10m_glaciated_areas
-- etldoc: osm_landcover_polygon_gen2 -> landcover_z12 -- etldoc: ne_10m_glaciated_areas -> ne_10m_glaciated_areas_gen_z6
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen2 DROP MATERIALIZED VIEW IF EXISTS ne_10m_glaciated_areas_gen_z6 CASCADE;
); CREATE MATERIALIZED VIEW ne_10m_glaciated_areas_gen_z6 AS
(
SELECT
ST_Simplify(geometry, ZRes(8)) as geometry,
'glacier'::text AS subclass
FROM ne_10m_glaciated_areas
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_10m_glaciated_areas_gen_z6_idx ON ne_10m_glaciated_areas_gen_z6 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z13 AS ( -- etldoc: ne_10m_glaciated_areas_gen_z6 -> ne_10m_glaciated_areas_gen_z5
-- etldoc: osm_landcover_polygon_gen1 -> landcover_z13 DROP MATERIALIZED VIEW IF EXISTS ne_10m_glaciated_areas_gen_z5 CASCADE;
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen1 CREATE MATERIALIZED VIEW ne_10m_glaciated_areas_gen_z5 AS
); (
SELECT
ST_Simplify(geometry, ZRes(7)) as geometry,
subclass
FROM ne_10m_glaciated_areas_gen_z6
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_10m_glaciated_areas_gen_z5_idx ON ne_10m_glaciated_areas_gen_z5 USING gist (geometry);
CREATE OR REPLACE VIEW landcover_z14 AS ( -- ne_10m_antarctic_ice_shelves_polys
-- etldoc: osm_landcover_polygon -> landcover_z14 -- etldoc: ne_10m_antarctic_ice_shelves_polys -> ne_10m_antarctic_ice_shelves_polys_gen_z6
SELECT osm_id, geometry, subclass FROM osm_landcover_polygon DROP MATERIALIZED VIEW IF EXISTS ne_10m_antarctic_ice_shelves_polys_gen_z6 CASCADE;
); CREATE MATERIALIZED VIEW ne_10m_antarctic_ice_shelves_polys_gen_z6 AS
(
SELECT
ST_Simplify(geometry, ZRes(8)) as geometry,
'ice_shelf'::text AS subclass
FROM ne_10m_antarctic_ice_shelves_polys
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_10m_antarctic_ice_shelves_polys_gen_z6_idx ON ne_10m_antarctic_ice_shelves_polys_gen_z6 USING gist (geometry);
-- etldoc: layer_landcover[shape=record fillcolor=lightpink, style="rounded, filled", label="layer_landcover | <z0_1> z0-z1 | <z2_4> z2-z4 | <z5_6> z5-z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ; -- etldoc: ne_10m_antarctic_ice_shelves_polys_gen_z6 -> ne_10m_antarctic_ice_shelves_polys_gen_z5
DROP MATERIALIZED VIEW IF EXISTS ne_10m_antarctic_ice_shelves_polys_gen_z5 CASCADE;
CREATE MATERIALIZED VIEW ne_10m_antarctic_ice_shelves_polys_gen_z5 AS
(
SELECT
ST_Simplify(geometry, ZRes(7)) as geometry,
subclass
FROM ne_10m_antarctic_ice_shelves_polys_gen_z6
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_10m_antarctic_ice_shelves_polys_gen_z5_idx ON ne_10m_antarctic_ice_shelves_polys_gen_z5 USING gist (geometry);
-- etldoc: ne_110m_glaciated_areas_gen_z0 -> landcover_z0
CREATE OR REPLACE VIEW landcover_z0 AS
(
SELECT
geometry,
subclass
FROM ne_110m_glaciated_areas_gen_z0
);
-- etldoc: ne_110m_glaciated_areas_gen_z1 -> landcover_z1
CREATE OR REPLACE VIEW landcover_z1 AS
(
SELECT
geometry,
subclass
FROM ne_110m_glaciated_areas_gen_z1
);
CREATE OR REPLACE VIEW landcover_z2 AS
(
-- etldoc: ne_50m_glaciated_areas_gen_z2 -> landcover_z2
SELECT
geometry,
subclass
FROM ne_50m_glaciated_areas_gen_z2
UNION ALL
-- etldoc: ne_50m_antarctic_ice_shelves_polys_gen_z2 -> landcover_z2
SELECT
geometry,
subclass
FROM ne_50m_antarctic_ice_shelves_polys_gen_z2
);
CREATE OR REPLACE VIEW landcover_z3 AS
(
-- etldoc: ne_50m_glaciated_areas_gen_z3 -> landcover_z3
SELECT
geometry,
subclass
FROM ne_50m_glaciated_areas_gen_z3
UNION ALL
-- etldoc: ne_50m_antarctic_ice_shelves_polys_gen_z3 -> landcover_z3
SELECT
geometry,
subclass
FROM ne_50m_antarctic_ice_shelves_polys_gen_z3
);
CREATE OR REPLACE VIEW landcover_z4 AS
(
-- etldoc: ne_50m_glaciated_areas_gen_z4 -> landcover_z4
SELECT
geometry,
subclass
FROM ne_50m_glaciated_areas_gen_z4
UNION ALL
-- etldoc: ne_50m_antarctic_ice_shelves_polys_gen_z4 -> landcover_z4
SELECT
geometry,
subclass
FROM ne_50m_antarctic_ice_shelves_polys_gen_z4
);
CREATE OR REPLACE VIEW landcover_z5 AS
(
-- etldoc: ne_10m_glaciated_areas_gen_z5 -> landcover_z5
SELECT
geometry,
subclass
FROM ne_10m_glaciated_areas_gen_z5
UNION ALL
-- etldoc: ne_10m_antarctic_ice_shelves_polys_gen_z5 -> landcover_z5
SELECT
geometry,
subclass
FROM ne_10m_antarctic_ice_shelves_polys_gen_z5
);
CREATE OR REPLACE VIEW landcover_z6 AS
(
-- etldoc: ne_10m_glaciated_areas_gen_z6 -> landcover_z6
SELECT
geometry,
subclass
FROM ne_10m_glaciated_areas_gen_z6
UNION ALL
-- etldoc: ne_10m_antarctic_ice_shelves_polys_gen_z6 -> landcover_z6
SELECT
geometry,
subclass
FROM ne_10m_antarctic_ice_shelves_polys_gen_z6
);
-- etldoc: layer_landcover[shape=record fillcolor=lightpink, style="rounded, filled", label="layer_landcover | <z0> z0 | <z1> z1 | <z2> z2 | <z3> z3 | <z4> z4 | <z5> z5 | <z6> z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_landcover(bbox geometry, zoom_level int) CREATE OR REPLACE FUNCTION layer_landcover(bbox geometry, zoom_level int)
RETURNS TABLE(osm_id bigint, geometry geometry, class text, subclass text) AS $$ RETURNS TABLE
SELECT osm_id, geometry, (
landcover_class(subclass) AS class, geometry geometry,
subclass class text,
FROM ( subclass text
-- etldoc: landcover_z0 -> layer_landcover:z0_1 )
SELECT * FROM landcover_z0 AS
WHERE zoom_level BETWEEN 0 AND 1 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z2 -> layer_landcover:z2_4
SELECT * FROM landcover_z2
WHERE zoom_level BETWEEN 2 AND 4 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z5 -> layer_landcover:z5_6
SELECT * FROM landcover_z5
WHERE zoom_level BETWEEN 5 AND 6 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z7 -> layer_landcover:z7
SELECT *
FROM landcover_z7 WHERE zoom_level = 7 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z8 -> layer_landcover:z8
SELECT *
FROM landcover_z8 WHERE zoom_level = 8 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z9 -> layer_landcover:z9
SELECT *
FROM landcover_z9 WHERE zoom_level = 9 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z10 -> layer_landcover:z10
SELECT *
FROM landcover_z10 WHERE zoom_level = 10 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z11 -> layer_landcover:z11
SELECT *
FROM landcover_z11 WHERE zoom_level = 11 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z12 -> layer_landcover:z12
SELECT *
FROM landcover_z12 WHERE zoom_level = 12 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z13 -> layer_landcover:z13
SELECT *
FROM landcover_z13 WHERE zoom_level = 13 AND geometry && bbox
UNION ALL
-- etldoc: landcover_z14 -> layer_landcover:z14_
SELECT *
FROM landcover_z14 WHERE zoom_level >= 14 AND geometry && bbox
) AS zoom_levels;
$$ $$
LANGUAGE SQL SELECT geometry,
IMMUTABLE PARALLEL SAFE; landcover_class(subclass) AS class,
subclass
FROM (
-- etldoc: landcover_z0 -> layer_landcover:z0
SELECT geometry,
subclass
FROM landcover_z0
WHERE zoom_level = 0
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z1 -> layer_landcover:z1
SELECT geometry,
subclass
FROM landcover_z1
WHERE zoom_level = 1
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z2 -> layer_landcover:z2
SELECT geometry,
subclass
FROM landcover_z2
WHERE zoom_level = 2
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z3 -> layer_landcover:z3
SELECT geometry,
subclass
FROM landcover_z3
WHERE zoom_level = 3
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z4 -> layer_landcover:z4
SELECT geometry,
subclass
FROM landcover_z4
WHERE zoom_level = 4
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z5 -> layer_landcover:z5
SELECT geometry,
subclass
FROM landcover_z5
WHERE zoom_level = 5
AND geometry && bbox
UNION ALL
-- etldoc: landcover_z6 -> layer_landcover:z6
SELECT geometry,
subclass
FROM landcover_z6
WHERE zoom_level = 6
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z7 -> layer_landcover:z7
SELECT geometry,
subclass
FROM osm_landcover_gen_z7
WHERE zoom_level = 7
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z8 -> layer_landcover:z8
SELECT geometry,
subclass
FROM osm_landcover_gen_z8
WHERE zoom_level = 8
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z9 -> layer_landcover:z9
SELECT geometry,
subclass
FROM osm_landcover_gen_z9
WHERE zoom_level = 9
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z10 -> layer_landcover:z10
SELECT geometry,
subclass
FROM osm_landcover_gen_z10
WHERE zoom_level = 10
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z11 -> layer_landcover:z11
SELECT geometry,
subclass
FROM osm_landcover_gen_z11
WHERE zoom_level = 11
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z12 -> layer_landcover:z12
SELECT geometry,
subclass
FROM osm_landcover_gen_z12
WHERE zoom_level = 12
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_gen_z13 -> layer_landcover:z13
SELECT geometry,
subclass
FROM osm_landcover_gen_z13
WHERE zoom_level = 13
AND geometry && bbox
UNION ALL
-- etldoc: osm_landcover_polygon -> layer_landcover:z14_
SELECT geometry,
subclass
FROM osm_landcover_polygon
WHERE zoom_level >= 14
AND geometry && bbox
) AS zoom_levels;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -73,6 +73,7 @@ layer:
geometry_field: geometry geometry_field: geometry
query: (SELECT geometry, class, subclass FROM layer_landcover(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, class, subclass FROM layer_landcover(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./generalized.sql
- ./landcover.sql - ./landcover.sql
datasources: datasources:
- type: imposm3 - type: imposm3

View File

@ -1,48 +1,3 @@
generalized_tables:
# etldoc: imposm3 -> osm_landcover_polygon_gen7
landcover_polygon_gen7:
source: landcover_polygon_gen6
sql_filter: area>power(ZRES5,2)
tolerance: ZRES7
# etldoc: imposm3 -> osm_landcover_polygon_gen6
landcover_polygon_gen6:
source: landcover_polygon_gen5
sql_filter: area>power(ZRES6,2)
tolerance: ZRES8
# etldoc: imposm3 -> osm_landcover_polygon_gen5
landcover_polygon_gen5:
source: landcover_polygon_gen4
sql_filter: area>power(ZRES7,2)
tolerance: ZRES9
# etldoc: imposm3 -> osm_landcover_polygon_gen4
landcover_polygon_gen4:
source: landcover_polygon_gen3
sql_filter: area>power(ZRES8,2)
tolerance: ZRES10
# etldoc: imposm3 -> osm_landcover_polygon_gen3
landcover_polygon_gen3:
source: landcover_polygon_gen2
sql_filter: area>power(ZRES8,2)
tolerance: ZRES11
# etldoc: imposm3 -> osm_landcover_polygon_gen2
landcover_polygon_gen2:
source: landcover_polygon_gen1
sql_filter: area>power(ZRES9,2)
tolerance: ZRES12
# etldoc: imposm3 -> osm_landcover_polygon_gen1
landcover_polygon_gen1:
source: landcover_polygon
sql_filter: area>power(ZRES10,2) AND ST_IsValid(geometry)
tolerance: ZRES13
tables: tables:
# etldoc: imposm3 -> osm_landcover_polygon # etldoc: imposm3 -> osm_landcover_polygon
landcover_polygon: landcover_polygon:

View File

@ -0,0 +1,10 @@
## Landmarks
### Docs
This is a custom layer including landmarks (named forests) that can not be classified as a POI
### Mapping Diagram
### ETL diagram

View File

@ -0,0 +1,19 @@
CREATE OR REPLACE FUNCTION lm_class_rank(class text)
RETURNS int AS
$$
SELECT CASE class
WHEN 'forest' THEN 120
ELSE 1000
END;
$$ LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;
CREATE OR REPLACE FUNCTION lm_class(subclass text, mapping_key text)
RETURNS text AS
$$
SELECT CASE
%%FIELD_MAPPING: class %%
ELSE subclass
END;
$$ LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,139 @@
layer:
id: "landmarks"
description: |
[Points of interests](http://wiki.openstreetmap.org/wiki/Points_of_interest) containing
a of a variety of OpenStreetMap tags. Mostly contains amenities, sport, shop and tourist POIs.
buffer_size: 64
srs: +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over
fields:
name: The OSM [`name`](http://wiki.openstreetmap.org/wiki/Key:name) value of the POI.
name_en: English name `name:en` if available, otherwise `name`.
name_de: German name `name:de` if available, otherwise `name` or `name:en`.
class:
description: |
More general classes of landmarks. If there is no more general `class` for the `subclass`
this field will contain the same value as `subclass`.
values:
shop:
subclass: ['accessories', 'antiques', 'beauty', 'bed', 'boutique', 'camera', 'carpet', 'charity', 'chemist',
'coffee', 'computer', 'convenience', 'copyshop', 'cosmetics', 'garden_centre', 'doityourself',
'erotic', 'electronics', 'fabric', 'florist', 'frozen_food', 'furniture', 'video_games', 'video',
'general', 'gift', 'hardware', 'hearing_aids', 'hifi', 'ice_cream', 'interior_decoration',
'jewelry', 'kiosk', 'lamps', 'mall', 'massage', 'motorcycle', 'mobile_phone', 'newsagent',
'optician', 'outdoor', 'perfumery', 'perfume', 'pet', 'photo', 'second_hand', 'shoes', 'sports',
'stationery', 'tailor', 'tattoo', 'ticket', 'tobacco', 'toys', 'travel_agency', 'watches',
'weapons', 'wholesale']
town_hall:
subclass: ['townhall', 'public_building', 'courthouse', 'community_centre']
golf:
subclass: ['golf', 'golf_course', 'miniature_golf']
fast_food:
subclass: ['fast_food', 'food_court']
park:
subclass: ['park', 'bbq']
bus:
subclass: ['bus_stop', 'bus_station']
railway:
- __AND__:
subclass: 'station'
mapping_key: 'railway'
- subclass: ['halt', 'tram_stop', 'subway']
aerialway:
__AND__:
subclass: 'station'
mapping_key: 'aerialway'
entrance:
subclass: ['subway_entrance', 'train_station_entrance']
campsite:
subclass: ['camp_site', 'caravan_site']
laundry:
subclass: ['laundry', 'dry_cleaning']
grocery:
subclass: ['supermarket', 'deli', 'delicatessen', 'department_store', 'greengrocer', 'marketplace']
library:
subclass: ['books', 'library']
college:
subclass: ['university', 'college']
lodging:
subclass: ['hotel', 'motel', 'bed_and_breakfast', 'guest_house', 'hostel', 'chalet', 'alpine_hut', 'dormitory']
ice_cream:
subclass: ['chocolate', 'confectionery']
post:
subclass: ['post_box', 'post_office']
cafe:
subclass: ['cafe']
school:
subclass: ['school', 'kindergarten']
alcohol_shop:
subclass: ['alcohol', 'beverages', 'wine']
bar:
subclass: ['bar', 'nightclub']
harbor:
subclass: ['marina', 'dock']
car:
subclass: ['car', 'car_repair', 'car_parts', 'taxi']
hospital:
subclass: ['hospital', 'nursing_home', 'clinic']
cemetery:
subclass: ['grave_yard', 'cemetery']
attraction:
subclass: ['attraction', 'viewpoint']
beer:
subclass: ['biergarten', 'pub']
music:
subclass: ['music', 'musical_instrument']
stadium:
subclass: ['american_football', 'stadium', 'soccer']
art_gallery:
subclass: ['art', 'artwork', 'gallery', 'arts_centre']
clothing_store:
subclass: ['bag', 'clothes']
swimming:
subclass: ['swimming_area', 'swimming']
castle:
subclass: ['castle', 'ruins']
subclass:
description: |
Original value of either the
[`amenity`](http://wiki.openstreetmap.org/wiki/Key:amenity),
[`barrier`](http://wiki.openstreetmap.org/wiki/Key:barrier),
[`historic`](http://wiki.openstreetmap.org/wiki/Key:historic),
[`information`](http://wiki.openstreetmap.org/wiki/Key:information),
[`landuse`](http://wiki.openstreetmap.org/wiki/Key:landuse),
[`leisure`](http://wiki.openstreetmap.org/wiki/Key:leisure),
[`railway`](http://wiki.openstreetmap.org/wiki/Key:railway),
[`shop`](http://wiki.openstreetmap.org/wiki/Key:shop),
[`sport`](http://wiki.openstreetmap.org/wiki/Key:sport),
[`station`](http://wiki.openstreetmap.org/wiki/Key:station),
[`religion`](http://wiki.openstreetmap.org/wiki/Key:religion),
[`tourism`](http://wiki.openstreetmap.org/wiki/Key:tourism),
[`aerialway`](http://wiki.openstreetmap.org/wiki/Key:aerialway),
[`building`](http://wiki.openstreetmap.org/wiki/Key:building),
[`highway`](http://wiki.openstreetmap.org/wiki/Key:highway)
or [`waterway`](http://wiki.openstreetmap.org/wiki/Key:waterway)
tag. Use this to do more precise styling.
rank: |
The POIs are ranked ascending according to their importance within a grid. The `rank` value shows the
local relative importance of a POI within it's cell in the grid. This can be used to reduce label density at *z14*.
Since all POIs already need to be contained at *z14* you can use `less than rank=10` epxression to limit
LMs. At some point like *z17* you can show all LMs.
level:
description: |
Original value of [`level`](http://wiki.openstreetmap.org/wiki/Key:level) tag.
layer:
description: |
Original value of [`layer`](http://wiki.openstreetmap.org/wiki/Key:layer) tag.
datasource:
geometry_field: geometry
key_field: osm_id
key_field_as_attribute: no
srid: 900913
query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, subclass, layer, level, rank FROM layer_lm(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t
schema:
- ./class.sql
- ./update_lm_polygon.sql
- ./update_lm_point.sql
- ./layer.sql
datasources:
- type: imposm3
mapping_file: ./mapping.yaml

View File

@ -0,0 +1,85 @@
-- etldoc: layer_lm[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_lm | <z12> z12 | <z13> z13 | <z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_lm(bbox geometry, zoom_level integer, pixel_width numeric)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
tags hstore,
class text,
subclass text,
layer integer,
level integer,
"rank" int
)
AS
$$
SELECT osm_id_hash AS osm_id,
geometry,
NULLIF(name, '') AS name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
lm_class(subclass, mapping_key) AS class,
subclass AS subclass,
NULLIF(layer, 0) AS layer,
"level",
row_number() OVER (
PARTITION BY LabelGrid(geometry, 100 * pixel_width)
ORDER BY CASE WHEN name = '' THEN 2000 ELSE lm_class_rank(lm_class(subclass, mapping_key)) END ASC
)::int AS "rank"
FROM (
-- etldoc: osm_lm_point -> layer_lm:z12
-- etldoc: osm_lm_point -> layer_lm:z13
SELECT *,
osm_id * 10 AS osm_id_hash
FROM osm_lm_point
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass = 'station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_lm_point -> layer_lm:z14_
SELECT *,
osm_id * 10 AS osm_id_hash
FROM osm_lm_point
WHERE geometry && bbox
AND zoom_level >= 14
UNION ALL
-- etldoc: osm_lm_polygon -> layer_lm:z12
-- etldoc: osm_lm_polygon -> layer_lm:z13
SELECT *,
CASE
WHEN osm_id < 0 THEN -osm_id * 10 + 4
ELSE osm_id * 10 + 1
END AS osm_id_hash
FROM osm_lm_polygon
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass = 'station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_lm_polygon -> layer_lm:z14_
SELECT *,
CASE
WHEN osm_id < 0 THEN -osm_id * 10 + 4
ELSE osm_id * 10 + 1
END AS osm_id_hash
FROM osm_lm_polygon
WHERE geometry && bbox
AND zoom_level >= 14
) AS lm_union
ORDER BY "rank"
$$ LANGUAGE SQL STABLE
PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL

View File

@ -0,0 +1,74 @@
# imposm3 mapping file for https://github.com/osm2vectortiles/imposm3
# Warning: this is not the official imposm3
# landuse values , see http://taginfo.openstreetmap.org/keys/landuse#values
def_lm_mapping_landuse: &lm_mapping_landuse
- forest
def_poi_fields: &lm_fields
- name: osm_id
type: id
- name: geometry
type: geometry
- name: name
key: name
type: string
- name: name_en
key: name:en
type: string
- name: name_de
key: name:de
type: string
- name: tags
type: hstore_tags
- name: subclass
type: mapping_value
- name: mapping_key
type: mapping_key
- name: station
key: station
type: string
- name: funicular
key: funicular
type: string
- name: information
key: information
type: string
- name: uic_ref
key: uic_ref
type: string
- name: religion
key: religion
type: string
- name: level
key: level
type: integer
- name: layer
key: layer
type: integer
- name: sport
key: sport
type: string
def_lm_mapping: &lm_mapping
landuse: *lm_mapping_landuse
tables:
# etldoc: imposm3 -> osm_lm_point
lm_point:
type: point
columns: *lm_fields
filters:
require:
name: ["__any__"]
mapping: *lm_mapping
# etldoc: imposm3 -> osm_lm_polygon
lm_polygon:
type: polygon
columns: *lm_fields
filters:
require:
name: ["__any__"]
mapping: *lm_mapping

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -0,0 +1,69 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_lm_point;
DROP TRIGGER IF EXISTS trigger_refresh ON lm_point.updates;
-- etldoc: osm_lm_point -> osm_lm_point
CREATE OR REPLACE FUNCTION update_osm_lm_point() RETURNS void AS
$$
BEGIN
UPDATE osm_lm_point
SET subclass = 'subway'
WHERE station = 'subway'
AND subclass = 'station';
UPDATE osm_lm_point
SET subclass = 'halt'
WHERE funicular = 'yes'
AND subclass = 'station';
UPDATE osm_lm_point
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END;
$$ LANGUAGE plpgsql;
SELECT update_osm_lm_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS lm_point;
CREATE TABLE IF NOT EXISTS lm_point.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION lm_point.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO lm_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION lm_point.refresh() RETURNS trigger AS
$$
BEGIN
RAISE LOG 'Refresh lm_point';
PERFORM update_osm_lm_point();
REFRESH MATERIALIZED VIEW osm_lm_stop_centroid;
REFRESH MATERIALIZED VIEW osm_lm_stop_rank;
-- noinspection SqlWithoutWhere
DELETE FROM lm_point.updates;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE
ON osm_lm_point
FOR EACH STATEMENT
EXECUTE PROCEDURE lm_point.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT
ON lm_point.updates
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE lm_point.refresh();

View File

@ -0,0 +1,78 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_lm_polygon;
DROP TRIGGER IF EXISTS trigger_refresh ON lm_polygon.updates;
-- etldoc: osm_lm_polygon -> osm_lm_polygon
CREATE OR REPLACE FUNCTION update_lm_polygon() RETURNS void AS
$$
BEGIN
UPDATE osm_lm_polygon
SET geometry =
CASE
WHEN ST_NPoints(ST_ConvexHull(geometry)) = ST_NPoints(geometry)
THEN ST_Centroid(geometry)
ELSE ST_PointOnSurface(geometry)
END
WHERE ST_GeometryType(geometry) <> 'ST_Point';
UPDATE osm_lm_polygon
SET subclass = 'subway'
WHERE station = 'subway'
AND subclass = 'station';
UPDATE osm_lm_polygon
SET subclass = 'halt'
WHERE funicular = 'yes'
AND subclass = 'station';
UPDATE osm_lm_polygon
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
ANALYZE osm_lm_polygon;
END;
$$ LANGUAGE plpgsql;
SELECT update_lm_polygon();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS lm_polygon;
CREATE TABLE IF NOT EXISTS lm_polygon.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION lm_polygon.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO lm_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION lm_polygon.refresh() RETURNS trigger AS
$$
BEGIN
RAISE LOG 'Refresh lm_polygon';
PERFORM update_lm_polygon();
-- noinspection SqlWithoutWhere
DELETE FROM lm_polygon.updates;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE
ON osm_lm_polygon
FOR EACH STATEMENT
EXECUTE PROCEDURE lm_polygon.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT
ON lm_polygon.updates
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE lm_polygon.refresh();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 176 KiB

View File

@ -1,113 +1,210 @@
-- etldoc: ne_50m_urban_areas -> landuse_z4 -- ne_50m_urban_areas
CREATE OR REPLACE VIEW landuse_z4 AS ( -- etldoc: ne_50m_urban_areas -> ne_50m_urban_areas_gen_z5
SELECT NULL::bigint AS osm_id, geometry, 'residential'::text AS landuse, NULL::text AS amenity, NULL::text AS leisure, NULL::text AS tourism, NULL::text AS place, NULL::text AS waterway DROP MATERIALIZED VIEW IF EXISTS ne_50m_urban_areas_gen_z5 CASCADE;
FROM ne_50m_urban_areas CREATE MATERIALIZED VIEW ne_50m_urban_areas_gen_z5 AS
WHERE scalerank <= 2 (
); SELECT
NULL::bigint AS osm_id,
ST_Simplify(geometry, ZRes(7)) as geometry,
'residential'::text AS landuse,
NULL::text AS amenity,
NULL::text AS leisure,
NULL::text AS tourism,
NULL::text AS place,
NULL::text AS waterway,
NULL::text AS man_made,
scalerank
FROM ne_50m_urban_areas
) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_urban_areas_gen_z5_idx ON ne_50m_urban_areas_gen_z5 USING gist (geometry);
-- etldoc: ne_50m_urban_areas -> landuse_z5 -- etldoc: ne_50m_urban_areas_gen_z5 -> ne_50m_urban_areas_gen_z4
CREATE OR REPLACE VIEW landuse_z5 AS ( DROP MATERIALIZED VIEW IF EXISTS ne_50m_urban_areas_gen_z4 CASCADE;
SELECT NULL::bigint AS osm_id, geometry, 'residential'::text AS landuse, NULL::text AS amenity, NULL::text AS leisure, NULL::text AS tourism, NULL::text AS place, NULL::text AS waterway CREATE MATERIALIZED VIEW ne_50m_urban_areas_gen_z4 AS
FROM ne_50m_urban_areas (
); SELECT
osm_id,
-- etldoc: osm_landuse_polygon_gen7 -> landuse_z6 ST_Simplify(geometry, ZRes(6)) as geometry,
CREATE OR REPLACE VIEW landuse_z6 AS ( landuse,
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway amenity,
FROM osm_landuse_polygon_gen7 leisure,
); tourism,
place,
-- etldoc: osm_landuse_polygon_gen6 -> landuse_z8 waterway,
CREATE OR REPLACE VIEW landuse_z8 AS ( man_made
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway FROM ne_50m_urban_areas_gen_z5
FROM osm_landuse_polygon_gen6 WHERE scalerank <= 2
); ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ;
CREATE INDEX IF NOT EXISTS ne_50m_urban_areas_gen_z4_idx ON ne_50m_urban_areas_gen_z4 USING gist (geometry);
-- etldoc: osm_landuse_polygon_gen5 -> landuse_z9
CREATE OR REPLACE VIEW landuse_z9 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon_gen5
);
-- etldoc: osm_landuse_polygon_gen4 -> landuse_z10
CREATE OR REPLACE VIEW landuse_z10 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon_gen4
);
-- etldoc: osm_landuse_polygon_gen3 -> landuse_z11
CREATE OR REPLACE VIEW landuse_z11 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon_gen3
);
-- etldoc: osm_landuse_polygon_gen2 -> landuse_z12
CREATE OR REPLACE VIEW landuse_z12 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon_gen2
);
-- etldoc: osm_landuse_polygon_gen1 -> landuse_z13
CREATE OR REPLACE VIEW landuse_z13 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon_gen1
);
-- etldoc: osm_landuse_polygon -> landuse_z14
CREATE OR REPLACE VIEW landuse_z14 AS (
SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway
FROM osm_landuse_polygon
);
-- etldoc: layer_landuse[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: layer_landuse[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_landuse |<z4> z4|<z5>z5|<z6>z6|<z7>z7| <z8> z8 |<z9> z9 |<z10> z10 |<z11> z11|<z12> z12|<z13> z13|<z14> z14+" ] ; -- etldoc: label="layer_landuse |<z4> z4|<z5> z5|<z6> z6|<z7> z7|<z8> z8|<z9> z9|<z10> z10|<z11> z11|<z12> z12|<z13> z13|<z14> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_landuse(bbox geometry, zoom_level int) CREATE OR REPLACE FUNCTION layer_landuse(bbox geometry, zoom_level int)
RETURNS TABLE(osm_id bigint, geometry geometry, class text) AS $$ RETURNS TABLE
SELECT osm_id, geometry, (
COALESCE( osm_id bigint,
NULLIF(landuse, ''), geometry geometry,
NULLIF(amenity, ''), class text
NULLIF(leisure, ''), )
NULLIF(tourism, ''), AS
NULLIF(place, ''),
NULLIF(waterway, '')
) AS class
FROM (
-- etldoc: landuse_z4 -> layer_landuse:z4
SELECT * FROM landuse_z4
WHERE zoom_level = 4
UNION ALL
-- etldoc: landuse_z5 -> layer_landuse:z5
SELECT * FROM landuse_z5
WHERE zoom_level = 5
UNION ALL
-- etldoc: landuse_z6 -> layer_landuse:z6
-- etldoc: landuse_z6 -> layer_landuse:z7
SELECT * FROM landuse_z6 WHERE zoom_level BETWEEN 6 AND 7
UNION ALL
-- etldoc: landuse_z8 -> layer_landuse:z8
SELECT * FROM landuse_z8 WHERE zoom_level = 8
UNION ALL
-- etldoc: landuse_z9 -> layer_landuse:z9
SELECT * FROM landuse_z9 WHERE zoom_level = 9
UNION ALL
-- etldoc: landuse_z10 -> layer_landuse:z10
SELECT * FROM landuse_z10 WHERE zoom_level = 10
UNION ALL
-- etldoc: landuse_z11 -> layer_landuse:z11
SELECT * FROM landuse_z11 WHERE zoom_level = 11
UNION ALL
-- etldoc: landuse_z12 -> layer_landuse:z12
SELECT * FROM landuse_z12 WHERE zoom_level = 12
UNION ALL
-- etldoc: landuse_z13 -> layer_landuse:z13
SELECT * FROM landuse_z13 WHERE zoom_level = 13
UNION ALL
-- etldoc: landuse_z14 -> layer_landuse:z14
SELECT * FROM landuse_z14 WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox;
$$ $$
LANGUAGE SQL SELECT osm_id,
IMMUTABLE PARALLEL SAFE; geometry,
COALESCE(
NULLIF(landuse, ''),
NULLIF(amenity, ''),
NULLIF(leisure, ''),
NULLIF(tourism, ''),
NULLIF(place, ''),
NULLIF(waterway, ''),
NULLIF(man_made, '')
) AS class
FROM (
-- etldoc: ne_50m_urban_areas_gen_z4 -> layer_landuse:z4
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM ne_50m_urban_areas_gen_z4
WHERE zoom_level = 4
UNION ALL
-- etldoc: ne_50m_urban_areas_gen_z5 -> layer_landuse:z5
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM ne_50m_urban_areas_gen_z5
WHERE zoom_level = 5
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z6 -> layer_landuse:z6
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z6
WHERE zoom_level = 6
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z7 -> layer_landuse:z7
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z7
WHERE zoom_level = 7
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z8 -> layer_landuse:z8
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z8
WHERE zoom_level = 8
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z9 -> layer_landuse:z9
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z9
WHERE zoom_level = 9
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z10 -> layer_landuse:z10
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z10
WHERE zoom_level = 10
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z11 -> layer_landuse:z11
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z11
WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z12 -> layer_landuse:z12
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z12
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_landuse_polygon_gen_z13 -> layer_landuse:z13
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon_gen_z13
WHERE zoom_level = 13
UNION ALL
-- etldoc: osm_landuse_polygon -> layer_landuse:z14
SELECT osm_id,
geometry,
landuse,
amenity,
leisure,
tourism,
place,
waterway,
man_made
FROM osm_landuse_polygon
WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -22,6 +22,7 @@ layer:
- residential - residential
- commercial - commercial
- industrial - industrial
- garages
- retail - retail
- bus_station - bus_station
- school - school
@ -37,11 +38,17 @@ layer:
- theme_park - theme_park
- zoo - zoo
- suburb - suburb
- quarter
- neighbourhood - neighbourhood
- dam - dam
- sports_centre - sports_centre
- parking - parking
- motorcycle_parking
- bicycle_parking
- religious - religious
- prison
- wastewater_plant
- water_works
datasource: datasource:
geometry_field: geometry geometry_field: geometry
query: (SELECT geometry, class FROM layer_landuse(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, class FROM layer_landuse(!bbox!, z(!scale_denominator!))) AS t

View File

@ -1,35 +1,41 @@
generalized_tables: generalized_tables:
# etldoc: imposm3 -> osm_landuse_polygon_gen7 # etldoc: osm_landuse_polygon_gen_z7 -> osm_landuse_polygon_gen_z6
landuse_polygon_gen7: landuse_polygon_gen_z6:
source: landuse_polygon_gen6 source: landuse_polygon_gen_z7
tolerance: ZRES6
sql_filter: area>power(ZRES6,2)
# etldoc: osm_landuse_polygon_gen_z8 -> osm_landuse_polygon_gen_z7
landuse_polygon_gen_z7:
source: landuse_polygon_gen_z8
tolerance: ZRES7 tolerance: ZRES7
# etldoc: imposm3 -> osm_landuse_polygon_gen6 sql_filter: area>power(ZRES6,2)
landuse_polygon_gen6: # etldoc: osm_landuse_polygon_gen_z9 -> osm_landuse_polygon_gen_z8
source: landuse_polygon_gen5 landuse_polygon_gen_z8:
sql_filter: area>power(ZRES6,2) AND (landuse='residential' OR place='suburb' OR place='neighbourhood') source: landuse_polygon_gen_z9
sql_filter: area>power(ZRES6,2) AND (landuse='residential' OR place='suburb' OR place='quarter' OR place='neighbourhood')
tolerance: ZRES8 tolerance: ZRES8
# etldoc: imposm3 -> osm_landuse_polygon_gen5 # etldoc: osm_landuse_polygon_gen_z10 -> osm_landuse_polygon_gen_z9
landuse_polygon_gen5: landuse_polygon_gen_z9:
source: landuse_polygon_gen4 source: landuse_polygon_gen_z10
sql_filter: area>power(ZRES7,2) sql_filter: area>power(ZRES7,2)
tolerance: ZRES9 tolerance: ZRES9
# etldoc: imposm3 -> osm_landuse_polygon_gen4 # etldoc: osm_landuse_polygon_gen_z11 -> osm_landuse_polygon_gen_z10
landuse_polygon_gen4: landuse_polygon_gen_z10:
source: landuse_polygon_gen3 source: landuse_polygon_gen_z11
sql_filter: area>power(ZRES8,2) sql_filter: area>power(ZRES8,2)
tolerance: ZRES10 tolerance: ZRES10
# etldoc: imposm3 -> osm_landuse_polygon_gen3 # etldoc: osm_landuse_polygon_gen_z12 -> osm_landuse_polygon_gen_z11
landuse_polygon_gen3: landuse_polygon_gen_z11:
source: landuse_polygon_gen2 source: landuse_polygon_gen_z12
sql_filter: area>power(ZRES9,2) sql_filter: area>power(ZRES9,2)
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_landuse_polygon_gen2 # etldoc: osm_landuse_polygon_gen_z13 -> osm_landuse_polygon_gen_z12
landuse_polygon_gen2: landuse_polygon_gen_z12:
source: landuse_polygon_gen1 source: landuse_polygon_gen_z13
sql_filter: area>power(ZRES10,2) sql_filter: area>power(ZRES10,2)
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_landuse_polygon_gen1 # etldoc: osm_landuse_polygon -> osm_landuse_polygon_gen_z13
landuse_polygon_gen1: landuse_polygon_gen_z13:
source: landuse_polygon source: landuse_polygon
sql_filter: area>power(ZRES11,2) AND ST_IsValid(geometry) sql_filter: area>power(ZRES11,2) AND ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
@ -63,6 +69,9 @@ tables:
type: string type: string
- name: area - name: area
type: area type: area
- name: man_made
key: man_made
type: string
mapping: mapping:
landuse: landuse:
- railway - railway
@ -75,6 +84,7 @@ tables:
- garages - garages
- retail - retail
- religious - religious
- construction
amenity: amenity:
- bus_station - bus_station
- school - school
@ -84,6 +94,9 @@ tables:
- library - library
- hospital - hospital
- parking - parking
- prison
- motorcycle_parking
- bicycle_parking
- animal_training - animal_training
leisure: leisure:
- stadium - stadium
@ -97,6 +110,10 @@ tables:
- picnic_site - picnic_site
place: place:
- suburb - suburb
- quarter
- neighbourhood - neighbourhood
waterway: waterway:
- dam - dam
man_made:
- wastewater_plant
- water_works

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -1,57 +0,0 @@
-- etldoc: layer_mountain_peak[shape=record fillcolor=lightpink,
-- etldoc: style="rounded,filled", label="layer_mountain_peak | <z7_> z7+" ] ;
CREATE OR REPLACE FUNCTION layer_mountain_peak(
bbox geometry,
zoom_level integer,
pixel_width numeric)
RETURNS TABLE(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
class text,
tags hstore,
ele int,
ele_ft int,
"rank" int) AS
$$
-- etldoc: osm_peak_point -> layer_mountain_peak:z7_
SELECT
osm_id,
geometry,
name,
name_en,
name_de,
tags -> 'natural' AS class,
tags,
ele::int,
ele_ft::int,
rank::int FROM (
SELECT osm_id, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
substring(ele from E'^(-?\\d+)(\\D|$)')::int AS ele,
round(substring(ele from E'^(-?\\d+)(\\D|$)')::int*3.2808399)::int AS ele_ft,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 100 * pixel_width)
ORDER BY (
substring(ele from E'^(-?\\d+)(\\D|$)')::int +
(CASE WHEN NULLIF(wikipedia, '') is not null THEN 10000 ELSE 0 END) +
(CASE WHEN NULLIF(name, '') is not null THEN 10000 ELSE 0 END)
) DESC
)::int AS "rank"
FROM osm_peak_point
WHERE geometry && bbox
AND ele is not null
AND ele ~ E'^-?\\d{1,4}(\\D|$)'
) AS ranked_peaks
WHERE zoom_level >= 7 AND (rank <= 5 OR zoom_level >= 14)
ORDER BY "rank" ASC;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -0,0 +1,62 @@
-- etldoc: layer_mountain_peak[shape=record fillcolor=lightpink,
-- etldoc: style="rounded,filled", label="layer_mountain_peak | <z7_> z7+" ] ;
CREATE OR REPLACE FUNCTION layer_mountain_peak(bbox geometry,
zoom_level integer,
pixel_width numeric)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
class text,
tags hstore,
ele int,
ele_ft int,
"rank" int
)
AS
$$
SELECT
-- etldoc: osm_peak_point -> layer_mountain_peak:z7_
osm_id,
geometry,
name,
name_en,
name_de,
tags->'natural' AS class,
tags,
ele::int,
ele_ft::int,
rank::int
FROM (
SELECT osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
substring(ele FROM E'^(-?\\d+)(\\D|$)')::int AS ele,
round(substring(ele FROM E'^(-?\\d+)(\\D|$)')::int * 3.2808399)::int AS ele_ft,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 100 * pixel_width)
ORDER BY (
substring(ele FROM E'^(-?\\d+)(\\D|$)')::int +
(CASE WHEN NULLIF(wikipedia, '') IS NOT NULL THEN 10000 ELSE 0 END) +
(CASE WHEN NULLIF(name, '') IS NOT NULL THEN 10000 ELSE 0 END)
) DESC
)::int AS "rank"
FROM osm_peak_point
WHERE geometry && bbox
AND ele IS NOT NULL
AND ele ~ E'^-?\\d{1,4}(\\D|$)'
) AS ranked_peaks
WHERE zoom_level >= 7
AND (rank <= 5 OR zoom_level >= 14)
ORDER BY "rank" ASC;
$$ LANGUAGE SQL STABLE
PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL

View File

@ -25,7 +25,7 @@ layer:
query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, ele, ele_ft, rank FROM layer_mountain_peak(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, ele, ele_ft, rank FROM layer_mountain_peak(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t
schema: schema:
- ./update_peak_point.sql - ./update_peak_point.sql
- ./layer.sql - ./mountain_peak.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,48 +1,86 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_peak_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_peak_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_peak_point;
DROP TRIGGER IF EXISTS trigger_refresh ON mountain_peak_point.updates; DROP TRIGGER IF EXISTS trigger_refresh ON mountain_peak_point.updates;
-- etldoc: osm_peak_point -> osm_peak_point
CREATE OR REPLACE FUNCTION update_osm_peak_point() RETURNS VOID AS $$
BEGIN
UPDATE osm_peak_point
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END;
$$ LANGUAGE plpgsql;
SELECT update_osm_peak_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS mountain_peak_point; CREATE SCHEMA IF NOT EXISTS mountain_peak_point;
CREATE TABLE IF NOT EXISTS mountain_peak_point.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS mountain_peak_point.osm_ids
CREATE OR REPLACE FUNCTION mountain_peak_point.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_peak_point -> osm_peak_point
CREATE OR REPLACE FUNCTION update_osm_peak_point(full_update boolean) RETURNS void AS
$$
UPDATE osm_peak_point
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM mountain_peak_point.osm_ids))
AND COALESCE(tags -> 'name:latin', tags -> 'name:nonlatin', tags -> 'name_int') IS NULL
AND tags != update_tags(tags, geometry)
$$ LANGUAGE SQL;
SELECT update_osm_peak_point(true);
-- Handle updates
CREATE OR REPLACE FUNCTION mountain_peak_point.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO mountain_peak_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO mountain_peak_point.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO mountain_peak_point.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS mountain_peak_point.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION mountain_peak_point.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO mountain_peak_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION mountain_peak_point.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION mountain_peak_point.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh mountain_peak_point'; RAISE LOG 'Refresh mountain_peak_point';
PERFORM update_osm_peak_point(); PERFORM update_osm_peak_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM mountain_peak_point.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM mountain_peak_point.updates; DELETE FROM mountain_peak_point.updates;
RETURN null;
END; RAISE LOG 'Refresh mountain_peak_point done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_peak_point
FOR EACH ROW
EXECUTE PROCEDURE mountain_peak_point.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_peak_point AFTER INSERT OR UPDATE OR DELETE
ON osm_peak_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE mountain_peak_point.flag(); EXECUTE PROCEDURE mountain_peak_point.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON mountain_peak_point.updates AFTER INSERT
ON mountain_peak_point.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE mountain_peak_point.refresh(); EXECUTE PROCEDURE mountain_peak_point.refresh();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 144 KiB

View File

@ -1,135 +0,0 @@
-- etldoc: layer_park[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_park |<z6> z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_park(bbox geometry, zoom_level int, pixel_width numeric)
RETURNS TABLE(osm_id bigint, geometry geometry, class text, name text, name_en text, name_de text, tags hstore, rank int) AS $$
SELECT osm_id, geometry, class, name, name_en, name_de, tags, rank
FROM (
SELECT osm_id, geometry,
COALESCE(
LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')),
NULLIF(boundary, ''),
NULLIF(leisure, '')
) AS class,
name, name_en, name_de, tags,
NULL::int as rank
FROM (
-- etldoc: osm_park_polygon_gen8 -> layer_park:z6
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen8
WHERE zoom_level = 6 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen7 -> layer_park:z7
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen7
WHERE zoom_level = 7 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen6 -> layer_park:z8
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen6
WHERE zoom_level = 8 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen5 -> layer_park:z9
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen5
WHERE zoom_level = 9 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen4 -> layer_park:z10
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen4
WHERE zoom_level = 10 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen3 -> layer_park:z11
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen3
WHERE zoom_level = 11 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen2 -> layer_park:z12
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen2
WHERE zoom_level = 12 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen1 -> layer_park:z13
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon_gen1
WHERE zoom_level = 13 AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon -> layer_park:z14
SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title
FROM osm_park_polygon
WHERE zoom_level >= 14 AND geometry && bbox
) AS park_polygon
UNION ALL
SELECT osm_id, geometry_point AS geometry,
COALESCE(
LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')),
NULLIF(boundary, ''),
NULLIF(leisure, '')
) AS class,
name, name_en, name_de, tags,
row_number() OVER (
PARTITION BY LabelGrid(geometry_point, 100 * pixel_width)
ORDER BY
(CASE WHEN boundary = 'national_park' THEN true ELSE false END) DESC,
(COALESCE(NULLIF(tags->'wikipedia', ''), NULLIF(tags->'wikidata', '')) IS NOT NULL) DESC,
area DESC
)::int AS "rank"
FROM (
-- etldoc: osm_park_polygon_gen8 -> layer_park:z6
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen8
WHERE zoom_level = 6 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen7 -> layer_park:z7
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen7
WHERE zoom_level = 7 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen6 -> layer_park:z8
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen6
WHERE zoom_level = 8 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen5 -> layer_park:z9
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen5
WHERE zoom_level = 9 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen4 -> layer_park:z10
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen4
WHERE zoom_level = 10 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen3 -> layer_park:z11
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen3
WHERE zoom_level = 11 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen2 -> layer_park:z12
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen2
WHERE zoom_level = 12 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen1 -> layer_park:z13
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon_gen1
WHERE zoom_level = 13 AND geometry_point && bbox
UNION ALL
-- etldoc: osm_park_polygon -> layer_park:z14
SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area
FROM osm_park_polygon
WHERE zoom_level >= 14 AND geometry_point && bbox
) AS park_point
) AS park_all;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -1,48 +1,48 @@
generalized_tables: generalized_tables:
# etldoc: imposm3 -> osm_park_polygon_gen8 # etldoc: osm_park_polygon_gen_z7 -> osm_park_polygon_gen_z6
park_polygon_gen8: park_polygon_gen_z6:
source: park_polygon_gen7 source: park_polygon_gen_z7
sql_filter: area>power(ZRES5,2) sql_filter: area>power(ZRES5,2)
tolerance: ZRES8 tolerance: ZRES8
# etldoc: imposm3 -> osm_park_polygon_gen7 # etldoc: osm_park_polygon_gen_z8 -> osm_park_polygon_gen_z7
park_polygon_gen7: park_polygon_gen_z7:
source: park_polygon_gen6 source: park_polygon_gen_z8
sql_filter: area>power(ZRES6,2) sql_filter: area>power(ZRES6,2)
tolerance: ZRES8 tolerance: ZRES8
# etldoc: imposm3 -> osm_park_polygon_gen6 # etldoc: osm_park_polygon_gen_z9 -> osm_park_polygon_gen_z8
park_polygon_gen6: park_polygon_gen_z8:
source: park_polygon_gen5 source: park_polygon_gen_z9
sql_filter: area>power(ZRES7,2) sql_filter: area>power(ZRES7,2)
tolerance: ZRES9 tolerance: ZRES9
# etldoc: imposm3 -> osm_park_polygon_gen5 # etldoc: osm_park_polygon_gen_z10 -> osm_park_polygon_gen_z9
park_polygon_gen5: park_polygon_gen_z9:
source: park_polygon_gen4 source: park_polygon_gen_z10
sql_filter: area>power(ZRES8,2) sql_filter: area>power(ZRES8,2)
tolerance: ZRES10 tolerance: ZRES10
# etldoc: imposm3 -> osm_park_polygon_gen4 # etldoc: osm_park_polygon_gen_z11 -> osm_park_polygon_gen_z10
park_polygon_gen4: park_polygon_gen_z10:
source: park_polygon_gen3 source: park_polygon_gen_z11
sql_filter: area>power(ZRES9,2) sql_filter: area>power(ZRES9,2)
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_park_polygon_gen3 # etldoc: osm_park_polygon_gen_z12 -> osm_park_polygon_gen_z11
park_polygon_gen3: park_polygon_gen_z11:
source: park_polygon_gen2 source: park_polygon_gen_z12
sql_filter: area>power(ZRES10,2) sql_filter: area>power(ZRES10,2)
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_park_polygon_gen2 # etldoc: osm_park_polygon_gen_z13 -> osm_park_polygon_gen_z12
park_polygon_gen2: park_polygon_gen_z12:
source: park_polygon_gen1 source: park_polygon_gen_z13
sql_filter: area>power(ZRES11,2) sql_filter: area>power(ZRES11,2)
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_park_polygon_gen1 # etldoc: osm_park_polygon -> osm_park_polygon_gen_z13
park_polygon_gen1: park_polygon_gen_z13:
source: park_polygon source: park_polygon
sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry) sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13

341
layers/park/park.sql Normal file
View File

@ -0,0 +1,341 @@
-- etldoc: layer_park[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_park |<z6> z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_park(bbox geometry, zoom_level int, pixel_width numeric)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
class text,
name text,
name_en text,
name_de text,
tags hstore,
rank int
)
AS
$$
SELECT osm_id,
geometry,
class,
name,
name_en,
name_de,
tags,
rank
FROM (
SELECT osm_id,
geometry,
COALESCE(
LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')),
NULLIF(boundary, ''),
NULLIF(leisure, '')
) AS class,
name,
name_en,
name_de,
tags,
NULL::int AS rank
FROM (
-- etldoc: osm_park_polygon_gen_z6 -> layer_park:z6
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z6
WHERE zoom_level = 6
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z7 -> layer_park:z7
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z7
WHERE zoom_level = 7
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z8 -> layer_park:z8
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z8
WHERE zoom_level = 8
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z9 -> layer_park:z9
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z9
WHERE zoom_level = 9
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z10 -> layer_park:z10
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z10
WHERE zoom_level = 10
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z11 -> layer_park:z11
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z11
WHERE zoom_level = 11
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z12 -> layer_park:z12
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z12
WHERE zoom_level = 12
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon_gen_z13 -> layer_park:z13
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon_gen_z13
WHERE zoom_level = 13
AND geometry && bbox
UNION ALL
-- etldoc: osm_park_polygon -> layer_park:z14
SELECT osm_id,
geometry,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title
FROM osm_park_polygon
WHERE zoom_level >= 14
AND geometry && bbox
) AS park_polygon
UNION ALL
SELECT osm_id,
geometry_point AS geometry,
COALESCE(
LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')),
NULLIF(boundary, ''),
NULLIF(leisure, '')
) AS class,
name,
name_en,
name_de,
tags,
row_number() OVER (
PARTITION BY LabelGrid(geometry_point, 100 * pixel_width)
ORDER BY
(CASE WHEN boundary = 'national_park' THEN TRUE ELSE FALSE END) DESC,
(COALESCE(NULLIF(tags->'wikipedia', ''), NULLIF(tags->'wikidata', '')) IS NOT NULL) DESC,
area DESC
)::int AS "rank"
FROM (
-- etldoc: osm_park_polygon_gen_z6 -> layer_park:z6
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z6
WHERE zoom_level = 6
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z7 -> layer_park:z7
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z7
WHERE zoom_level = 7
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z8 -> layer_park:z8
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z8
WHERE zoom_level = 8
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z9 -> layer_park:z9
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z9
WHERE zoom_level = 9
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z10 -> layer_park:z10
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z10
WHERE zoom_level = 10
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z11 -> layer_park:z11
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z11
WHERE zoom_level = 11
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z12 -> layer_park:z12
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z12
WHERE zoom_level = 12
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon_gen_z13 -> layer_park:z13
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon_gen_z13
WHERE zoom_level = 13
AND geometry_point && bbox
AND area > 70000*2^(20-zoom_level)
UNION ALL
-- etldoc: osm_park_polygon -> layer_park:z14
SELECT osm_id,
geometry_point,
name,
name_en,
name_de,
tags,
leisure,
boundary,
protection_title,
area
FROM osm_park_polygon
WHERE zoom_level >= 14
AND geometry_point && bbox
) AS park_point
) AS park_all;
$$ LANGUAGE SQL STABLE
PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL

View File

@ -26,7 +26,7 @@ layer:
query: (SELECT geometry, class, name, name_en, name_de, {name_languages}, rank FROM layer_park(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t query: (SELECT geometry, class, name, name_en, name_de, {name_languages}, rank FROM layer_park(!bbox!, z(!scale_denominator!), !pixel_width!)) AS t
schema: schema:
- ./update_park_polygon.sql - ./update_park_polygon.sql
- ./layer.sql - ./park.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,140 +1,156 @@
ALTER TABLE osm_park_polygon ADD COLUMN IF NOT EXISTS geometry_point geometry; ALTER TABLE osm_park_polygon
ALTER TABLE osm_park_polygon_gen1 ADD COLUMN IF NOT EXISTS geometry_point geometry; ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen2 ADD COLUMN IF NOT EXISTS geometry_point geometry; ALTER TABLE osm_park_polygon_gen_z13
ALTER TABLE osm_park_polygon_gen3 ADD COLUMN IF NOT EXISTS geometry_point geometry; ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen4 ADD COLUMN IF NOT EXISTS geometry_point geometry; ALTER TABLE osm_park_polygon_gen_z12
ALTER TABLE osm_park_polygon_gen5 ADD COLUMN IF NOT EXISTS geometry_point geometry; ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen6 ADD COLUMN IF NOT EXISTS geometry_point geometry; ALTER TABLE osm_park_polygon_gen_z11
ALTER TABLE osm_park_polygon_gen7 ADD COLUMN IF NOT EXISTS geometry_point geometry; ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen8 ADD COLUMN IF NOT EXISTS geometry_point geometry; ALTER TABLE osm_park_polygon_gen_z10
ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen_z9
ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen_z8
ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen_z7
ADD COLUMN IF NOT EXISTS geometry_point geometry;
ALTER TABLE osm_park_polygon_gen_z6
ADD COLUMN IF NOT EXISTS geometry_point geometry;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen1; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z13;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen2; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z12;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen3; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z11;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen4; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z10;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen5; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z9;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen6; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z8;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen7; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z7;
DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen8; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen_z6;
-- etldoc: osm_park_polygon -> osm_park_polygon -- etldoc: osm_park_polygon -> osm_park_polygon
-- etldoc: osm_park_polygon_gen1 -> osm_park_polygon_gen1 -- etldoc: osm_park_polygon_gen_z13 -> osm_park_polygon_gen_z13
-- etldoc: osm_park_polygon_gen2 -> osm_park_polygon_gen2 -- etldoc: osm_park_polygon_gen_z12 -> osm_park_polygon_gen_z12
-- etldoc: osm_park_polygon_gen3 -> osm_park_polygon_gen3 -- etldoc: osm_park_polygon_gen_z11 -> osm_park_polygon_gen_z11
-- etldoc: osm_park_polygon_gen4 -> osm_park_polygon_gen4 -- etldoc: osm_park_polygon_gen_z10 -> osm_park_polygon_gen_z10
-- etldoc: osm_park_polygon_gen5 -> osm_park_polygon_gen5 -- etldoc: osm_park_polygon_gen_z9 -> osm_park_polygon_gen_z9
-- etldoc: osm_park_polygon_gen6 -> osm_park_polygon_gen6 -- etldoc: osm_park_polygon_gen_z8 -> osm_park_polygon_gen_z8
-- etldoc: osm_park_polygon_gen7 -> osm_park_polygon_gen7 -- etldoc: osm_park_polygon_gen_z7 -> osm_park_polygon_gen_z7
-- etldoc: osm_park_polygon_gen8 -> osm_park_polygon_gen8 -- etldoc: osm_park_polygon_gen_z6 -> osm_park_polygon_gen_z6
CREATE OR REPLACE FUNCTION update_osm_park_polygon() RETURNS VOID AS $$ CREATE OR REPLACE FUNCTION update_osm_park_polygon() RETURNS void AS
$$
BEGIN BEGIN
UPDATE osm_park_polygon UPDATE osm_park_polygon
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen1 UPDATE osm_park_polygon_gen_z13
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen2 UPDATE osm_park_polygon_gen_z12
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen3 UPDATE osm_park_polygon_gen_z11
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen4 UPDATE osm_park_polygon_gen_z10
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen5 UPDATE osm_park_polygon_gen_z9
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen6 UPDATE osm_park_polygon_gen_z8
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen7 UPDATE osm_park_polygon_gen_z7
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
UPDATE osm_park_polygon_gen8 UPDATE osm_park_polygon_gen_z6
SET tags = update_tags(tags, geometry), SET tags = update_tags(tags, geometry),
geometry_point = st_centroid(geometry); geometry_point = st_centroid(geometry);
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
SELECT update_osm_park_polygon(); SELECT update_osm_park_polygon();
CREATE INDEX IF NOT EXISTS osm_park_polygon_point_geom_idx ON osm_park_polygon USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_point_geom_idx ON osm_park_polygon USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen1_point_geom_idx ON osm_park_polygon_gen1 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z13_point_geom_idx ON osm_park_polygon_gen_z13 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen2_point_geom_idx ON osm_park_polygon_gen2 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z12_point_geom_idx ON osm_park_polygon_gen_z12 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen3_point_geom_idx ON osm_park_polygon_gen3 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z11_point_geom_idx ON osm_park_polygon_gen_z11 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen4_point_geom_idx ON osm_park_polygon_gen4 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z10_point_geom_idx ON osm_park_polygon_gen_z10 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen5_point_geom_idx ON osm_park_polygon_gen5 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z9_point_geom_idx ON osm_park_polygon_gen_z9 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen6_point_geom_idx ON osm_park_polygon_gen6 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z8_point_geom_idx ON osm_park_polygon_gen_z8 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen7_point_geom_idx ON osm_park_polygon_gen7 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z7_point_geom_idx ON osm_park_polygon_gen_z7 USING gist (geometry_point);
CREATE INDEX IF NOT EXISTS osm_park_polygon_gen8_point_geom_idx ON osm_park_polygon_gen8 USING gist(geometry_point); CREATE INDEX IF NOT EXISTS osm_park_polygon_gen_z6_point_geom_idx ON osm_park_polygon_gen_z6 USING gist (geometry_point);
CREATE OR REPLACE FUNCTION update_osm_park_polygon_row() CREATE OR REPLACE FUNCTION update_osm_park_polygon_row()
RETURNS TRIGGER RETURNS trigger
AS AS
$BODY$ $$
BEGIN BEGIN
NEW.tags = update_tags(NEW.tags, NEW.geometry); NEW.tags = update_tags(NEW.tags, NEW.geometry);
NEW.geometry_point = st_centroid(NEW.geometry); NEW.geometry_point = st_centroid(NEW.geometry);
RETURN NEW; RETURN NEW;
END; END;
$BODY$ $$ LANGUAGE plpgsql;
LANGUAGE plpgsql;
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen1 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z13
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen2 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z12
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen3 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z11
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen4 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z10
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen5 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z9
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen6 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z8
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen7 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z7
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();
CREATE TRIGGER update_row CREATE TRIGGER update_row
BEFORE INSERT OR UPDATE ON osm_park_polygon_gen8 BEFORE INSERT OR UPDATE
FOR EACH ROW ON osm_park_polygon_gen_z6
FOR EACH ROW
EXECUTE PROCEDURE update_osm_park_polygon_row(); EXECUTE PROCEDURE update_osm_park_polygon_row();

View File

@ -1,9 +1,10 @@
CREATE OR REPLACE FUNCTION normalize_capital_level(capital TEXT) CREATE OR REPLACE FUNCTION normalize_capital_level(capital text)
RETURNS INT AS $$ RETURNS int AS
SELECT CASE
WHEN capital IN ('yes', '2') THEN 2
WHEN capital = '4' THEN 4
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN capital IN ('yes', '2') THEN 2
WHEN capital = '4' THEN 4
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;

View File

@ -1,57 +1,79 @@
-- etldoc: layer_city[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: layer_city[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_city | <z2_14> z2-z14+" ] ; -- etldoc: label="layer_city | <z2_14> z2-z14+" ] ;
-- etldoc: osm_city_point -> layer_city:z2_14 -- etldoc: osm_city_point -> layer_city:z2_14
CREATE OR REPLACE FUNCTION layer_city(bbox geometry, zoom_level int, pixel_width numeric) 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, name_de text, tags hstore, place city_place, "rank" int, capital int) AS $$ RETURNS TABLE
SELECT * FROM ( (
SELECT osm_id, geometry, name, osm_id bigint,
COALESCE(NULLIF(name_en, ''), name) AS name_en, geometry geometry,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, name text,
tags, name_en text,
place, "rank", normalize_capital_level(capital) AS capital name_de text,
FROM osm_city_point tags hstore,
WHERE geometry && bbox place city_place,
AND ((zoom_level = 2 AND "rank" = 1) "rank" int,
OR (zoom_level BETWEEN 3 AND 7 AND "rank" <= zoom_level + 1) capital int
) )
UNION ALL AS
SELECT osm_id, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
place,
COALESCE("rank", gridrank + 10),
normalize_capital_level(capital) AS capital
FROM (
SELECT osm_id, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
place, "rank", capital,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 128 * pixel_width)
ORDER BY "rank" ASC NULLS LAST,
place ASC NULLS LAST,
population DESC NULLS LAST,
length(name) ASC
)::int AS gridrank
FROM osm_city_point
WHERE geometry && bbox
AND ((zoom_level = 7 AND place <= 'town'::city_place
OR (zoom_level BETWEEN 8 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 BETWEEN 7 AND 8 AND (gridrank <= 4 OR "rank" IS NOT NULL))
OR (zoom_level = 9 AND (gridrank <= 8 OR "rank" IS NOT NULL))
OR (zoom_level = 10 AND (gridrank <= 12 OR "rank" IS NOT NULL))
OR (zoom_level BETWEEN 11 AND 12 AND (gridrank <= 14 OR "rank" IS NOT NULL))
OR (zoom_level >= 13)
) as city_all;
$$ $$
LANGUAGE SQL SELECT *
IMMUTABLE PARALLEL SAFE; FROM (
SELECT osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
place,
"rank",
normalize_capital_level(capital) AS capital
FROM osm_city_point
WHERE geometry && bbox
AND ((zoom_level = 2 AND "rank" = 1)
OR (zoom_level BETWEEN 3 AND 7 AND "rank" <= zoom_level + 1)
)
UNION ALL
SELECT osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
place,
COALESCE("rank", gridrank + 10),
normalize_capital_level(capital) AS capital
FROM (
SELECT osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
place,
"rank",
capital,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 128 * pixel_width)
ORDER BY "rank" ASC NULLS LAST,
place ASC NULLS LAST,
population DESC NULLS LAST,
length(name) ASC
)::int AS gridrank
FROM osm_city_point
WHERE geometry && bbox
AND ((zoom_level = 7 AND place <= 'town'::city_place
OR (zoom_level BETWEEN 8 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 BETWEEN 7 AND 8 AND (gridrank <= 4 OR "rank" IS NOT NULL))
OR (zoom_level = 9 AND (gridrank <= 8 OR "rank" IS NOT NULL))
OR (zoom_level = 10 AND (gridrank <= 12 OR "rank" IS NOT NULL))
OR (zoom_level BETWEEN 11 AND 12 AND (gridrank <= 14 OR "rank" IS NOT NULL))
OR (zoom_level >= 13)
) AS city_all;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -1,11 +1,12 @@
CREATE OR REPLACE FUNCTION island_rank(area REAL) RETURNS INT AS $$ CREATE OR REPLACE FUNCTION island_rank(area real) RETURNS int AS
SELECT CASE
WHEN area < 10000000 THEN 6
WHEN area BETWEEN 1000000 AND 15000000 THEN 5
WHEN area BETWEEN 15000000 AND 40000000 THEN 4
WHEN area > 40000000 THEN 3
ELSE 7
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN area < 10000000 THEN 6
WHEN area BETWEEN 1000000 AND 15000000 THEN 5
WHEN area BETWEEN 15000000 AND 40000000 THEN 4
WHEN area > 40000000 THEN 3
ELSE 7
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;

View File

@ -1,101 +0,0 @@
-- etldoc: layer_place[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_place | <z0_3> z0-3|<z4_7> z4-7|<z8_11> z8-11| <z12_14> z12-z14+" ] ;
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,
name_de text, tags hstore, class text, "rank" int, capital INT, iso_a2
TEXT) AS $$
SELECT * FROM (
-- etldoc: osm_continent_point -> layer_place:z0_3
SELECT
osm_id*10, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'continent' AS class, 1 AS "rank", NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_continent_point
WHERE geometry && bbox AND zoom_level < 4
UNION ALL
-- etldoc: osm_country_point -> layer_place:z0_3
-- etldoc: osm_country_point -> layer_place:z4_7
-- etldoc: osm_country_point -> layer_place:z8_11
-- etldoc: osm_country_point -> layer_place:z12_14
SELECT
osm_id*10, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'country' AS class, "rank", NULL::int AS capital,
iso3166_1_alpha_2 AS iso_a2
FROM osm_country_point
WHERE geometry && bbox AND "rank" <= zoom_level + 1 AND name <> ''
UNION ALL
-- etldoc: osm_state_point -> layer_place:z0_3
-- etldoc: osm_state_point -> layer_place:z4_7
-- etldoc: osm_state_point -> layer_place:z8_11
-- etldoc: osm_state_point -> layer_place:z12_14
SELECT
osm_id*10, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'state' AS class, "rank", NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_state_point
WHERE geometry && bbox AND
name <> '' AND
("rank" + 2 <= zoom_level) AND (
zoom_level >= 5 OR
is_in_country IN ('United Kingdom', 'USA', 'Россия', 'Brasil', 'China', 'India') OR
is_in_country_code IN ('AU', 'CN', 'IN', 'BR', 'US'))
UNION ALL
-- etldoc: osm_island_point -> layer_place:z12_14
SELECT
osm_id*10, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'island' AS class, 7 AS "rank", NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_island_point
WHERE zoom_level >= 12
AND geometry && bbox
UNION ALL
-- etldoc: osm_island_polygon -> layer_place:z8_11
-- etldoc: osm_island_polygon -> layer_place:z12_14
SELECT
osm_id*10, geometry, name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'island' AS class, island_rank(area) AS "rank", NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_island_polygon
WHERE geometry && bbox AND
((zoom_level = 8 AND island_rank(area) <= 3)
OR (zoom_level = 9 AND island_rank(area) <= 4)
OR (zoom_level >= 10))
UNION ALL
-- etldoc: layer_city -> layer_place:z0_3
-- etldoc: layer_city -> layer_place:z4_7
-- etldoc: layer_city -> layer_place:z8_11
-- etldoc: layer_city -> layer_place:z12_14
SELECT
osm_id*10, geometry, name, name_en, name_de,
tags,
place::text AS class, "rank", capital,
NULL::text AS iso_a2
FROM layer_city(bbox, zoom_level, pixel_width)
ORDER BY "rank" ASC
) AS place_all
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -174,5 +174,6 @@ tables:
- village - village
- hamlet - hamlet
- suburb - suburb
- quarter
- neighbourhood - neighbourhood
- isolated_dwelling - isolated_dwelling

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

143
layers/place/place.sql Normal file
View File

@ -0,0 +1,143 @@
-- etldoc: layer_place[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_place | <z0_3> z0-3|<z4_7> z4-7|<z8_11> z8-11| <z12_14> z12-z14+" ] ;
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,
name_de text,
tags hstore,
class text,
"rank" int,
capital int,
iso_a2 text
)
AS
$$
SELECT *
FROM (
SELECT
-- etldoc: osm_continent_point -> layer_place:z0_3
osm_id * 10 AS osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'continent' AS class,
1 AS "rank",
NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_continent_point
WHERE geometry && bbox
AND zoom_level < 4
UNION ALL
SELECT
-- etldoc: osm_country_point -> layer_place:z0_3
-- etldoc: osm_country_point -> layer_place:z4_7
-- etldoc: osm_country_point -> layer_place:z8_11
-- etldoc: osm_country_point -> layer_place:z12_14
osm_id * 10 AS osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'country' AS class,
"rank",
NULL::int AS capital,
iso3166_1_alpha_2 AS iso_a2
FROM osm_country_point
WHERE geometry && bbox
AND "rank" <= zoom_level + 1
AND name <> ''
UNION ALL
SELECT
-- etldoc: osm_state_point -> layer_place:z0_3
-- etldoc: osm_state_point -> layer_place:z4_7
-- etldoc: osm_state_point -> layer_place:z8_11
-- etldoc: osm_state_point -> layer_place:z12_14
osm_id * 10 AS osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'state' AS class,
"rank",
NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_state_point
WHERE geometry && bbox
AND name <> ''
AND zoom_level > 1
UNION ALL
SELECT
-- etldoc: osm_island_point -> layer_place:z12_14
osm_id * 10 AS osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'island' AS class,
7 AS "rank",
NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_island_point
WHERE zoom_level >= 12
AND geometry && bbox
UNION ALL
SELECT
-- etldoc: osm_island_polygon -> layer_place:z8_11
-- etldoc: osm_island_polygon -> layer_place:z12_14
osm_id * 10 AS osm_id,
geometry,
name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
'island' AS class,
island_rank(area) AS "rank",
NULL::int AS capital,
NULL::text AS iso_a2
FROM osm_island_polygon
WHERE geometry && bbox
AND ((zoom_level = 8 AND island_rank(area) <= 3)
OR (zoom_level = 9 AND island_rank(area) <= 4)
OR (zoom_level >= 10))
UNION ALL
SELECT
-- etldoc: layer_city -> layer_place:z0_3
-- etldoc: layer_city -> layer_place:z4_7
-- etldoc: layer_city -> layer_place:z8_11
-- etldoc: layer_city -> layer_place:z12_14
osm_id * 10 AS osm_id,
geometry,
name,
name_en,
name_de,
tags,
place::text AS class,
"rank",
capital,
NULL::text AS iso_a2
FROM layer_city(bbox, zoom_level, pixel_width)
ORDER BY "rank" ASC
) AS place_all
$$ LANGUAGE SQL STABLE
PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL

View File

@ -32,11 +32,12 @@ layer:
- village - village
- hamlet - hamlet
- suburb - suburb
- quarter
- neighbourhood - neighbourhood
- isolated_dwelling - isolated_dwelling
iso_a2: iso_a2:
description: | description: |
Two-letter country code [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Two-letter country code [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Available only for `class=country`.
Original value of the Original value of the
[`country_code_iso3166_1_alpha_2`](http://wiki.openstreetmap.org/wiki/Tag:place%3Dcountry) tag. [`country_code_iso3166_1_alpha_2`](http://wiki.openstreetmap.org/wiki/Tag:place%3Dcountry) tag.
rank: rank:
@ -72,7 +73,7 @@ schema:
- ./update_island_point.sql - ./update_island_point.sql
- ./update_state_point.sql - ./update_state_point.sql
- ./update_city_point.sql - ./update_city_point.sql
- ./layer.sql - ./place.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,9 +1,11 @@
DO $$ DO
BEGIN $$
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'city_place') THEN BEGIN
CREATE TYPE city_place AS ENUM ('city', 'town', 'village', 'hamlet', 'suburb', 'neighbourhood', 'isolated_dwelling'); IF NOT EXISTS(SELECT 1 FROM pg_type WHERE typname = 'city_place') THEN
END IF; CREATE TYPE city_place AS enum ('city', 'town', 'village', 'hamlet', 'suburb', 'quarter', 'neighbourhood', 'isolated_dwelling');
END END IF;
END
$$; $$;
ALTER TABLE osm_city_point ALTER COLUMN place TYPE city_place USING place::city_place; ALTER TABLE osm_city_point
ALTER COLUMN place TYPE city_place USING place::city_place;

View File

@ -1,87 +1,116 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_city_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_city_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_city_point;
DROP TRIGGER IF EXISTS trigger_refresh ON place_city.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_city.updates;
CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE OR REPLACE FUNCTION update_osm_city_point() RETURNS VOID AS $$ CREATE SCHEMA IF NOT EXISTS place_city;
BEGIN
-- Clear OSM key:rank ( https://github.com/openmaptiles/openmaptiles/issues/108 ) CREATE TABLE IF NOT EXISTS place_city.osm_ids
-- etldoc: osm_city_point -> osm_city_point (
UPDATE osm_city_point AS osm SET "rank" = NULL WHERE "rank" IS NOT NULL; osm_id bigint
);
-- etldoc: ne_10m_populated_places -> osm_city_point CREATE OR REPLACE FUNCTION update_osm_city_point(full_update boolean) RETURNS void AS
-- etldoc: osm_city_point -> osm_city_point $$
-- etldoc: ne_10m_populated_places -> osm_city_point
-- etldoc: osm_city_point -> osm_city_point
WITH important_city_point AS ( WITH important_city_point AS (
SELECT osm.geometry, osm.osm_id, osm.name, osm.name_en, ne.scalerank, ne.labelrank SELECT osm.osm_id, ne.scalerank
FROM ne_10m_populated_places AS ne, osm_city_point AS osm FROM osm_city_point AS osm
WHERE -- Clear OSM key:rank ( https://github.com/openmaptiles/openmaptiles/issues/108 )
( LEFT JOIN ne_10m_populated_places AS ne ON
(osm.tags ? 'wikidata' AND osm.tags->'wikidata' = ne.wikidataid) OR (
ne.name ILIKE osm.name OR (osm.tags ? 'wikidata' AND osm.tags->'wikidata' = ne.wikidataid) OR
ne.name ILIKE osm.name_en OR lower(osm.name) IN (lower(ne.name), lower(ne.namealt), lower(ne.meganame), lower(ne.gn_ascii), lower(ne.nameascii)) OR
ne.namealt ILIKE osm.name OR lower(osm.name_en) IN (lower(ne.name), lower(ne.namealt), lower(ne.meganame), lower(ne.gn_ascii), lower(ne.nameascii)) OR
ne.namealt ILIKE osm.name_en OR ne.name = unaccent(osm.name)
ne.meganame ILIKE osm.name OR )
ne.meganame ILIKE osm.name_en OR AND osm.place IN ('city', 'town', 'village')
ne.gn_ascii ILIKE osm.name OR AND ST_DWithin(ne.geometry, osm.geometry, 50000)
ne.gn_ascii ILIKE osm.name_en OR )
ne.nameascii ILIKE osm.name OR UPDATE osm_city_point AS osm
ne.nameascii ILIKE osm.name_en OR -- Move scalerank to range 1 to 10 and merge scalerank 5 with 6 since not enough cities
ne.name = unaccent(osm.name) -- are in the scalerank 5 bucket
) SET "rank" = CASE WHEN scalerank <= 5 THEN scalerank + 1 ELSE scalerank END
AND osm.place IN ('city', 'town', 'village') FROM important_city_point AS ne
AND ST_DWithin(ne.geometry, osm.geometry, 50000) WHERE (full_update OR osm.osm_id IN (SELECT osm_id FROM place_city.osm_ids))
) AND rank IS DISTINCT FROM CASE WHEN scalerank <= 5 THEN scalerank + 1 ELSE scalerank END
UPDATE osm_city_point AS osm AND osm.osm_id = ne.osm_id;
-- Move scalerank to range 1 to 10 and merge scalerank 5 with 6 since not enough cities
-- are in the scalerank 5 bucket
SET "rank" = CASE WHEN scalerank <= 5 THEN scalerank + 1 ELSE scalerank END
FROM important_city_point AS ne
WHERE osm.osm_id = ne.osm_id;
UPDATE osm_city_point UPDATE osm_city_point
SET tags = update_tags(tags, geometry) SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_city.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
END; $$ LANGUAGE SQL;
$$ LANGUAGE plpgsql;
SELECT update_osm_city_point(); SELECT update_osm_city_point(true);
CREATE INDEX IF NOT EXISTS osm_city_point_rank_idx ON osm_city_point("rank"); CREATE INDEX IF NOT EXISTS osm_city_point_rank_idx ON osm_city_point ("rank");
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS place_city; CREATE OR REPLACE FUNCTION place_city.store() RETURNS trigger AS
$$
CREATE TABLE IF NOT EXISTS place_city.updates(id serial primary key, t text, unique (t));
CREATE OR REPLACE FUNCTION place_city.flag() RETURNS trigger AS $$
BEGIN BEGIN
INSERT INTO place_city.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_city.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_city.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_city.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_city.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_city.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_city.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_city.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_city rank'; RAISE LOG 'Refresh place_city rank';
PERFORM update_osm_city_point(); PERFORM update_osm_city_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_city.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_city.updates; DELETE FROM place_city.updates;
RETURN null;
END; RAISE LOG 'Refresh place_city done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_city_point
FOR EACH ROW
EXECUTE PROCEDURE place_city.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_city_point AFTER INSERT OR UPDATE OR DELETE
ON osm_city_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_city.flag(); EXECUTE PROCEDURE place_city.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_city.updates AFTER INSERT
ON place_city.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_city.refresh(); EXECUTE PROCEDURE place_city.refresh();

View File

@ -1,48 +1,86 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_continent_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_continent_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_continent_point;
DROP TRIGGER IF EXISTS trigger_refresh ON place_continent_point.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_continent_point.updates;
-- etldoc: osm_continent_point -> osm_continent_point
CREATE OR REPLACE FUNCTION update_osm_continent_point() RETURNS VOID AS $$
BEGIN
UPDATE osm_continent_point
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END;
$$ LANGUAGE plpgsql;
SELECT update_osm_continent_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS place_continent_point; CREATE SCHEMA IF NOT EXISTS place_continent_point;
CREATE TABLE IF NOT EXISTS place_continent_point.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS place_continent_point.osm_ids
CREATE OR REPLACE FUNCTION place_continent_point.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_continent_point -> osm_continent_point
CREATE OR REPLACE FUNCTION update_osm_continent_point(full_update boolean) RETURNS void AS
$$
UPDATE osm_continent_point
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_continent_point.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
$$ LANGUAGE SQL;
SELECT update_osm_continent_point(true);
-- Handle updates
CREATE OR REPLACE FUNCTION place_continent_point.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO place_continent_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_continent_point.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_continent_point.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_continent_point.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_continent_point.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_continent_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_continent_point.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_continent_point.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_continent_point'; RAISE LOG 'Refresh place_continent_point';
PERFORM update_osm_continent_point(); PERFORM update_osm_continent_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_continent_point.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_continent_point.updates; DELETE FROM place_continent_point.updates;
RETURN null;
END; RAISE LOG 'Refresh place_continent_point done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_continent_point
FOR EACH ROW
EXECUTE PROCEDURE place_continent_point.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_continent_point AFTER INSERT OR UPDATE OR DELETE
ON osm_continent_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_continent_point.flag(); EXECUTE PROCEDURE place_continent_point.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_continent_point.updates AFTER INSERT
ON place_continent_point.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_continent_point.refresh(); EXECUTE PROCEDURE place_continent_point.refresh();

View File

@ -1,119 +1,165 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_country_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_country_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_country_point;
DROP TRIGGER IF EXISTS trigger_refresh ON place_country.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_country.updates;
ALTER TABLE osm_country_point DROP CONSTRAINT IF EXISTS osm_country_point_rank_constraint; CREATE SCHEMA IF NOT EXISTS place_country;
CREATE TABLE IF NOT EXISTS place_country.osm_ids
(
osm_id bigint
);
-- etldoc: ne_10m_admin_0_countries -> osm_country_point -- etldoc: ne_10m_admin_0_countries -> osm_country_point
-- etldoc: osm_country_point -> osm_country_point -- etldoc: osm_country_point -> osm_country_point
CREATE OR REPLACE FUNCTION update_osm_country_point() RETURNS VOID AS $$ CREATE OR REPLACE FUNCTION update_osm_country_point(full_update boolean) RETURNS void AS
BEGIN $$
UPDATE osm_country_point AS osm
SET "rank" = 7,
iso3166_1_alpha_2 = COALESCE(
NULLIF(osm.country_code_iso3166_1_alpha_2, ''),
NULLIF(osm.iso3166_1_alpha_2, ''),
NULLIF(osm.iso3166_1, '')
)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_country.osm_ids))
AND rank IS NULL;
UPDATE osm_country_point AS osm WITH important_country_point AS (
SET SELECT osm.geometry,
"rank" = 7, osm.osm_id,
iso3166_1_alpha_2 = COALESCE( osm.name,
NULLIF(osm.country_code_iso3166_1_alpha_2, ''), COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en,
NULLIF(osm.iso3166_1_alpha_2, ''), ne.scalerank,
NULLIF(osm.iso3166_1, '') ne.labelrank
FROM ne_10m_admin_0_countries AS ne,
osm_country_point AS osm
WHERE
-- We match only countries with ISO codes to eliminate disputed countries
iso3166_1_alpha_2 IS NOT NULL
-- that lies inside polygon of sovereign country
AND ST_Within(osm.geometry, ne.geometry)
) )
; UPDATE osm_country_point AS osm
-- Normalize both scalerank and labelrank into a ranking system from 1 to 6
-- where the ranks are still distributed uniform enough across all countries
SET "rank" = LEAST(6, CEILING((scalerank + labelrank) / 2.0))
FROM important_country_point AS ne
WHERE (full_update OR osm.osm_id IN (SELECT osm_id FROM place_country.osm_ids))
AND rank = 7
AND osm.osm_id = ne.osm_id;
WITH important_country_point AS ( -- Repeat the step for archipelago countries like Philippines or Indonesia
SELECT osm.geometry, osm.osm_id, osm.name, COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, ne.scalerank, ne.labelrank -- whose label point is not within country's polygon
FROM ne_10m_admin_0_countries AS ne, osm_country_point AS osm WITH important_country_point AS (
WHERE SELECT osm.osm_id,
-- We match only countries with ISO codes to eliminate disputed countries
iso3166_1_alpha_2 IS NOT NULL
-- that lies inside polygon of sovereign country
AND ST_Within(osm.geometry, ne.geometry)
)
UPDATE osm_country_point AS osm
-- Normalize both scalerank and labelrank into a ranking system from 1 to 6
-- where the ranks are still distributed uniform enough across all countries
SET "rank" = LEAST(6, CEILING((scalerank + labelrank)/2.0))
FROM important_country_point AS ne
WHERE osm.osm_id = ne.osm_id;
-- Repeat the step for archipelago countries like Philippines or Indonesia
-- whose label point is not within country's polygon
WITH important_country_point AS (
SELECT
osm.osm_id,
-- osm.name, -- osm.name,
ne.scalerank, ne.scalerank,
ne.labelrank, ne.labelrank,
-- ST_Distance(osm.geometry, ne.geometry) AS distance, -- ST_Distance(osm.geometry, ne.geometry) AS distance,
ROW_NUMBER() ROW_NUMBER()
OVER ( OVER (
PARTITION BY osm.osm_id PARTITION BY osm.osm_id
ORDER BY ORDER BY
ST_Distance(osm.geometry, ne.geometry) ST_Distance(osm.geometry, ne.geometry)
) AS rk ) AS rk
FROM osm_country_point osm, FROM osm_country_point osm,
ne_10m_admin_0_countries AS ne ne_10m_admin_0_countries AS ne
WHERE WHERE iso3166_1_alpha_2 IS NOT NULL
iso3166_1_alpha_2 IS NOT NULL AND NOT (osm."rank" BETWEEN 1 AND 6)
AND NOT (osm."rank" BETWEEN 1 AND 6) )
) UPDATE osm_country_point AS osm
UPDATE osm_country_point AS osm -- Normalize both scalerank and labelrank into a ranking system from 1 to 6
-- Normalize both scalerank and labelrank into a ranking system from 1 to 6 -- where the ranks are still distributed uniform enough across all countries
-- where the ranks are still distributed uniform enough across all countries SET "rank" = LEAST(6, CEILING((ne.scalerank + ne.labelrank) / 2.0))
SET "rank" = LEAST(6, CEILING((ne.scalerank + ne.labelrank)/2.0)) FROM important_country_point AS ne
FROM important_country_point AS ne WHERE (full_update OR osm.osm_id IN (SELECT osm_id FROM place_country.osm_ids))
WHERE osm.osm_id = ne.osm_id AND ne.rk = 1; AND rank = 7
AND osm.osm_id = ne.osm_id
AND ne.rk = 1;
UPDATE osm_country_point AS osm UPDATE osm_country_point AS osm
SET "rank" = 6 SET "rank" = 6
WHERE "rank" = 7; WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_country.osm_ids))
AND "rank" = 7;
-- TODO: This shouldn't be necessary? The rank function makes something wrong... -- TODO: This shouldn't be necessary? The rank function makes something wrong...
UPDATE osm_country_point AS osm UPDATE osm_country_point AS osm
SET "rank" = 1 SET "rank" = 1
WHERE "rank" = 0; WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_country.osm_ids))
AND "rank" = 0;
UPDATE osm_country_point UPDATE osm_country_point
SET tags = update_tags(tags, geometry) SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_country.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
END; $$ LANGUAGE SQL;
$$ LANGUAGE plpgsql;
SELECT update_osm_country_point(); SELECT update_osm_country_point(true);
-- ALTER TABLE osm_country_point ADD CONSTRAINT osm_country_point_rank_constraint CHECK("rank" BETWEEN 1 AND 6); CREATE INDEX IF NOT EXISTS osm_country_point_rank_idx ON osm_country_point ("rank");
CREATE INDEX IF NOT EXISTS osm_country_point_rank_idx ON osm_country_point("rank");
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS place_country; CREATE OR REPLACE FUNCTION place_country.store() RETURNS trigger AS
$$
CREATE TABLE IF NOT EXISTS place_country.updates(id serial primary key, t text, unique (t));
CREATE OR REPLACE FUNCTION place_country.flag() RETURNS trigger AS $$
BEGIN BEGIN
INSERT INTO place_country.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_country.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_country.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_country.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_country.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_country.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_country.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_country.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_country rank'; RAISE LOG 'Refresh place_country rank';
PERFORM update_osm_country_point(); PERFORM update_osm_country_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_country.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_country.updates; DELETE FROM place_country.updates;
RETURN null;
END; RAISE LOG 'Refresh place_country done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_country_point
FOR EACH ROW
EXECUTE PROCEDURE place_country.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_country_point AFTER INSERT OR UPDATE OR DELETE
ON osm_country_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_country.flag(); EXECUTE PROCEDURE place_country.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_country.updates AFTER INSERT
ON place_country.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_country.refresh(); EXECUTE PROCEDURE place_country.refresh();

View File

@ -1,48 +1,86 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_island_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_island_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_island_point;
DROP TRIGGER IF EXISTS trigger_refresh ON place_island_point.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_island_point.updates;
-- etldoc: osm_island_point -> osm_island_point
CREATE OR REPLACE FUNCTION update_osm_island_point() RETURNS VOID AS $$
BEGIN
UPDATE osm_island_point
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END;
$$ LANGUAGE plpgsql;
SELECT update_osm_island_point();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS place_island_point; CREATE SCHEMA IF NOT EXISTS place_island_point;
CREATE TABLE IF NOT EXISTS place_island_point.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS place_island_point.osm_ids
CREATE OR REPLACE FUNCTION place_island_point.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_island_point -> osm_island_point
CREATE OR REPLACE FUNCTION update_osm_island_point(full_update boolean) RETURNS void AS
$$
UPDATE osm_island_point
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_island_point.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
$$ LANGUAGE SQL;
SELECT update_osm_island_point(true);
-- Handle updates
CREATE OR REPLACE FUNCTION place_island_point.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO place_island_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_island_point.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_island_point.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_island_point.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_island_point.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_island_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_island_point.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_island_point.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_island_point'; RAISE LOG 'Refresh place_island_point';
PERFORM update_osm_island_point(); PERFORM update_osm_island_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_island_point.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_island_point.updates; DELETE FROM place_island_point.updates;
RETURN null;
END; RAISE LOG 'Refresh place_island_point done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_island_point
FOR EACH ROW
EXECUTE PROCEDURE place_island_point.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_island_point AFTER INSERT OR UPDATE OR DELETE
ON osm_island_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_island_point.flag(); EXECUTE PROCEDURE place_island_point.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_island_point.updates AFTER INSERT
ON place_island_point.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_island_point.refresh(); EXECUTE PROCEDURE place_island_point.refresh();

View File

@ -1,51 +1,93 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_island_polygon; DROP TRIGGER IF EXISTS trigger_flag ON osm_island_polygon;
DROP TRIGGER IF EXISTS trigger_store ON osm_island_polygon;
DROP TRIGGER IF EXISTS trigger_refresh ON place_island_polygon.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_island_polygon.updates;
-- etldoc: osm_island_polygon -> osm_island_polygon
CREATE OR REPLACE FUNCTION update_osm_island_polygon() RETURNS VOID AS $$
BEGIN
UPDATE osm_island_polygon SET geometry=ST_PointOnSurface(geometry) WHERE ST_GeometryType(geometry) <> 'ST_Point';
UPDATE osm_island_polygon
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
ANALYZE osm_island_polygon;
END;
$$ LANGUAGE plpgsql;
SELECT update_osm_island_polygon();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS place_island_polygon; CREATE SCHEMA IF NOT EXISTS place_island_polygon;
CREATE TABLE IF NOT EXISTS place_island_polygon.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS place_island_polygon.osm_ids
CREATE OR REPLACE FUNCTION place_island_polygon.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_island_polygon -> osm_island_polygon
CREATE OR REPLACE FUNCTION update_osm_island_polygon(full_update boolean) RETURNS void AS
$$
UPDATE osm_island_polygon
SET geometry = ST_PointOnSurface(geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_island_polygon.osm_ids))
AND ST_GeometryType(geometry) <> 'ST_Point'
AND ST_IsValid(geometry);
UPDATE osm_island_polygon
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_island_polygon.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
$$ LANGUAGE SQL;
SELECT update_osm_island_polygon(true);
-- Handle updates
CREATE OR REPLACE FUNCTION place_island_polygon.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO place_island_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_island_polygon.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_island_polygon.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_island_polygon.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_island_polygon.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_island_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_island_polygon.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_island_polygon.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_island_polygon'; RAISE LOG 'Refresh place_island_polygon';
PERFORM update_osm_island_polygon(); PERFORM update_osm_island_polygon(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_island_polygon.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_island_polygon.updates; DELETE FROM place_island_polygon.updates;
RETURN null;
END; RAISE LOG 'Refresh place_island_polygon done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_island_polygon
FOR EACH ROW
EXECUTE PROCEDURE place_island_polygon.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_island_polygon AFTER INSERT OR UPDATE OR DELETE
ON osm_island_polygon
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_island_polygon.flag(); EXECUTE PROCEDURE place_island_polygon.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_island_polygon.updates AFTER INSERT
ON place_island_polygon.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_island_polygon.refresh(); EXECUTE PROCEDURE place_island_polygon.refresh();

View File

@ -1,79 +1,127 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_state_point; DROP TRIGGER IF EXISTS trigger_flag ON osm_state_point;
DROP TRIGGER IF EXISTS trigger_store ON osm_state_point;
DROP TRIGGER IF EXISTS trigger_refresh ON place_state.updates; DROP TRIGGER IF EXISTS trigger_refresh ON place_state.updates;
ALTER TABLE osm_state_point DROP CONSTRAINT IF EXISTS osm_state_point_rank_constraint; CREATE SCHEMA IF NOT EXISTS place_state;
CREATE TABLE IF NOT EXISTS place_state.osm_ids
(
osm_id bigint
);
-- etldoc: ne_10m_admin_1_states_provinces -> osm_state_point -- etldoc: ne_10m_admin_1_states_provinces -> osm_state_point
-- etldoc: osm_state_point -> osm_state_point -- etldoc: osm_state_point -> osm_state_point
CREATE OR REPLACE FUNCTION update_osm_state_point() RETURNS VOID AS $$ CREATE OR REPLACE FUNCTION update_osm_state_point(full_update boolean) RETURNS void AS
BEGIN $$
WITH important_state_point AS (
SELECT osm.geometry,
osm.osm_id,
osm.name,
COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en,
ne.scalerank,
ne.labelrank,
ne.datarank
FROM ne_10m_admin_1_states_provinces AS ne,
osm_state_point AS osm
WHERE
-- We only match whether the point is within the Natural Earth polygon
-- because name matching is difficult
ST_Within(osm.geometry, ne.geometry)
-- We leave out leess important states
AND ne.scalerank <= 3
AND ne.labelrank <= 2
)
UPDATE osm_state_point AS osm
-- Normalize both scalerank and labelrank into a ranking system from 1 to 6.
SET "rank" = LEAST(6, CEILING((scalerank + labelrank + datarank) / 3.0))
FROM important_state_point AS ne
WHERE (full_update OR osm.osm_id IN (SELECT osm_id FROM place_state.osm_ids))
AND rank IS NULL
AND osm.osm_id = ne.osm_id;
WITH important_state_point AS ( -- TODO: This shouldn't be necessary? The rank function makes something wrong...
SELECT osm.geometry, osm.osm_id, osm.name, COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, ne.scalerank, ne.labelrank, ne.datarank UPDATE osm_state_point AS osm
FROM ne_10m_admin_1_states_provinces AS ne, osm_state_point AS osm SET "rank" = 1
WHERE WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_state.osm_ids))
-- We only match whether the point is within the Natural Earth polygon AND "rank" = 0;
-- because name matching is difficult
ST_Within(osm.geometry, ne.geometry)
-- We leave out leess important states
AND ne.scalerank <= 3 AND ne.labelrank <= 2
)
UPDATE osm_state_point AS osm
-- Normalize both scalerank and labelrank into a ranking system from 1 to 6.
SET "rank" = LEAST(6, CEILING((scalerank + labelrank + datarank)/3.0))
FROM important_state_point AS ne
WHERE osm.osm_id = ne.osm_id;
-- TODO: This shouldn't be necessary? The rank function makes something wrong... DELETE FROM osm_state_point
UPDATE osm_state_point AS osm WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_state.osm_ids))
SET "rank" = 1 AND "rank" IS NULL;
WHERE "rank" = 0;
DELETE FROM osm_state_point WHERE "rank" IS NULL; UPDATE osm_state_point
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM place_state.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
UPDATE osm_state_point $$ LANGUAGE SQL;
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END; SELECT update_osm_state_point(true);
$$ LANGUAGE plpgsql;
SELECT update_osm_state_point(); CREATE INDEX IF NOT EXISTS osm_state_point_rank_idx ON osm_state_point ("rank");
-- ALTER TABLE osm_state_point ADD CONSTRAINT osm_state_point_rank_constraint CHECK("rank" BETWEEN 1 AND 6);
CREATE INDEX IF NOT EXISTS osm_state_point_rank_idx ON osm_state_point("rank");
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS place_state; CREATE OR REPLACE FUNCTION place_state.store() RETURNS trigger AS
$$
CREATE TABLE IF NOT EXISTS place_state.updates(id serial primary key, t text, unique (t));
CREATE OR REPLACE FUNCTION place_state.flag() RETURNS trigger AS $$
BEGIN BEGIN
INSERT INTO place_state.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO place_state.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO place_state.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS place_state.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION place_state.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO place_state.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION place_state.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION place_state.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh place_state rank'; RAISE LOG 'Refresh place_state rank';
PERFORM update_osm_state_point(); PERFORM update_osm_state_point(false);
-- noinspection SqlWithoutWhere
DELETE FROM place_state.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM place_state.updates; DELETE FROM place_state.updates;
RETURN null;
END; RAISE LOG 'Refresh place_state done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_state_point
FOR EACH ROW
EXECUTE PROCEDURE place_state.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_state_point AFTER INSERT OR UPDATE OR DELETE
ON osm_state_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE place_state.flag(); EXECUTE PROCEDURE place_state.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON place_state.updates AFTER INSERT
ON place_state.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE place_state.refresh(); EXECUTE PROCEDURE place_state.refresh();

View File

@ -1,40 +1,83 @@
CREATE OR REPLACE FUNCTION poi_class_rank(class TEXT) CREATE OR REPLACE FUNCTION poi_class_rank(class text, subclass text)
RETURNS INT AS $$ RETURNS int AS
SELECT CASE class
WHEN 'hospital' THEN 20
WHEN 'railway' THEN 40
WHEN 'bus' THEN 50
WHEN 'attraction' THEN 70
WHEN 'harbor' THEN 75
WHEN 'college' THEN 80
WHEN 'school' THEN 85
WHEN 'stadium' THEN 90
WHEN 'zoo' THEN 95
WHEN 'town_hall' THEN 100
WHEN 'campsite' THEN 110
WHEN 'cemetery' THEN 115
WHEN 'park' THEN 120
WHEN 'library' THEN 130
WHEN 'police' THEN 135
WHEN 'post' THEN 140
WHEN 'golf' THEN 150
WHEN 'shop' THEN 400
WHEN 'grocery' THEN 500
WHEN 'fast_food' THEN 600
WHEN 'clothing_store' THEN 700
WHEN 'bar' THEN 800
ELSE 1000
END;
$$ $$
LANGUAGE SQL SELECT CASE class
IMMUTABLE PARALLEL SAFE; WHEN 'hospital' THEN 20
WHEN 'airport' THEN 30
WHEN 'railway' THEN 40
WHEN 'aerialway' THEN 40
WHEN 'heliport' THEN 45
WHEN 'taxi' THEN 50
WHEN 'harbor' THEN 55
WHEN 'library' THEN 60
WHEN 'bus' THEN
CASE subclass
WHEN 'bus_station' THEN 70
ELSE 72
END
WHEN 'attraction' THEN 75
WHEN 'college' THEN 80
WHEN 'school' THEN 85
WHEN 'stadium' THEN 90
WHEN 'zoo' THEN 95
WHEN 'town_hall' THEN 100
WHEN 'campsite' THEN 110
WHEN 'cemetery' THEN 115
WHEN 'park' THEN 120
WHEN 'library' THEN 130
WHEN 'police' THEN 135
WHEN 'post' THEN 140
WHEN 'golf' THEN 150
WHEN 'entrance' THEN 250
WHEN 'parking' THEN 300
WHEN 'car_parking' THEN 300
WHEN 'fuel' THEN 350
WHEN 'charging_station' THEN 355
WHEN 'bicycle_parking' THEN 360
WHEN 'motorcycle_parking' THEN 360
WHEN 'bank' THEN 380
WHEN 'art_gallery' THEN 400
WHEN 'information' THEN 420
WHEN 'fast_food' THEN 430
WHEN 'ice_cream' THEN 430
WHEN 'bar' THEN 450
WHEN 'cafe' THEN 450
WHEN 'grocery' THEN 450
WHEN 'bakery' THEN 475
WHEN 'community_centre' THEN 500
WHEN 'shop' THEN 600
WHEN 'optician' THEN 600
WHEN 'furniture' THEN 600
WHEN 'jewelry' THEN 600
WHEN 'toys' THEN 600
WHEN 'newsagent' THEN 600
WHEN 'paint' THEN 600
WHEN 'electronics' THEN 600
WHEN 'garden_centre' THEN 600
WHEN 'mobile_phone' THEN 600
WHEN 'shoes' THEN 600
WHEN 'clothing_store' THEN 600
WHEN 'florist' THEN 600
WHEN 'laundry' THEN 700
WHEN 'dog_park' THEN 800
WHEN 'pitch' THEN 800
WHEN 'power_tower' then 900
WHEN 'wind_mill' then 900
WHEN 'water_tower' then 900
WHEN 'communications_tower' then 900
WHEN 'wind_turbine' then 900
WHEN 'shelter' then 3000
ELSE 1000
END;
$$ LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;
CREATE OR REPLACE FUNCTION poi_class(subclass TEXT, mapping_key TEXT) CREATE OR REPLACE FUNCTION poi_class(subclass text, mapping_key text, subtype text)
RETURNS TEXT AS $$ RETURNS text AS
SELECT CASE
%%FIELD_MAPPING: class %%
ELSE subclass
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE PARALLEL SAFE; %%FIELD_MAPPING: class %%
ELSE subclass
END;
$$ LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;

View File

@ -1,75 +0,0 @@
-- etldoc: layer_poi[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_poi | <z12> z12 | <z13> z13 | <z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_poi(bbox geometry, zoom_level integer, pixel_width numeric)
RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, name_de text, tags hstore, class text, subclass text, agg_stop integer, layer integer, level integer, indoor integer, "rank" int) AS $$
SELECT osm_id_hash AS osm_id, geometry, NULLIF(name, '') AS name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
poi_class(subclass, mapping_key) AS class,
CASE
WHEN subclass = 'information'
THEN NULLIF(information, '')
WHEN subclass = 'place_of_worship'
THEN NULLIF(religion, '')
WHEN subclass = 'pitch'
THEN NULLIF(sport, '')
ELSE subclass
END AS subclass,
agg_stop,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor=TRUE THEN 1 END as indoor,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 100 * pixel_width)
ORDER BY CASE WHEN name = '' THEN 2000 ELSE poi_class_rank(poi_class(subclass, mapping_key)) END ASC
)::int AS "rank"
FROM (
-- etldoc: osm_poi_point -> layer_poi:z12
-- etldoc: osm_poi_point -> layer_poi:z13
SELECT *,
osm_id*10 AS osm_id_hash FROM osm_poi_point
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass='station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_poi_point -> layer_poi:z14_
SELECT *,
osm_id*10 AS osm_id_hash FROM osm_poi_point
WHERE geometry && bbox
AND zoom_level >= 14
UNION ALL
-- etldoc: osm_poi_polygon -> layer_poi:z12
-- etldoc: osm_poi_polygon -> layer_poi:z13
SELECT *,
NULL::INTEGER AS agg_stop,
CASE WHEN osm_id<0 THEN -osm_id*10+4
ELSE osm_id*10+1
END AS osm_id_hash
FROM osm_poi_polygon
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass='station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_poi_polygon -> layer_poi:z14_
SELECT *,
NULL::INTEGER AS agg_stop,
CASE WHEN osm_id<0 THEN -osm_id*10+4
ELSE osm_id*10+1
END AS osm_id_hash
FROM osm_poi_polygon
WHERE geometry && bbox
AND zoom_level >= 14
) as poi_union
ORDER BY "rank"
;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -21,6 +21,7 @@ def_poi_mapping_amenity: &poi_mapping_amenity
- clinic - clinic
- college - college
- community_centre - community_centre
- social_facility
- courthouse - courthouse
- dentist - dentist
- doctors - doctors
@ -62,6 +63,7 @@ def_poi_mapping_amenity: &poi_mapping_amenity
- university - university
- veterinary - veterinary
- waste_basket - waste_basket
- charging_station
# barrier values , see http://taginfo.openstreetmap.org/keys/barrier#values # barrier values , see http://taginfo.openstreetmap.org/keys/barrier#values
def_poi_mapping_barrier: &poi_mapping_barrier def_poi_mapping_barrier: &poi_mapping_barrier
@ -77,10 +79,13 @@ def_poi_mapping_barrier: &poi_mapping_barrier
# building values , see http://taginfo.openstreetmap.org/keys/building#values # building values , see http://taginfo.openstreetmap.org/keys/building#values
def_poi_mapping_building: &poi_mapping_building def_poi_mapping_building: &poi_mapping_building
- dormitory - dormitory
- office
- industrial
# highway values , see http://taginfo.openstreetmap.org/keys/highway#values # highway values , see http://taginfo.openstreetmap.org/keys/highway#values
def_poi_mapping_highway: &poi_mapping_highway def_poi_mapping_highway: &poi_mapping_highway
- bus_stop - bus_stop
- speed_camera
# historic values , see http://taginfo.openstreetmap.org/keys/historic#values # historic values , see http://taginfo.openstreetmap.org/keys/historic#values
def_poi_mapping_historic: &poi_mapping_historic def_poi_mapping_historic: &poi_mapping_historic
@ -114,6 +119,7 @@ def_poi_mapping_leisure: &poi_mapping_leisure
- swimming_area - swimming_area
- swimming_pool - swimming_pool
- water_park - water_park
- nature_reserve
# railway values , see http://taginfo.openstreetmap.org/keys/railway#values # railway values , see http://taginfo.openstreetmap.org/keys/railway#values
def_poi_mapping_railway: &poi_mapping_railway def_poi_mapping_railway: &poi_mapping_railway
@ -316,6 +322,24 @@ def_poi_mapping_tourism: &poi_mapping_tourism
def_poi_mapping_waterway: &poi_mapping_waterway def_poi_mapping_waterway: &poi_mapping_waterway
- dock - dock
# aeroway values , see http://taginfo.openstreetmap.org/keys/aeroway#values
def_poi_mapping_aeroway: &poi_mapping_aeroway
- helipad
- aerodrome
# aeroway values , see http://taginfo.openstreetmap.org/keys/aeroway#values
def_poi_mapping_power: &poi_mapping_power
- generator
- tower
def_poi_mapping_man_made: &poi_mapping_man_made
- communications_tower
- water_tower
- wind_mill
def_poi_mapping_emergency: &poi_mapping_emergency
- defibrillator
def_poi_fields: &poi_fields def_poi_fields: &poi_fields
- name: osm_id - name: osm_id
type: id type: id
@ -363,6 +387,12 @@ def_poi_fields: &poi_fields
- name: sport - name: sport
key: sport key: sport
type: string type: string
- name: power
key: power
type: string
- name: source
key: "generator:source"
type: string
def_poi_mapping: &poi_mapping def_poi_mapping: &poi_mapping
aerialway: *poi_mapping_aerialway aerialway: *poi_mapping_aerialway
@ -378,6 +408,10 @@ def_poi_mapping: &poi_mapping
sport: *poi_mapping_sport sport: *poi_mapping_sport
tourism: *poi_mapping_tourism tourism: *poi_mapping_tourism
waterway: *poi_mapping_waterway waterway: *poi_mapping_waterway
aeroway: *poi_mapping_aeroway
power: *poi_mapping_power
man_made: *poi_mapping_man_made
emergency: *poi_mapping_emergency
tables: tables:
# etldoc: imposm3 -> osm_poi_point # etldoc: imposm3 -> osm_poi_point

127
layers/poi/poi.sql Normal file
View File

@ -0,0 +1,127 @@
-- etldoc: layer_poi[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_poi | <z12> z12 | <z13> z13 | <z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_poi(bbox geometry, zoom_level integer, pixel_width numeric)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
tags hstore,
class text,
subclass text,
agg_stop integer,
layer integer,
level integer,
indoor integer,
"rank" int
)
AS
$$
SELECT osm_id_hash AS osm_id,
geometry,
NULLIF(name, '') AS name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
poi_class(subclass, mapping_key, subtype) AS class,
CASE
WHEN subclass = 'information'
THEN NULLIF(information, '')
WHEN subclass = 'place_of_worship'
THEN NULLIF(religion, '')
WHEN subclass = 'pitch'
THEN NULLIF(sport, '')
WHEN subclass = 'sports_centre'
THEN NULLIF(sport, subclass)
ELSE subclass
END AS subclass,
agg_stop,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor = TRUE THEN 1 END AS indoor,
row_number() OVER (
PARTITION BY LabelGrid(geometry, 100 * pixel_width)
ORDER BY
CASE
WHEN name = ''
THEN 2000
ELSE poi_class_rank(poi_class(
subclass,
mapping_key,
subtype
), subclass) END ASC
)::int AS "rank"
FROM (
-- Intermediate mapping for subtype and filtering out nameless industrial/office buildings
SELECT *,
CASE
WHEN subclass = 'information'
THEN NULLIF(information, '')
WHEN subclass = 'place_of_worship'
THEN NULLIF(religion, '')
WHEN subclass = 'pitch'
THEN NULLIF(sport, '')
WHEN subclass = 'sports_centre'
THEN NULLIF(sport, '')
WHEN subclass = 'generator' AND mapping_key = 'power'
THEN NULLIF(source, '')
ELSE subclass
END as subtype
FROM (
-- etldoc: osm_poi_point -> layer_poi:z12
-- etldoc: osm_poi_point -> layer_poi:z13
SELECT *,
osm_id * 10 AS osm_id_hash
FROM osm_poi_point
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass = 'station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_poi_point -> layer_poi:z14_
SELECT *,
osm_id * 10 AS osm_id_hash
FROM osm_poi_point
WHERE geometry && bbox
AND zoom_level >= 14
UNION ALL
-- etldoc: osm_poi_polygon -> layer_poi:z12
-- etldoc: osm_poi_polygon -> layer_poi:z13
SELECT *,
NULL::integer AS agg_stop,
CASE
WHEN osm_id < 0 THEN -osm_id * 10 + 4
ELSE osm_id * 10 + 1
END AS osm_id_hash
FROM osm_poi_polygon
WHERE geometry && bbox
AND zoom_level BETWEEN 12 AND 13
AND ((subclass = 'station' AND mapping_key = 'railway')
OR subclass IN ('halt', 'ferry_terminal'))
UNION ALL
-- etldoc: osm_poi_polygon -> layer_poi:z14_
SELECT *,
NULL::integer AS agg_stop,
CASE
WHEN osm_id < 0 THEN -osm_id * 10 + 4
ELSE osm_id * 10 + 1
END AS osm_id_hash
FROM osm_poi_polygon
WHERE geometry && bbox
AND zoom_level >= 14
) AS poi_union_raw
WHERE NOT (mapping_key = 'building' AND (subclass = 'office' OR subclass = 'industrial') AND coalesce(name, name_en, '') = '')
) AS poi_union
ORDER BY "rank"
$$ LANGUAGE SQL STABLE
PARALLEL SAFE;
-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL

View File

@ -18,15 +18,41 @@ layer:
values: values:
shop: shop:
subclass: ['accessories', 'antiques', 'beauty', 'bed', 'boutique', 'camera', 'carpet', 'charity', 'chemist', subclass: ['accessories', 'antiques', 'beauty', 'bed', 'boutique', 'camera', 'carpet', 'charity', 'chemist',
'coffee', 'computer', 'convenience', 'copyshop', 'cosmetics', 'garden_centre', 'doityourself', 'coffee', 'computer', 'convenience', 'copyshop', 'cosmetics',
'erotic', 'electronics', 'fabric', 'florist', 'frozen_food', 'furniture', 'video_games', 'video', 'erotic', 'fabric', 'frozen_food', 'video_games', 'video', 'general', 'gift',
'general', 'gift', 'hardware', 'hearing_aids', 'hifi', 'ice_cream', 'interior_decoration', 'hearing_aids', 'hifi', 'interior_decoration', 'kiosk', 'lamps', 'mall', 'massage','outdoor',
'jewelry', 'kiosk', 'lamps', 'mall', 'massage', 'motorcycle', 'mobile_phone', 'newsagent', 'perfumery', 'perfume', 'pet', 'photo', 'second_hand', 'sports', 'stationery', 'tailor', 'tattoo',
'optician', 'outdoor', 'perfumery', 'perfume', 'pet', 'photo', 'second_hand', 'shoes', 'sports', 'ticket', 'tobacco', 'travel_agency', 'watches', 'weapons', 'wholesale']
'stationery', 'tailor', 'tattoo', 'ticket', 'tobacco', 'toys', 'travel_agency', 'watches', optician:
'weapons', 'wholesale'] subclass: ['optician']
toys:
subclass: ['toys']
jewelry:
subclass: ['jewelry']
furniture:
subclass: ['furniture']
newsagent:
subclass: ['newsagent']
paint:
subclass: ['paint']
beverages:
subclass: ['beverages']
electronics:
subclass: ['electronics']
garden_centre:
subclass: ['garden_centre']
mobile_phone:
subclass: ['mobile_phone']
shoes:
subclass: ['shoes']
hardware:
subclass: ['hardware', 'doityourself']
florist:
subclass: ['florist']
town_hall: town_hall:
subclass: ['townhall', 'public_building', 'courthouse', 'community_centre'] subclass: ['townhall', 'public_building', 'courthouse']
community_centre:
subclass: ['community_centre', 'social_facility']
golf: golf:
subclass: ['golf', 'golf_course', 'miniature_golf'] subclass: ['golf', 'golf_course', 'miniature_golf']
fast_food: fast_food:
@ -59,7 +85,7 @@ layer:
lodging: lodging:
subclass: ['hotel', 'motel', 'bed_and_breakfast', 'guest_house', 'hostel', 'chalet', 'alpine_hut', 'dormitory'] subclass: ['hotel', 'motel', 'bed_and_breakfast', 'guest_house', 'hostel', 'chalet', 'alpine_hut', 'dormitory']
ice_cream: ice_cream:
subclass: ['chocolate', 'confectionery'] subclass: ['chocolate', 'confectionery', 'ice_cream']
post: post:
subclass: ['post_box', 'post_office'] subclass: ['post_box', 'post_office']
cafe: cafe:
@ -72,8 +98,14 @@ layer:
subclass: ['bar', 'nightclub'] subclass: ['bar', 'nightclub']
harbor: harbor:
subclass: ['marina', 'dock'] subclass: ['marina', 'dock']
car: taxi:
subclass: ['car', 'car_repair', 'car_parts', 'taxi'] subclass: ['taxi']
motorcycle_dealer:
subclass: ['motorcycle']
car_dealer:
subclass: ['car', 'car_parts']
car_repair:
subclass: ['car_repair']
hospital: hospital:
subclass: ['hospital', 'nursing_home', 'clinic'] subclass: ['hospital', 'nursing_home', 'clinic']
cemetery: cemetery:
@ -94,6 +126,25 @@ layer:
subclass: ['swimming_area', 'swimming'] subclass: ['swimming_area', 'swimming']
castle: castle:
subclass: ['castle', 'ruins'] subclass: ['castle', 'ruins']
airport:
subclass: ['aerodrome']
heliport:
subclass: ['helipad']
wind_turbine:
__AND__:
subclass: ['generator']
subtype: ['wind']
mapping_key: ['power']
communications_tower:
subclass: ['communications_tower']
water_tower:
subclass: ['water_tower']
wind_mill:
subclass: ['wind_mill']
power_tower:
subclass: ['tower']
industry:
subclass: ['industrial']
subclass: subclass:
description: | description: |
Original value of either the Original value of either the
@ -150,7 +201,7 @@ schema:
- ./poi_stop_agg.sql - ./poi_stop_agg.sql
- ./update_poi_polygon.sql - ./update_poi_polygon.sql
- ./update_poi_point.sql - ./update_poi_point.sql
- ./layer.sql - ./poi.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,35 +1,31 @@
DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_centroid CASCADE; DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_centroid CASCADE;
CREATE MATERIALIZED VIEW osm_poi_stop_centroid AS ( CREATE MATERIALIZED VIEW osm_poi_stop_centroid AS
SELECT (
uic_ref, SELECT uic_ref,
count(*) as count, count(*) AS count,
CASE WHEN count(*) > 2 THEN ST_Centroid(ST_UNION(geometry)) END AS centroid CASE WHEN count(*) > 2 THEN ST_Centroid(ST_UNION(geometry)) END AS centroid
FROM osm_poi_point FROM osm_poi_point
WHERE WHERE nullif(uic_ref, '') IS NOT NULL
nullif(uic_ref, '') IS NOT NULL AND subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway')
AND subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') GROUP BY uic_ref
GROUP BY HAVING count(*) > 1
uic_ref ) /* DELAY_MATERIALIZED_VIEW_CREATION */;
HAVING
count(*) > 1
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_rank CASCADE; DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_rank CASCADE;
CREATE MATERIALIZED VIEW osm_poi_stop_rank AS ( CREATE MATERIALIZED VIEW osm_poi_stop_rank AS
SELECT (
p.osm_id, SELECT p.osm_id,
-- p.uic_ref, -- p.uic_ref,
-- p.subclass, -- p.subclass,
ROW_NUMBER() ROW_NUMBER()
OVER ( OVER (
PARTITION BY p.uic_ref PARTITION BY p.uic_ref
ORDER BY ORDER BY
p.subclass :: public_transport_stop_type NULLS LAST, p.subclass :: public_transport_stop_type NULLS LAST,
ST_Distance(c.centroid, p.geometry) ST_Distance(c.centroid, p.geometry)
) AS rk ) AS rk
FROM osm_poi_point p FROM osm_poi_point p
INNER JOIN osm_poi_stop_centroid c ON (p.uic_ref = c.uic_ref) INNER JOIN osm_poi_stop_centroid c ON (p.uic_ref = c.uic_ref)
WHERE WHERE subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway')
subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') ORDER BY p.uic_ref, rk
ORDER BY p.uic_ref, rk ) /* DELAY_MATERIALIZED_VIEW_CREATION */;
) /* DELAY_MATERIALIZED_VIEW_CREATION */;

View File

@ -1,11 +1,12 @@
DO $$ DO
BEGIN $$
IF NOT EXISTS (SELECT 1 BEGIN
FROM pg_type IF NOT EXISTS(SELECT 1
WHERE typname = 'public_transport_stop_type') THEN FROM pg_type
CREATE TYPE public_transport_stop_type AS ENUM ( WHERE typname = 'public_transport_stop_type') THEN
'subway', 'tram_stop', 'bus_station', 'bus_stop' CREATE TYPE public_transport_stop_type AS enum (
); 'subway', 'tram_stop', 'bus_station', 'bus_stop'
END IF; );
END END IF;
END
$$; $$;

View File

@ -2,83 +2,99 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_poi_point;
DROP TRIGGER IF EXISTS trigger_refresh ON poi_point.updates; DROP TRIGGER IF EXISTS trigger_refresh ON poi_point.updates;
-- etldoc: osm_poi_point -> osm_poi_point -- etldoc: osm_poi_point -> osm_poi_point
CREATE OR REPLACE FUNCTION update_osm_poi_point() RETURNS VOID AS $$ CREATE OR REPLACE FUNCTION update_osm_poi_point() RETURNS void AS
$$
BEGIN BEGIN
UPDATE osm_poi_point UPDATE osm_poi_point
SET subclass = 'subway' SET subclass = 'subway'
WHERE station = 'subway' and subclass='station'; WHERE station = 'subway'
AND subclass = 'station';
UPDATE osm_poi_point UPDATE osm_poi_point
SET subclass = 'halt' SET subclass = 'halt'
WHERE funicular = 'yes' and subclass='station'; WHERE funicular = 'yes'
AND subclass = 'station';
UPDATE osm_poi_point UPDATE osm_poi_point
SET tags = update_tags(tags, geometry) SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
SELECT update_osm_poi_point(); SELECT update_osm_poi_point();
CREATE OR REPLACE FUNCTION update_osm_poi_point_agg() RETURNS VOID AS $$ CREATE OR REPLACE FUNCTION update_osm_poi_point_agg() RETURNS void AS
$$
BEGIN BEGIN
UPDATE osm_poi_point p UPDATE osm_poi_point p
SET agg_stop = CASE SET agg_stop = CASE
WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway')
THEN 1 THEN 1
END; END;
UPDATE osm_poi_point p UPDATE osm_poi_point p
SET agg_stop = ( SET agg_stop = (
CASE CASE
WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway')
AND r.rk IS NULL OR r.rk = 1 AND r.rk IS NULL OR r.rk = 1
THEN 1 THEN 1
END) END)
FROM osm_poi_stop_rank r FROM osm_poi_stop_rank r
WHERE p.osm_id = r.osm_id WHERE p.osm_id = r.osm_id;
;
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
ALTER TABLE osm_poi_point ADD COLUMN IF NOT EXISTS agg_stop INTEGER DEFAULT NULL; ALTER TABLE osm_poi_point
ADD COLUMN IF NOT EXISTS agg_stop integer DEFAULT NULL;
SELECT update_osm_poi_point_agg(); SELECT update_osm_poi_point_agg();
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS poi_point; CREATE SCHEMA IF NOT EXISTS poi_point;
CREATE TABLE IF NOT EXISTS poi_point.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS poi_point.updates
CREATE OR REPLACE FUNCTION poi_point.flag() RETURNS trigger AS $$ (
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION poi_point.flag() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO poi_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; INSERT INTO poi_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN null; RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION poi_point.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION poi_point.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh poi_point'; RAISE LOG 'Refresh poi_point';
PERFORM update_osm_poi_point(); PERFORM update_osm_poi_point();
REFRESH MATERIALIZED VIEW osm_poi_stop_centroid; REFRESH MATERIALIZED VIEW osm_poi_stop_centroid;
REFRESH MATERIALIZED VIEW osm_poi_stop_rank; REFRESH MATERIALIZED VIEW osm_poi_stop_rank;
PERFORM update_osm_poi_point_agg(); PERFORM update_osm_poi_point_agg();
-- noinspection SqlWithoutWhere
DELETE FROM poi_point.updates; DELETE FROM poi_point.updates;
RETURN null;
END; RAISE LOG 'Refresh poi_point done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_poi_point AFTER INSERT OR UPDATE OR DELETE
ON osm_poi_point
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE poi_point.flag(); EXECUTE PROCEDURE poi_point.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON poi_point.updates AFTER INSERT
ON poi_point.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE poi_point.refresh(); EXECUTE PROCEDURE poi_point.refresh();

View File

@ -1,66 +1,111 @@
DROP TRIGGER IF EXISTS trigger_flag ON osm_poi_polygon; DROP TRIGGER IF EXISTS trigger_flag ON osm_poi_polygon;
DROP TRIGGER IF EXISTS trigger_store ON osm_poi_polygon;
DROP TRIGGER IF EXISTS trigger_refresh ON poi_polygon.updates; DROP TRIGGER IF EXISTS trigger_refresh ON poi_polygon.updates;
-- etldoc: osm_poi_polygon -> osm_poi_polygon
CREATE OR REPLACE FUNCTION update_poi_polygon() RETURNS VOID AS $$
BEGIN
UPDATE osm_poi_polygon
SET geometry =
CASE WHEN ST_NPoints(ST_ConvexHull(geometry))=ST_NPoints(geometry)
THEN ST_Centroid(geometry)
ELSE ST_PointOnSurface(geometry)
END
WHERE ST_GeometryType(geometry) <> 'ST_Point';
UPDATE osm_poi_polygon
SET subclass = 'subway'
WHERE station = 'subway' and subclass='station';
UPDATE osm_poi_polygon
SET subclass = 'halt'
WHERE funicular = 'yes' and subclass='station';
UPDATE osm_poi_polygon
SET tags = update_tags(tags, geometry)
WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL;
ANALYZE osm_poi_polygon;
END;
$$ LANGUAGE plpgsql;
SELECT update_poi_polygon();
-- Handle updates
CREATE SCHEMA IF NOT EXISTS poi_polygon; CREATE SCHEMA IF NOT EXISTS poi_polygon;
CREATE TABLE IF NOT EXISTS poi_polygon.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS poi_polygon.osm_ids
CREATE OR REPLACE FUNCTION poi_polygon.flag() RETURNS trigger AS $$ (
osm_id bigint
);
-- etldoc: osm_poi_polygon -> osm_poi_polygon
CREATE OR REPLACE FUNCTION update_poi_polygon(full_update boolean) RETURNS void AS
$$
UPDATE osm_poi_polygon
SET geometry =
CASE
WHEN ST_NPoints(ST_ConvexHull(geometry)) = ST_NPoints(geometry)
THEN ST_Centroid(geometry)
ELSE ST_PointOnSurface(geometry)
END
WHERE (full_update OR osm_id IN (SELECT osm_id FROM poi_polygon.osm_ids))
AND ST_GeometryType(geometry) <> 'ST_Point'
AND ST_IsValid(geometry);
UPDATE osm_poi_polygon
SET subclass = 'subway'
WHERE (full_update OR osm_id IN (SELECT osm_id FROM poi_polygon.osm_ids))
AND station = 'subway'
AND subclass = 'station';
UPDATE osm_poi_polygon
SET subclass = 'halt'
WHERE (full_update OR osm_id IN (SELECT osm_id FROM poi_polygon.osm_ids))
AND funicular = 'yes'
AND subclass = 'station';
UPDATE osm_poi_polygon
SET tags = update_tags(tags, geometry)
WHERE (full_update OR osm_id IN (SELECT osm_id FROM poi_polygon.osm_ids))
AND COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL
AND tags != update_tags(tags, geometry);
$$ LANGUAGE SQL;
SELECT update_poi_polygon(true);
-- Handle updates
CREATE OR REPLACE FUNCTION poi_polygon.store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO poi_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; IF (tg_op = 'DELETE') THEN
RETURN null; INSERT INTO poi_polygon.osm_ids VALUES (OLD.osm_id);
ELSE
INSERT INTO poi_polygon.osm_ids VALUES (NEW.osm_id);
END IF;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS poi_polygon.updates
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION poi_polygon.flag() RETURNS trigger AS
$$
BEGIN
INSERT INTO poi_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION poi_polygon.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION poi_polygon.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh poi_polygon'; RAISE LOG 'Refresh poi_polygon';
PERFORM update_poi_polygon(); PERFORM update_poi_polygon(false);
-- noinspection SqlWithoutWhere
DELETE FROM poi_polygon.osm_ids;
-- noinspection SqlWithoutWhere
DELETE FROM poi_polygon.updates; DELETE FROM poi_polygon.updates;
RETURN null;
END; RAISE LOG 'Refresh poi_polygon done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store
AFTER INSERT OR UPDATE OR DELETE
ON osm_poi_polygon
FOR EACH ROW
EXECUTE PROCEDURE poi_polygon.store();
CREATE TRIGGER trigger_flag CREATE TRIGGER trigger_flag
AFTER INSERT OR UPDATE OR DELETE ON osm_poi_polygon AFTER INSERT OR UPDATE OR DELETE
ON osm_poi_polygon
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE poi_polygon.flag(); EXECUTE PROCEDURE poi_polygon.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON poi_polygon.updates AFTER INSERT
ON poi_polygon.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE poi_polygon.refresh(); EXECUTE PROCEDURE poi_polygon.refresh();

View File

@ -1,51 +1,58 @@
CREATE OR REPLACE FUNCTION brunnel(is_bridge BOOL, is_tunnel BOOL, is_ford BOOL) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION brunnel(is_bridge bool, is_tunnel bool, is_ford bool) RETURNS text AS
SELECT CASE
WHEN is_bridge THEN 'bridge'
WHEN is_tunnel THEN 'tunnel'
WHEN is_ford THEN 'ford'
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN is_bridge THEN 'bridge'
WHEN is_tunnel THEN 'tunnel'
WHEN is_ford THEN 'ford'
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;
-- The classes for highways are derived from the classes used in ClearTables -- The classes for highways are derived from the classes used in ClearTables
-- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua -- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua
CREATE OR REPLACE FUNCTION highway_class(highway TEXT, public_transport TEXT, construction TEXT) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION highway_class(highway text, public_transport text, construction text) RETURNS text AS
SELECT CASE
%%FIELD_MAPPING: class %%
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE PARALLEL SAFE; %%FIELD_MAPPING: class %%
END;
$$ LANGUAGE SQL IMMUTABLE
PARALLEL SAFE;
-- The classes for railways are derived from the classes used in ClearTables -- The classes for railways are derived from the classes used in ClearTables
-- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua -- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua
CREATE OR REPLACE FUNCTION railway_class(railway TEXT) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION railway_class(railway text) RETURNS text AS
SELECT CASE
WHEN railway IN ('rail', 'narrow_gauge', 'preserved', 'funicular') THEN 'rail'
WHEN railway IN ('subway', 'light_rail', 'monorail', 'tram') THEN 'transit'
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN railway IN ('rail', 'narrow_gauge', 'preserved', 'funicular') THEN 'rail'
WHEN railway IN ('subway', 'light_rail', 'monorail', 'tram') THEN 'transit'
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;
-- Limit service to only the most important values to ensure -- Limit service to only the most important values to ensure
-- we always know the values of service -- we always know the values of service
CREATE OR REPLACE FUNCTION service_value(service TEXT) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION service_value(service text) RETURNS text AS
SELECT CASE
WHEN service IN ('spur', 'yard', 'siding', 'crossover', 'driveway', 'alley', 'parking_aisle') THEN service
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN service IN ('spur', 'yard', 'siding', 'crossover', 'driveway', 'alley', 'parking_aisle') THEN service
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;
-- Limit surface to only the most important values to ensure -- Limit surface to only the most important values to ensure
-- we always know the values of surface -- we always know the values of surface
CREATE OR REPLACE FUNCTION surface_value(surface TEXT) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION surface_value(surface text) RETURNS text AS
SELECT CASE
WHEN surface IN ('paved', 'asphalt', 'cobblestone', 'concrete', 'concrete:lanes', 'concrete:plates', 'metal', 'paving_stones', 'sett', 'unhewn_cobblestone', 'wood') THEN 'paved'
WHEN surface IN ('unpaved', 'compacted', 'dirt', 'earth', 'fine_gravel', 'grass', 'grass_paver', 'gravel', 'gravel_turf', 'ground', 'ice', 'mud', 'pebblestone', 'salt', 'sand', 'snow', 'woodchips') THEN 'unpaved'
END;
$$ $$
LANGUAGE SQL SELECT CASE
IMMUTABLE STRICT PARALLEL SAFE; WHEN surface IN ('paved', 'asphalt', 'cobblestone', 'concrete', 'concrete:lanes', 'concrete:plates', 'metal',
'paving_stones', 'sett', 'unhewn_cobblestone', 'wood') THEN 'paved'
WHEN surface IN ('unpaved', 'compacted', 'dirt', 'earth', 'fine_gravel', 'grass', 'grass_paver', 'gravel',
'gravel_turf', 'ground', 'ice', 'mud', 'pebblestone', 'salt', 'sand', 'snow', 'woodchips')
THEN 'unpaved'
END;
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 KiB

After

Width:  |  Height:  |  Size: 531 KiB

View File

@ -1,373 +0,0 @@
CREATE OR REPLACE FUNCTION highway_is_link(highway TEXT) RETURNS BOOLEAN AS $$
SELECT highway LIKE '%_link';
$$
LANGUAGE SQL
IMMUTABLE STRICT PARALLEL SAFE;
-- etldoc: layer_transportation[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="<sql> layer_transportation |<z4> z4 |<z5> z5 |<z6> z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_transportation(bbox geometry, zoom_level int)
RETURNS TABLE(osm_id bigint, geometry geometry, class text, subclass text,
ramp int, oneway int, brunnel TEXT, service TEXT, layer INT, level INT,
indoor INT, bicycle TEXT, foot TEXT, horse TEXT, mtb_scale TEXT, surface TEXT) AS $$
SELECT
osm_id, geometry,
CASE
WHEN NULLIF(highway, '') IS NOT NULL OR NULLIF(public_transport, '') IS NOT NULL THEN highway_class(highway, public_transport, construction)
WHEN NULLIF(railway, '') IS NOT NULL THEN railway_class(railway)
WHEN NULLIF(aerialway, '') IS NOT NULL THEN aerialway
WHEN NULLIF(shipway, '') IS NOT NULL THEN shipway
WHEN NULLIF(man_made, '') IS NOT NULL THEN man_made
END AS class,
CASE
WHEN railway IS NOT NULL THEN railway
WHEN (highway IS NOT NULL OR public_transport IS NOT NULL)
AND highway_class(highway, public_transport, construction) = 'path'
THEN COALESCE(NULLIF(public_transport, ''), highway)
END AS subclass,
-- All links are considered as ramps as well
CASE WHEN highway_is_link(highway) OR highway = 'steps'
THEN 1 ELSE is_ramp::int END AS ramp,
is_oneway::int AS oneway,
brunnel(is_bridge, is_tunnel, is_ford) AS brunnel,
NULLIF(service, '') AS service,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor=TRUE THEN 1 END as indoor,
NULLIF(bicycle, '') AS bicycle,
NULLIF(foot, '') AS foot,
NULLIF(horse, '') AS horse,
NULLIF(mtb_scale, '') AS mtb_scale,
NULLIF(surface, '') AS surface
FROM (
-- etldoc: osm_transportation_merge_linestring_gen7 -> layer_transportation:z4
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_transportation_merge_linestring_gen7
WHERE zoom_level = 4
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen6 -> layer_transportation:z5
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_transportation_merge_linestring_gen6
WHERE zoom_level = 5
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen5 -> layer_transportation:z6
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_transportation_merge_linestring_gen5
WHERE zoom_level = 6
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen4 -> layer_transportation:z7
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_transportation_merge_linestring_gen4
WHERE zoom_level = 7
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen3 -> layer_transportation:z8
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_transportation_merge_linestring_gen3
WHERE zoom_level = 8
UNION ALL
-- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z9
-- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z10
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
bicycle, foot, horse, mtb_scale,
NULL AS surface, z_order
FROM osm_highway_linestring_gen2
WHERE zoom_level BETWEEN 9 AND 10
AND st_length(geometry)>zres(11)
UNION ALL
-- etldoc: osm_highway_linestring_gen1 -> layer_transportation:z11
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, NULL AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
bicycle, foot, horse, mtb_scale,
NULL AS surface, z_order
FROM osm_highway_linestring_gen1
WHERE zoom_level = 11
AND st_length(geometry)>zres(12)
UNION ALL
-- etldoc: osm_highway_linestring -> layer_transportation:z12
-- etldoc: osm_highway_linestring -> layer_transportation:z13
-- etldoc: osm_highway_linestring -> layer_transportation:z14_
SELECT
osm_id, geometry,
highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, man_made,
layer,
CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level",
CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor,
bicycle, foot, horse, mtb_scale,
surface_value(surface) AS "surface",
z_order
FROM osm_highway_linestring
WHERE NOT is_area AND (
zoom_level = 12 AND (
highway_class(highway, public_transport, construction) NOT IN ('track', 'path', 'minor')
OR highway IN ('unclassified', 'residential')
) AND man_made <> 'pier'
OR zoom_level = 13
AND (
highway_class(highway, public_transport, construction) NOT IN ('track', 'path') AND man_made <> 'pier'
OR
man_made = 'pier' AND NOT ST_IsClosed(geometry)
)
OR zoom_level >= 14
AND (
man_made <> 'pier'
OR
NOT ST_IsClosed(geometry)
)
)
UNION ALL
-- etldoc: osm_railway_linestring_gen5 -> layer_transportation:z8
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL as surface, z_order
FROM osm_railway_linestring_gen5
WHERE zoom_level = 8
AND railway='rail' AND service = '' and usage='main'
UNION ALL
-- etldoc: osm_railway_linestring_gen4 -> layer_transportation:z9
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_railway_linestring_gen4
WHERE zoom_level = 9
AND railway='rail' AND service = '' and usage='main'
UNION ALL
-- etldoc: osm_railway_linestring_gen3 -> layer_transportation:z10
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_railway_linestring_gen3
WHERE zoom_level = 10
AND railway IN ('rail', 'narrow_gauge') AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring_gen2 -> layer_transportation:z11
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL as surface, z_order
FROM osm_railway_linestring_gen2
WHERE zoom_level = 11
AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring_gen1 -> layer_transportation:z12
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL as surface, z_order
FROM osm_railway_linestring_gen1
WHERE zoom_level = 12
AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring -> layer_transportation:z13
-- etldoc: osm_railway_linestring -> layer_transportation:z14_
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL as surface, z_order
FROM osm_railway_linestring
WHERE zoom_level = 13
AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = ''
OR zoom_Level >= 14
UNION ALL
-- etldoc: osm_aerialway_linestring_gen1 -> layer_transportation:z12
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, NULL as railway, aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_aerialway_linestring_gen1
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aerialway_linestring -> layer_transportation:z13
-- etldoc: osm_aerialway_linestring -> layer_transportation:z14_
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, NULL as railway, aerialway, NULL AS shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_aerialway_linestring
WHERE zoom_level >= 13
UNION ALL
-- etldoc: osm_shipway_linestring_gen2 -> layer_transportation:z11
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_shipway_linestring_gen2
WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_shipway_linestring_gen1 -> layer_transportation:z12
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_shipway_linestring_gen1
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_shipway_linestring -> layer_transportation:z13
-- etldoc: osm_shipway_linestring -> layer_transportation:z14_
SELECT
osm_id, geometry,
NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway,
NULL AS public_transport, service_value(service) AS service,
is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_shipway_linestring
WHERE zoom_level >= 13
UNION ALL
-- NOTE: We limit the selection of polys because we need to be
-- careful to net get false positives here because
-- it is possible that closed linestrings appear both as
-- highway linestrings and as polygon
-- etldoc: osm_highway_polygon -> layer_transportation:z13
-- etldoc: osm_highway_polygon -> layer_transportation:z14_
SELECT
osm_id, geometry,
highway, NULL AS construction, NULL AS railway, NULL AS aerialway, NULL AS shipway,
public_transport, NULL AS service,
CASE WHEN man_made IN ('bridge') THEN TRUE
ELSE FALSE
END AS is_bridge, FALSE AS is_tunnel, FALSE AS is_ford,
FALSE AS is_ramp, FALSE::int AS is_oneway, man_made,
layer, NULL::int AS level, NULL::boolean AS indoor,
NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale,
NULL AS surface, z_order
FROM osm_highway_polygon
-- We do not want underground pedestrian areas for now
WHERE zoom_level >= 13
AND (
man_made IN ('bridge', 'pier')
OR (is_area AND COALESCE(layer, 0) >= 0)
)
) AS zoom_levels
WHERE geometry && bbox
ORDER BY z_order ASC;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -1,55 +1,61 @@
generalized_tables: generalized_tables:
# etldoc: imposm3 -> osm_railway_linestring_gen5 # etldoc: osm_railway_linestring_gen_z9 -> osm_railway_linestring_gen_z8
railway_linestring_gen5: railway_linestring_gen_z8:
source: railway_linestring_gen4 source: railway_linestring_gen_z9
tolerance: ZRES9 tolerance: ZRES9
# etldoc: imposm3 -> osm_railway_linestring_gen4 # etldoc: osm_railway_linestring_gen_z10 -> osm_railway_linestring_gen_z9
railway_linestring_gen4: railway_linestring_gen_z9:
source: railway_linestring_gen3 source: railway_linestring_gen_z10
tolerance: ZRES10 tolerance: ZRES10
# etldoc: imposm3 -> osm_railway_linestring_gen3 # etldoc: osm_railway_linestring_gen_z11 -> osm_railway_linestring_gen_z10
railway_linestring_gen3: railway_linestring_gen_z10:
source: railway_linestring_gen2 source: railway_linestring_gen_z11
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_railway_linestring_gen2 # etldoc: osm_railway_linestring_gen_z12 -> osm_railway_linestring_gen_z11
railway_linestring_gen2: railway_linestring_gen_z11:
source: railway_linestring_gen1 source: railway_linestring_gen_z12
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_railway_linestring_gen1 # etldoc: osm_railway_linestring -> osm_railway_linestring_gen_z12
railway_linestring_gen1: railway_linestring_gen_z12:
source: railway_linestring source: railway_linestring
sql_filter: railway IN ('rail', 'narrow_gauge', 'light_rail') AND service='' AND ST_IsValid(geometry) sql_filter: railway IN ('rail', 'narrow_gauge', 'light_rail') AND service='' AND ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
# etldoc: imposm3 -> osm_aerialway_linestring_gen1 # etldoc: osm_aerialway_linestring -> osm_aerialway_linestring_gen_z12
aerialway_linestring_gen1: aerialway_linestring_gen_z12:
source: aerialway_linestring source: aerialway_linestring
sql_filter: ST_IsValid(geometry) sql_filter: ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
# etldoc: imposm3 -> osm_shipway_linestring_gen2 # etldoc: osm_shipway_linestring_gen_z12 -> osm_shipway_linestring_gen_z11
shipway_linestring_gen2: shipway_linestring_gen_z11:
source: shipway_linestring_gen1 source: shipway_linestring_gen_z12
tolerance: ZRES12 tolerance: ZRES12
# etldoc: imposm3 -> osm_shipway_linestring_gen1 # etldoc: osm_shipway_linestring -> osm_shipway_linestring_gen_z12
shipway_linestring_gen1: shipway_linestring_gen_z12:
source: shipway_linestring source: shipway_linestring
sql_filter: ST_IsValid(geometry) sql_filter: ST_IsValid(geometry)
tolerance: ZRES13 tolerance: ZRES13
# etldoc: imposm3 -> osm_highway_linestring_gen2 # etldoc: osm_highway_linestring_gen_z10 -> osm_highway_linestring_gen_z9
highway_linestring_gen2: highway_linestring_gen_z9:
source: highway_linestring_gen1 source: highway_linestring_gen_z10
sql_filter: (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link') OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link')) AND NOT is_area
tolerance: ZRES10
# etldoc: osm_highway_linestring_gen_z11 -> osm_highway_linestring_gen_z10
highway_linestring_gen_z10:
source: highway_linestring_gen_z11
sql_filter: (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link') OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link')) AND NOT is_area sql_filter: (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link') OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary', 'secondary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link')) AND NOT is_area
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_highway_linestring_gen1 # etldoc: osm_highway_linestring -> osm_highway_linestring_gen_z11
highway_linestring_gen1: highway_linestring_gen_z11:
source: highway_linestring source: highway_linestring
sql_filter: (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link') OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link')) AND NOT is_area AND ST_IsValid(geometry) sql_filter: (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link') OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link')) AND NOT is_area AND ST_IsValid(geometry)
tolerance: ZRES12 tolerance: ZRES12

View File

@ -0,0 +1,734 @@
CREATE OR REPLACE FUNCTION highway_is_link(highway text) RETURNS boolean AS
$$
SELECT highway LIKE '%_link';
$$ LANGUAGE SQL IMMUTABLE
STRICT
PARALLEL SAFE;
-- etldoc: layer_transportation[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="<sql> layer_transportation |<z4> z4 |<z5> z5 |<z6> z6 |<z7> z7 |<z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_transportation(bbox geometry, zoom_level int)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
class text,
subclass text,
ramp int,
oneway int,
brunnel text,
service text,
layer int,
level int,
indoor int,
bicycle text,
foot text,
horse text,
mtb_scale text,
surface text
)
AS
$$
SELECT osm_id,
geometry,
CASE
WHEN NULLIF(highway, '') IS NOT NULL OR NULLIF(public_transport, '') IS NOT NULL
THEN highway_class(highway, public_transport, construction)
WHEN NULLIF(railway, '') IS NOT NULL THEN railway_class(railway)
WHEN NULLIF(aerialway, '') IS NOT NULL THEN 'aerialway'
WHEN NULLIF(shipway, '') IS NOT NULL THEN shipway
WHEN NULLIF(man_made, '') IS NOT NULL THEN man_made
END AS class,
CASE
WHEN railway IS NOT NULL THEN railway
WHEN (highway IS NOT NULL OR public_transport IS NOT NULL)
AND highway_class(highway, public_transport, construction) = 'path'
THEN COALESCE(NULLIF(public_transport, ''), highway)
WHEN aerialway IS NOT NULL THEN aerialway
END AS subclass,
-- All links are considered as ramps as well
CASE
WHEN highway_is_link(highway) OR highway = 'steps'
THEN 1
ELSE is_ramp::int END AS ramp,
is_oneway::int AS oneway,
brunnel(is_bridge, is_tunnel, is_ford) AS brunnel,
NULLIF(service, '') AS service,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor = TRUE THEN 1 END AS indoor,
NULLIF(bicycle, '') AS bicycle,
NULLIF(foot, '') AS foot,
NULLIF(horse, '') AS horse,
NULLIF(mtb_scale, '') AS mtb_scale,
NULLIF(surface, '') AS surface
FROM (
-- etldoc: osm_transportation_merge_linestring_gen_z4 -> layer_transportation:z4
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_transportation_merge_linestring_gen_z4
WHERE zoom_level = 4
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen_z5 -> layer_transportation:z5
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_transportation_merge_linestring_gen_z5
WHERE zoom_level = 5
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen_z6 -> layer_transportation:z6
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_transportation_merge_linestring_gen_z6
WHERE zoom_level = 6
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen_z7 -> layer_transportation:z7
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_transportation_merge_linestring_gen_z7
WHERE zoom_level = 7
UNION ALL
-- etldoc: osm_transportation_merge_linestring_gen_z8 -> layer_transportation:z8
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_transportation_merge_linestring_gen_z8
WHERE zoom_level = 8
UNION ALL
-- etldoc: osm_highway_linestring_gen_z9 -> layer_transportation:z9
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
bicycle,
foot,
horse,
mtb_scale,
NULL AS surface,
z_order
FROM osm_highway_linestring_gen_z9
WHERE zoom_level = 9
AND ST_Length(geometry) > ZRes(11)
UNION ALL
-- etldoc: osm_highway_linestring_gen_z10 -> layer_transportation:z10
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
bicycle,
foot,
horse,
mtb_scale,
NULL AS surface,
z_order
FROM osm_highway_linestring_gen_z10
WHERE zoom_level = 10
AND ST_Length(geometry) > ZRes(11)
UNION ALL
-- etldoc: osm_highway_linestring_gen_z11 -> layer_transportation:z11
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
NULL AS service,
is_bridge,
is_tunnel,
is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
bicycle,
foot,
horse,
mtb_scale,
NULL AS surface,
z_order
FROM osm_highway_linestring_gen_z11
WHERE zoom_level = 11
AND ST_Length(geometry) > ZRes(12)
UNION ALL
-- etldoc: osm_highway_linestring -> layer_transportation:z12
-- etldoc: osm_highway_linestring -> layer_transportation:z13
-- etldoc: osm_highway_linestring -> layer_transportation:z14_
SELECT osm_id,
geometry,
highway,
construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
man_made,
layer,
CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level",
CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor,
bicycle,
foot,
horse,
mtb_scale,
surface_value(surface) AS "surface",
z_order
FROM osm_highway_linestring
WHERE NOT is_area
AND (
zoom_level = 12 AND (
highway_class(highway, public_transport, construction) NOT IN ('track', 'path', 'minor')
OR highway IN ('unclassified', 'residential')
) AND man_made <> 'pier'
OR zoom_level = 13
AND (
highway_class(highway, public_transport, construction) NOT IN ('track', 'path') AND
man_made <> 'pier'
OR
man_made = 'pier' AND NOT ST_IsClosed(geometry)
)
OR zoom_level >= 14
AND (
man_made <> 'pier'
OR
NOT ST_IsClosed(geometry)
)
)
UNION ALL
-- etldoc: osm_railway_linestring_gen_z8 -> layer_transportation:z8
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
NULL::boolean AS is_bridge,
NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring_gen_z8
WHERE zoom_level = 8
AND railway = 'rail'
AND service = ''
AND usage = 'main'
UNION ALL
-- etldoc: osm_railway_linestring_gen_z9 -> layer_transportation:z9
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
NULL::boolean AS is_bridge,
NULL::boolean AS is_tunnel,
NULL::boolean AS is_ford,
NULL::boolean AS is_ramp,
NULL::int AS is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring_gen_z9
WHERE zoom_level = 9
AND railway = 'rail'
AND service = ''
AND usage = 'main'
UNION ALL
-- etldoc: osm_railway_linestring_gen_z10 -> layer_transportation:z10
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring_gen_z10
WHERE zoom_level = 10
AND railway IN ('rail', 'narrow_gauge')
AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring_gen_z11 -> layer_transportation:z11
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring_gen_z11
WHERE zoom_level = 11
AND railway IN ('rail', 'narrow_gauge', 'light_rail')
AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring_gen_z12 -> layer_transportation:z12
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring_gen_z12
WHERE zoom_level = 12
AND railway IN ('rail', 'narrow_gauge', 'light_rail')
AND service = ''
UNION ALL
-- etldoc: osm_railway_linestring -> layer_transportation:z13
-- etldoc: osm_railway_linestring -> layer_transportation:z14_
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
railway,
NULL AS aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_railway_linestring
WHERE zoom_level = 13
AND railway IN ('rail', 'narrow_gauge', 'light_rail')
AND service = ''
OR zoom_level >= 14
UNION ALL
-- etldoc: osm_aerialway_linestring_gen_z12 -> layer_transportation:z12
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
NULL AS railway,
aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_aerialway_linestring_gen_z12
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_aerialway_linestring -> layer_transportation:z13
-- etldoc: osm_aerialway_linestring -> layer_transportation:z14_
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
NULL AS railway,
aerialway,
NULL AS shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_aerialway_linestring
WHERE zoom_level >= 13
UNION ALL
-- etldoc: osm_shipway_linestring_gen_z11 -> layer_transportation:z11
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
NULL AS railway,
NULL AS aerialway,
shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_shipway_linestring_gen_z11
WHERE zoom_level = 11
UNION ALL
-- etldoc: osm_shipway_linestring_gen_z12 -> layer_transportation:z12
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
NULL AS railway,
NULL AS aerialway,
shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_shipway_linestring_gen_z12
WHERE zoom_level = 12
UNION ALL
-- etldoc: osm_shipway_linestring -> layer_transportation:z13
-- etldoc: osm_shipway_linestring -> layer_transportation:z14_
SELECT osm_id,
geometry,
NULL AS highway,
NULL AS construction,
NULL AS railway,
NULL AS aerialway,
shipway,
NULL AS public_transport,
service_value(service) AS service,
is_bridge,
is_tunnel,
is_ford,
is_ramp,
is_oneway,
NULL AS man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_shipway_linestring
WHERE zoom_level >= 13
UNION ALL
-- NOTE: We limit the selection of polys because we need to be
-- careful to net get false positives here because
-- it is possible that closed linestrings appear both as
-- highway linestrings and as polygon
-- etldoc: osm_highway_polygon -> layer_transportation:z13
-- etldoc: osm_highway_polygon -> layer_transportation:z14_
SELECT osm_id,
geometry,
highway,
NULL AS construction,
NULL AS railway,
NULL AS aerialway,
NULL AS shipway,
public_transport,
NULL AS service,
CASE
WHEN man_made IN ('bridge') THEN TRUE
ELSE FALSE
END AS is_bridge,
FALSE AS is_tunnel,
FALSE AS is_ford,
FALSE AS is_ramp,
FALSE::int AS is_oneway,
man_made,
layer,
NULL::int AS level,
NULL::boolean AS indoor,
NULL AS bicycle,
NULL AS foot,
NULL AS horse,
NULL AS mtb_scale,
NULL AS surface,
z_order
FROM osm_highway_polygon
-- We do not want underground pedestrian areas for now
WHERE zoom_level >= 13
AND (
man_made IN ('bridge', 'pier')
OR (is_area AND COALESCE(layer, 0) >= 0)
)
) AS zoom_levels
WHERE geometry && bbox
ORDER BY z_order ASC;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -178,7 +178,7 @@ layer:
schema: schema:
- ./class.sql - ./class.sql
- ./update_transportation_merge.sql - ./update_transportation_merge.sql
- ./layer.sql - ./transportation.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ./mapping.yaml mapping_file: ./mapping.yaml

View File

@ -1,11 +1,3 @@
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen3 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen4 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen5 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen6 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen7 CASCADE;
DROP TRIGGER IF EXISTS trigger_flag_transportation ON osm_highway_linestring; DROP TRIGGER IF EXISTS trigger_flag_transportation ON osm_highway_linestring;
DROP TRIGGER IF EXISTS trigger_refresh ON transportation.updates; DROP TRIGGER IF EXISTS trigger_refresh ON transportation.updates;
@ -16,134 +8,184 @@ DROP TRIGGER IF EXISTS trigger_refresh ON transportation.updates;
-- Improve performance of the sql in transportation_name/network_type.sql -- Improve performance of the sql in transportation_name/network_type.sql
CREATE INDEX IF NOT EXISTS osm_highway_linestring_highway_idx
ON osm_highway_linestring(highway);
-- Improve performance of the sql below
CREATE INDEX IF NOT EXISTS osm_highway_linestring_highway_partial_idx CREATE INDEX IF NOT EXISTS osm_highway_linestring_highway_partial_idx
ON osm_highway_linestring(highway) ON osm_highway_linestring (highway)
WHERE highway IN ('motorway','trunk', 'primary', 'construction'); WHERE highway IN ('motorway', 'trunk', 'primary', 'construction');
-- etldoc: osm_highway_linestring -> osm_transportation_merge_linestring -- etldoc: osm_highway_linestring -> osm_transportation_merge_linestring
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring CASCADE;
SELECT CREATE MATERIALIZED VIEW osm_transportation_merge_linestring AS
(ST_Dump(geometry)).geom AS geometry, (
NULL::bigint AS osm_id, SELECT (ST_Dump(geometry)).geom AS geometry,
highway, construction, NULL::bigint AS osm_id,
z_order highway,
FROM ( construction,
SELECT is_bridge,
ST_LineMerge(ST_Collect(geometry)) AS geometry, is_tunnel,
highway, construction, is_ford,
min(z_order) AS z_order z_order
FROM osm_highway_linestring FROM (
WHERE (highway IN ('motorway','trunk', 'primary') OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary')) SELECT ST_LineMerge(ST_Collect(geometry)) AS geometry,
AND ST_IsValid(geometry) highway,
group by highway, construction construction,
) AS highway_union is_bridge,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; is_tunnel,
is_ford,
min(z_order) AS z_order
FROM osm_highway_linestring
WHERE (highway IN ('motorway', 'trunk', 'primary') OR
highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary'))
AND ST_IsValid(geometry)
GROUP BY highway, construction, is_bridge, is_tunnel, is_ford
) AS highway_union
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_geometry_idx CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_geometry_idx
ON osm_transportation_merge_linestring USING gist(geometry); ON osm_transportation_merge_linestring USING gist (geometry);
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_highway_partial_idx
ON osm_transportation_merge_linestring(highway, construction)
WHERE highway IN ('motorway','trunk', 'primary', 'construction');
-- etldoc: osm_transportation_merge_linestring -> osm_transportation_merge_linestring_gen3 -- etldoc: osm_transportation_merge_linestring -> osm_transportation_merge_linestring_gen_z8
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen3 AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen_z8 CASCADE;
SELECT ST_Simplify(geometry, 120) AS geometry, osm_id, highway, construction, z_order CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z8 AS
FROM osm_transportation_merge_linestring (
WHERE highway IN ('motorway','trunk', 'primary') SELECT ST_Simplify(geometry, ZRes(10)) AS geometry,
OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary') osm_id,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; highway,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen3_geometry_idx construction,
ON osm_transportation_merge_linestring_gen3 USING gist(geometry); is_bridge,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen3_highway_partial_idx is_tunnel,
ON osm_transportation_merge_linestring_gen3(highway, construction) is_ford,
WHERE highway IN ('motorway','trunk', 'primary', 'construction'); z_order
FROM osm_transportation_merge_linestring
WHERE highway IN ('motorway', 'trunk', 'primary')
OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary')
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen_z8_geometry_idx
ON osm_transportation_merge_linestring_gen_z8 USING gist (geometry);
-- etldoc: osm_transportation_merge_linestring_gen3 -> osm_transportation_merge_linestring_gen4 -- etldoc: osm_transportation_merge_linestring_gen_z8 -> osm_transportation_merge_linestring_gen_z7
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen4 AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen_z7 CASCADE;
SELECT ST_Simplify(geometry, 200) AS geometry, osm_id, highway, construction, z_order CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z7 AS
FROM osm_transportation_merge_linestring_gen3 (
WHERE (highway IN ('motorway','trunk', 'primary') OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary')) SELECT ST_Simplify(geometry, ZRes(9)) AS geometry,
AND ST_Length(geometry) > 50 osm_id,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; highway,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen4_geometry_idx construction,
ON osm_transportation_merge_linestring_gen4 USING gist(geometry); is_bridge,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen4_highway_partial_idx is_tunnel,
ON osm_transportation_merge_linestring_gen4(highway, construction) is_ford,
WHERE highway IN ('motorway','trunk', 'primary', 'construction'); z_order
FROM osm_transportation_merge_linestring_gen_z8
WHERE (highway IN ('motorway', 'trunk', 'primary') OR
highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary'))
AND ST_Length(geometry) > 50
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen_z7_geometry_idx
ON osm_transportation_merge_linestring_gen_z7 USING gist (geometry);
-- etldoc: osm_transportation_merge_linestring_gen4 -> osm_transportation_merge_linestring_gen5 -- etldoc: osm_transportation_merge_linestring_gen_z7 -> osm_transportation_merge_linestring_gen_z6
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen5 AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen_z6 CASCADE;
SELECT ST_Simplify(geometry, 500) AS geometry, osm_id, highway, construction, z_order CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z6 AS
FROM osm_transportation_merge_linestring_gen4 (
WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) SELECT ST_Simplify(geometry, ZRes(8)) AS geometry,
AND ST_Length(geometry) > 100 osm_id,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; highway,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen5_geometry_idx construction,
ON osm_transportation_merge_linestring_gen5 USING gist(geometry); is_bridge,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen5_highway_partial_idx is_tunnel,
ON osm_transportation_merge_linestring_gen5(highway, construction) is_ford,
WHERE highway IN ('motorway','trunk', 'construction'); z_order
FROM osm_transportation_merge_linestring_gen_z7
WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk'))
AND ST_Length(geometry) > 100
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen_z6_geometry_idx
ON osm_transportation_merge_linestring_gen_z6 USING gist (geometry);
-- etldoc: osm_transportation_merge_linestring_gen5 -> osm_transportation_merge_linestring_gen6 -- etldoc: osm_transportation_merge_linestring_gen_z6 -> osm_transportation_merge_linestring_gen_z5
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen6 AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen_z5 CASCADE;
SELECT ST_Simplify(geometry, 1000) AS geometry, osm_id, highway, construction, z_order CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z5 AS
FROM osm_transportation_merge_linestring_gen5 (
WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 500 SELECT ST_Simplify(geometry, ZRes(7)) AS geometry,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; osm_id,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen6_geometry_idx highway,
ON osm_transportation_merge_linestring_gen6 USING gist(geometry); construction,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen6_highway_partial_idx is_bridge,
ON osm_transportation_merge_linestring_gen6(highway, construction) is_tunnel,
WHERE highway IN ('motorway','trunk', 'construction'); is_ford,
z_order
FROM osm_transportation_merge_linestring_gen_z6
WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk'))
AND ST_Length(geometry) > 500
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen_z5_geometry_idx
ON osm_transportation_merge_linestring_gen_z5 USING gist (geometry);
-- etldoc: osm_transportation_merge_linestring_gen6 -> osm_transportation_merge_linestring_gen7 -- etldoc: osm_transportation_merge_linestring_gen_z5 -> osm_transportation_merge_linestring_gen_z4
CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen7 AS ( DROP MATERIALIZED VIEW IF EXISTS osm_transportation_merge_linestring_gen_z4 CASCADE;
SELECT ST_Simplify(geometry, 2000) AS geometry, osm_id, highway, construction, z_order CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z4 AS
FROM osm_transportation_merge_linestring_gen6 (
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 1000 SELECT ST_Simplify(geometry, ZRes(6)) AS geometry,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; osm_id,
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen7_geometry_idx highway,
ON osm_transportation_merge_linestring_gen7 USING gist(geometry); construction,
is_bridge,
is_tunnel,
is_ford,
z_order
FROM osm_transportation_merge_linestring_gen_z5
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway')
AND ST_Length(geometry) > 1000
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen_z4_geometry_idx
ON osm_transportation_merge_linestring_gen_z4 USING gist (geometry);
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS transportation; CREATE SCHEMA IF NOT EXISTS transportation;
CREATE TABLE IF NOT EXISTS transportation.updates(id serial primary key, t text, unique (t)); CREATE TABLE IF NOT EXISTS transportation.updates
CREATE OR REPLACE FUNCTION transportation.flag() RETURNS trigger AS $$ (
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION transportation.flag() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO transportation.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; INSERT INTO transportation.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN null; RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION transportation.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION transportation.refresh() RETURNS trigger AS
$BODY$ $$
BEGIN DECLARE
RAISE NOTICE 'Refresh transportation'; t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh transportation';
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring;
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen3; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z8;
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen4; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z7;
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen5; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z6;
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen6; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z5;
REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen7; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen_z4;
-- noinspection SqlWithoutWhere
DELETE FROM transportation.updates; DELETE FROM transportation.updates;
RETURN null;
END; RAISE LOG 'Refresh transportation done in %', age(clock_timestamp(), t);
$BODY$ RETURN NULL;
language plpgsql; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_flag_transportation CREATE TRIGGER trigger_flag_transportation
AFTER INSERT OR UPDATE OR DELETE ON osm_highway_linestring AFTER INSERT OR UPDATE OR DELETE
ON osm_highway_linestring
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE transportation.flag(); EXECUTE PROCEDURE transportation.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON transportation.updates AFTER INSERT
ON transportation.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE transportation.refresh(); EXECUTE PROCEDURE transportation.refresh();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

@ -1,131 +0,0 @@
-- etldoc: layer_transportation_name[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_transportation_name | <z6> z6 | <z7> z7 | <z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_transportation_name(bbox geometry, zoom_level integer)
RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text,
name_de text, tags hstore, ref text, ref_length int, network text, class
text, subclass text, layer INT, level INT, indoor INT) AS $$
SELECT osm_id, geometry,
NULLIF(name, '') AS name,
COALESCE(NULLIF(name_en, ''), name) AS name_en,
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags,
NULLIF(ref, ''), NULLIF(LENGTH(ref), 0) AS ref_length,
--TODO: The road network of the road is not yet implemented
case
when network is not null
then network::text
when length(coalesce(ref, ''))>0
then 'road'
end as network,
highway_class(highway, '', construction) AS class,
CASE
WHEN highway IS NOT NULL AND highway_class(highway, '', construction) = 'path'
THEN highway
END AS subclass,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor=TRUE THEN 1 END as indoor
FROM (
-- etldoc: osm_transportation_name_linestring_gen4 -> layer_transportation_name:z6
SELECT *,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen4
WHERE zoom_level = 6
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen3 -> layer_transportation_name:z7
SELECT *,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen3
WHERE zoom_level = 7
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen2 -> layer_transportation_name:z8
SELECT *,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen2
WHERE zoom_level = 8
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z9
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z10
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z11
SELECT *,
NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen1
WHERE zoom_level BETWEEN 9 AND 11
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z12
SELECT
geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level = 12
AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry)
AND highway_class(highway, '', construction) NOT IN ('minor', 'track', 'path')
AND NOT highway_is_link(highway)
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z13
SELECT
geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level = 13
AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry)
AND highway_class(highway, '', construction) NOT IN ('track', 'path')
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z14_
SELECT
geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox
ORDER BY z_order ASC;
$$
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE;

View File

@ -1,30 +1,33 @@
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_network CASCADE; DROP TRIGGER IF EXISTS trigger_store_transportation_route_member ON osm_route_member;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring CASCADE; DROP TRIGGER IF EXISTS trigger_store_transportation_highway_linestring ON osm_highway_linestring;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen1 CASCADE; DROP TRIGGER IF EXISTS trigger_flag_transportation_name ON transportation_name.network_changes;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen2 CASCADE; DROP TRIGGER IF EXISTS trigger_refresh_network ON transportation_name.updates_network;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen3 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen4 CASCADE;
DO $$ DROP TRIGGER IF EXISTS trigger_store_transportation_name_network ON osm_transportation_name_network;
BEGIN DROP TRIGGER IF EXISTS trigger_flag_name ON transportation_name.name_changes;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'route_network_type') THEN DROP TRIGGER IF EXISTS trigger_refresh_name ON transportation_name.updates_name;
CREATE TYPE route_network_type AS ENUM (
'us-interstate', 'us-highway', 'us-state', DO
'ca-transcanada',
'gb-motorway', 'gb-trunk'
);
END IF;
END
$$ $$
; BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_type WHERE typname = 'route_network_type') THEN
CREATE TYPE route_network_type AS enum (
'us-interstate', 'us-highway', 'us-state',
'ca-transcanada',
'gb-motorway', 'gb-trunk'
);
END IF;
END
$$;
DO $$ DO
$$
BEGIN BEGIN
BEGIN BEGIN
ALTER TABLE osm_route_member ADD COLUMN network_type route_network_type; ALTER TABLE osm_route_member
ADD COLUMN network_type route_network_type;
EXCEPTION EXCEPTION
WHEN duplicate_column THEN RAISE NOTICE 'column network_type already exists in network_type.'; WHEN duplicate_column THEN RAISE NOTICE 'column network_type already exists in network_type.';
END; END;
END; END;
$$ $$;
;

View File

@ -0,0 +1,157 @@
-- etldoc: layer_transportation_name[shape=record fillcolor=lightpink, style="rounded,filled",
-- etldoc: label="layer_transportation_name | <z6> z6 | <z7> z7 | <z8> z8 |<z9> z9 |<z10> z10 |<z11> z11 |<z12> z12|<z13> z13|<z14_> z14+" ] ;
CREATE OR REPLACE FUNCTION layer_transportation_name(bbox geometry, zoom_level integer)
RETURNS TABLE
(
osm_id bigint,
geometry geometry,
name text,
name_en text,
name_de text,
tags hstore,
ref text,
ref_length int,
network text,
class text,
subclass text,
brunnel text,
layer int,
level int,
indoor int
)
AS
$$
SELECT osm_id,
geometry,
name,
COALESCE(name_en, name) AS name_en,
COALESCE(name_de, name, name_en) AS name_de,
tags,
ref,
NULLIF(LENGTH(ref), 0) AS ref_length,
--TODO: The road network of the road is not yet implemented
CASE
WHEN network IS NOT NULL
THEN network::text
WHEN length(coalesce(ref, '')) > 0
THEN 'road'
END AS network,
highway_class(highway, '', construction) AS class,
CASE
WHEN highway IS NOT NULL AND highway_class(highway, '', construction) = 'path'
THEN highway
END AS subclass,
brunnel,
NULLIF(layer, 0) AS layer,
"level",
CASE WHEN indoor = TRUE THEN 1 END AS indoor
FROM (
-- etldoc: osm_transportation_name_linestring_gen4 -> layer_transportation_name:z6
SELECT *,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen4
WHERE zoom_level = 6
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen3 -> layer_transportation_name:z7
SELECT *,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen3
WHERE zoom_level = 7
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen2 -> layer_transportation_name:z8
SELECT *,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen2
WHERE zoom_level = 8
UNION ALL
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z9
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z10
-- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z11
SELECT *,
NULL::int AS layer,
NULL::int AS level,
NULL::boolean AS indoor
FROM osm_transportation_name_linestring_gen1
WHERE zoom_level BETWEEN 9 AND 11
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z12
SELECT geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
brunnel,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level = 12
AND LineLabel(zoom_level, COALESCE(name, ref), geometry)
AND highway_class(highway, '', construction) NOT IN ('minor', 'track', 'path')
AND NOT highway_is_link(highway)
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z13
SELECT geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
brunnel,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level = 13
AND LineLabel(zoom_level, COALESCE(name, ref), geometry)
AND highway_class(highway, '', construction) NOT IN ('track', 'path')
UNION ALL
-- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z14_
SELECT geometry,
osm_id,
name,
name_en,
name_de,
"tags",
ref,
highway,
construction,
brunnel,
network,
z_order,
layer,
"level",
indoor
FROM osm_transportation_name_linestring
WHERE zoom_level >= 14
) AS zoom_levels
WHERE geometry && bbox
ORDER BY z_order ASC;
$$ LANGUAGE SQL STABLE
-- STRICT
PARALLEL SAFE;

View File

@ -69,6 +69,13 @@ layer:
- bridleway - bridleway
- corridor - corridor
- platform - platform
brunnel:
description: |
Mark whether way is a bridge, a tunnel or a ford.
values:
- bridge
- tunnel
- ford
level: level:
description: | description: |
Experimental feature! Filled only for steps and footways. Original Experimental feature! Filled only for steps and footways. Original
@ -86,12 +93,12 @@ layer:
datasource: datasource:
geometry_field: geometry geometry_field: geometry
srid: 900913 srid: 900913
query: (SELECT geometry, name, name_en, name_de, {name_languages}, ref, ref_length, network::text, class::text, subclass, layer, level, indoor FROM layer_transportation_name(!bbox!, z(!scale_denominator!))) AS t query: (SELECT geometry, name, name_en, name_de, {name_languages}, ref, ref_length, network::text, class::text, subclass, brunnel, layer, level, indoor FROM layer_transportation_name(!bbox!, z(!scale_denominator!))) AS t
schema: schema:
- ./network_type.sql - ./network_type.sql
- ./update_route_member.sql - ./update_route_member.sql
- ./update_transportation_name.sql - ./update_transportation_name.sql
- ./layer.sql - ./transportation_name.sql
datasources: datasources:
- type: imposm3 - type: imposm3
mapping_file: ../transportation/mapping.yaml mapping_file: ../transportation/mapping.yaml

View File

@ -1,68 +1,93 @@
DROP TRIGGER IF EXISTS trigger_flag_transportation_name ON osm_route_member; CREATE TABLE IF NOT EXISTS ne_10m_admin_0_bg_buffer AS
SELECT ST_Buffer(geometry, 10000)
FROM ne_10m_admin_0_countries
WHERE iso_a2 = 'GB';
CREATE OR REPLACE VIEW gbr_route_members_view AS
SELECT 0,
osm_id,
substring(ref FROM E'^[AM][0-9AM()]+'),
CASE WHEN highway = 'motorway' THEN 'omt-gb-motorway' ELSE 'omt-gb-trunk' END
FROM osm_highway_linestring
WHERE length(ref) > 0
AND ST_Intersects(geometry, (SELECT * FROM ne_10m_admin_0_bg_buffer))
AND highway IN ('motorway', 'trunk')
;
-- Create GBR relations (so we can use it in the same way as other relations)
DELETE
FROM osm_route_member
WHERE network IN ('omt-gb-motorway', 'omt-gb-trunk');
-- etldoc: osm_highway_linestring -> osm_route_member
INSERT INTO osm_route_member (osm_id, member, ref, network)
SELECT *
FROM gbr_route_members_view;
-- create GBR relations (so we can use it in the same way as other relations) CREATE OR REPLACE FUNCTION osm_route_member_network_type(network text, name text, ref text) RETURNS route_network_type AS
CREATE OR REPLACE FUNCTION update_gbr_route_members() RETURNS VOID AS $$ $$
DECLARE gbr_geom geometry; SELECT CASE
BEGIN WHEN network = 'US:I' THEN 'us-interstate'::route_network_type
SELECT st_buffer(geometry, 10000) INTO gbr_geom FROM ne_10m_admin_0_countries where iso_a2 = 'GB'; WHEN network = 'US:US' THEN 'us-highway'::route_network_type
DELETE FROM osm_route_member WHERE network IN ('omt-gb-motorway', 'omt-gb-trunk'); WHEN network LIKE 'US:__' THEN 'us-state'::route_network_type
-- https://en.wikipedia.org/wiki/Trans-Canada_Highway
INSERT INTO osm_route_member (osm_id, member, ref, network) -- TODO: improve hierarchical queries using
SELECT 0, osm_id, substring(ref FROM E'^[AM][0-9AM()]+'), -- http://www.openstreetmap.org/relation/1307243
CASE WHEN highway = 'motorway' THEN 'omt-gb-motorway' ELSE 'omt-gb-trunk' END -- however the relation does not cover the whole Trans-Canada_Highway
FROM osm_highway_linestring WHEN
WHERE (network = 'CA:transcanada') OR
length(ref)>0 AND (network = 'CA:BC:primary' AND ref IN ('16')) OR
ST_Intersects(geometry, gbr_geom) AND (name = 'Yellowhead Highway (AB)' AND ref IN ('16')) OR
highway IN ('motorway', 'trunk') (network = 'CA:SK:primary' AND ref IN ('16')) OR
; (network = 'CA:ON:primary' AND ref IN ('17', '417')) OR
END; (name = 'Route Transcanadienne') OR
$$ LANGUAGE plpgsql; (network = 'CA:NB:primary' AND ref IN ('2', '16')) OR
(network = 'CA:PE' AND ref IN ('1')) OR
(network = 'CA:NS' AND ref IN ('104', '105')) OR
(network = 'CA:NL:R' AND ref IN ('1')) OR
(name = 'Trans-Canada Highway')
THEN 'ca-transcanada'::route_network_type
WHEN network = 'omt-gb-motorway' THEN 'gb-motorway'::route_network_type
WHEN network = 'omt-gb-trunk' THEN 'gb-trunk'::route_network_type
END;
$$ LANGUAGE sql IMMUTABLE
PARALLEL SAFE;
-- etldoc: osm_route_member -> osm_route_member -- etldoc: osm_route_member -> osm_route_member
CREATE OR REPLACE FUNCTION update_osm_route_member() RETURNS VOID AS $$ -- see http://wiki.openstreetmap.org/wiki/Relation:route#Road_routes
UPDATE osm_route_member
SET network_type = osm_route_member_network_type(network, name, ref)
WHERE network != ''
AND network_type IS DISTINCT FROM osm_route_member_network_type(network, name, ref)
;
CREATE OR REPLACE FUNCTION update_osm_route_member() RETURNS void AS
$$
BEGIN BEGIN
PERFORM update_gbr_route_members(); DELETE
FROM osm_route_member AS r
USING
transportation_name.network_changes AS c
WHERE network IN ('omt-gb-motorway', 'omt-gb-trunk')
AND r.osm_id = c.osm_id;
-- see http://wiki.openstreetmap.org/wiki/Relation:route#Road_routes INSERT INTO osm_route_member (osm_id, member, ref, network)
UPDATE osm_route_member SELECT r.*
SET network_type = FROM gbr_route_members_view AS r
CASE JOIN transportation_name.network_changes AS c ON
WHEN network = 'US:I' THEN 'us-interstate'::route_network_type r.osm_id = c.osm_id;
WHEN network = 'US:US' THEN 'us-highway'::route_network_type
WHEN network LIKE 'US:__' THEN 'us-state'::route_network_type
-- https://en.wikipedia.org/wiki/Trans-Canada_Highway
-- TODO: improve hierarchical queries using
-- http://www.openstreetmap.org/relation/1307243
-- however the relation does not cover the whole Trans-Canada_Highway
WHEN
(network = 'CA:transcanada') OR
(network = 'CA:BC:primary' AND ref IN ('16')) OR
(name = 'Yellowhead Highway (AB)' AND ref IN ('16')) OR
(network = 'CA:SK:primary' AND ref IN ('16')) OR
(network = 'CA:ON:primary' AND ref IN ('17', '417')) OR
(name = 'Route Transcanadienne') OR
(network = 'CA:NB:primary' AND ref IN ('2', '16')) OR
(network = 'CA:PE' AND ref IN ('1')) OR
(network = 'CA:NS' AND ref IN ('104', '105')) OR
(network = 'CA:NL:R' AND ref IN ('1')) OR
(name = 'Trans-Canada Highway')
THEN 'ca-transcanada'::route_network_type
WHEN network = 'omt-gb-motorway' THEN 'gb-motorway'::route_network_type
WHEN network = 'omt-gb-trunk' THEN 'gb-trunk'::route_network_type
END
;
UPDATE
osm_route_member AS r
SET network_type = osm_route_member_network_type(network, name, ref)
FROM transportation_name.network_changes AS c
WHERE network != ''
AND network_type IS DISTINCT FROM osm_route_member_network_type(network, name, ref)
AND r.member = c.osm_id;
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
CREATE INDEX IF NOT EXISTS osm_route_member_network_idx ON osm_route_member("network"); CREATE INDEX IF NOT EXISTS osm_route_member_network_idx ON osm_route_member ("network");
CREATE INDEX IF NOT EXISTS osm_route_member_member_idx ON osm_route_member("member"); CREATE INDEX IF NOT EXISTS osm_route_member_member_idx ON osm_route_member ("member");
CREATE INDEX IF NOT EXISTS osm_route_member_name_idx ON osm_route_member("name"); CREATE INDEX IF NOT EXISTS osm_route_member_name_idx ON osm_route_member ("name");
CREATE INDEX IF NOT EXISTS osm_route_member_ref_idx ON osm_route_member("ref"); CREATE INDEX IF NOT EXISTS osm_route_member_ref_idx ON osm_route_member ("ref");
SELECT update_osm_route_member(); CREATE INDEX IF NOT EXISTS osm_route_member_network_type_idx ON osm_route_member ("network_type");
CREATE INDEX IF NOT EXISTS osm_route_member_network_type_idx ON osm_route_member("network_type");

View File

@ -1,6 +1,3 @@
DROP TRIGGER IF EXISTS trigger_flag_transportation_name ON osm_highway_linestring;
DROP TRIGGER IF EXISTS trigger_refresh ON transportation_name.updates;
-- Instead of using relations to find out the road names we -- Instead of using relations to find out the road names we
-- stitch together the touching ways with the same name -- stitch together the touching ways with the same name
-- to allow for nice label rendering -- to allow for nice label rendering
@ -9,165 +6,654 @@ DROP TRIGGER IF EXISTS trigger_refresh ON transportation_name.updates;
-- etldoc: osm_highway_linestring -> osm_transportation_name_network -- etldoc: osm_highway_linestring -> osm_transportation_name_network
-- etldoc: osm_route_member -> osm_transportation_name_network -- etldoc: osm_route_member -> osm_transportation_name_network
CREATE MATERIALIZED VIEW osm_transportation_name_network AS ( CREATE TABLE IF NOT EXISTS osm_transportation_name_network AS
SELECT SELECT
hl.geometry, geometry,
hl.osm_id, osm_id,
CASE WHEN length(hl.name)>15 THEN osml10n_street_abbrev_all(hl.name) ELSE hl.name END AS "name", name,
CASE WHEN length(hl.name_en)>15 THEN osml10n_street_abbrev_en(hl.name_en) ELSE hl.name_en END AS "name_en", name_en,
CASE WHEN length(hl.name_de)>15 THEN osml10n_street_abbrev_de(hl.name_de) ELSE hl.name_de END AS "name_de", name_de,
hl.tags, tags,
rm.network_type, ref,
CASE highway,
WHEN (rm.network_type is not null AND nullif(rm.ref::text, '') is not null) construction,
then rm.ref::text brunnel,
else hl.ref "level",
end as ref, layer,
hl.highway, indoor,
hl.construction, network_type,
CASE WHEN highway IN ('footway', 'steps') THEN layer END AS layer, z_order
CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level", FROM (
CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor, SELECT hl.geometry,
ROW_NUMBER() OVER(PARTITION BY hl.osm_id hl.osm_id,
ORDER BY rm.network_type) AS "rank", CASE WHEN length(hl.name) > 15 THEN osml10n_street_abbrev_all(hl.name) ELSE NULLIF(hl.name, '') END AS "name",
hl.z_order CASE WHEN length(hl.name_en) > 15 THEN osml10n_street_abbrev_en(hl.name_en) ELSE NULLIF(hl.name_en, '') END AS "name_en",
FROM osm_highway_linestring hl CASE WHEN length(hl.name_de) > 15 THEN osml10n_street_abbrev_de(hl.name_de) ELSE NULLIF(hl.name_de, '') END AS "name_de",
left join osm_route_member rm on (rm.member = hl.osm_id) slice_language_tags(hl.tags) AS tags,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; rm.network_type,
CREATE INDEX IF NOT EXISTS osm_transportation_name_network_geometry_idx ON osm_transportation_name_network USING gist(geometry); CASE
WHEN rm.network_type IS NOT NULL AND nullif(rm.ref::text, '') IS NOT NULL
THEN rm.ref::text
ELSE NULLIF(hl.ref, '')
END AS ref,
hl.highway,
hl.construction,
brunnel(hl.is_bridge, hl.is_tunnel, hl.is_ford) AS brunnel,
CASE WHEN highway IN ('footway', 'steps') THEN layer END AS layer,
CASE WHEN highway IN ('footway', 'steps') THEN level END AS level,
CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor,
ROW_NUMBER() OVER (PARTITION BY hl.osm_id
ORDER BY rm.network_type) AS "rank",
hl.z_order
FROM osm_highway_linestring hl
LEFT JOIN osm_route_member rm ON
rm.member = hl.osm_id
WHERE (hl.name <> '' OR hl.ref <> '')
AND NULLIF(hl.highway, '') IS NOT NULL
) AS t
WHERE ("rank" = 1 OR "rank" IS NULL);
CREATE INDEX IF NOT EXISTS osm_transportation_name_network_osm_id_idx ON osm_transportation_name_network (osm_id);
CREATE INDEX IF NOT EXISTS osm_transportation_name_network_name_ref_idx ON osm_transportation_name_network (coalesce(name, ''), coalesce(ref, ''));
CREATE INDEX IF NOT EXISTS osm_transportation_name_network_geometry_idx ON osm_transportation_name_network USING gist (geometry);
-- etldoc: osm_transportation_name_network -> osm_transportation_name_linestring -- etldoc: osm_transportation_name_network -> osm_transportation_name_linestring
CREATE MATERIALIZED VIEW osm_transportation_name_linestring AS ( CREATE TABLE IF NOT EXISTS osm_transportation_name_linestring AS
SELECT SELECT (ST_Dump(geometry)).geom AS geometry,
(ST_Dump(geometry)).geom AS geometry, NULL::bigint AS osm_id,
NULL::bigint AS osm_id, name,
name, name_en,
name_en, name_de,
name_de, tags || get_basic_names(tags, geometry) AS "tags",
tags || get_basic_names(tags, geometry) AS "tags", ref,
ref, highway,
highway, construction,
construction, brunnel,
"level", "level",
layer, layer,
indoor, indoor,
network_type AS network, network_type AS network,
z_order z_order
FROM ( FROM (
SELECT SELECT ST_LineMerge(ST_Collect(geometry)) AS geometry,
ST_LineMerge(ST_Collect(geometry)) AS geometry, name,
name, name_en,
name_en, name_de,
name_de, tags || hstore( -- store results of osml10n_street_abbrev_* above
hstore(string_agg(nullif(slice_language_tags(tags || hstore(ARRAY['name', name, 'name:en', name_en, 'name:de', name_de]))::text, ''), ',')) ARRAY ['name', name, 'name:en', name_en, 'name:de', name_de]) AS tags,
AS "tags", ref,
ref, highway,
highway, construction,
construction, brunnel,
"level", "level",
layer, layer,
indoor, indoor,
network_type, network_type,
min(z_order) AS z_order min(z_order) AS z_order
FROM osm_transportation_name_network FROM osm_transportation_name_network
WHERE ("rank"=1 OR "rank" is null) GROUP BY name, name_en, name_de, tags, ref, highway, construction, brunnel, "level", layer, indoor, network_type
AND (name <> '' OR ref <> '') ) AS highway_union
AND NULLIF(highway, '') IS NOT NULL ;
group by name, name_en, name_de, ref, highway, construction, "level", layer, indoor, network_type CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_name_ref_idx ON osm_transportation_name_linestring (coalesce(name, ''), coalesce(ref, ''));
) AS highway_union CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_geometry_idx ON osm_transportation_name_linestring USING gist (geometry);
) /* DELAY_MATERIALIZED_VIEW_CREATION */;
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_geometry_idx ON osm_transportation_name_linestring USING gist(geometry);
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_highway_partial_idx CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_highway_partial_idx
ON osm_transportation_name_linestring(highway, construction) ON osm_transportation_name_linestring (highway, construction)
WHERE highway IN ('motorway','trunk', 'construction'); WHERE highway IN ('motorway', 'trunk', 'construction');
-- etldoc: osm_transportation_name_linestring -> osm_transportation_name_linestring_gen1 -- etldoc: osm_transportation_name_linestring -> osm_transportation_name_linestring_gen1
CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen1 AS ( CREATE OR REPLACE VIEW osm_transportation_name_linestring_gen1_view AS
SELECT ST_Simplify(geometry, 50) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order SELECT ST_Simplify(geometry, 50) AS geometry,
FROM osm_transportation_name_linestring osm_id,
WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 8000 name,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; name_en,
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_geometry_idx ON osm_transportation_name_linestring_gen1 USING gist(geometry); name_de,
tags,
ref,
highway,
construction,
brunnel,
network,
z_order
FROM osm_transportation_name_linestring
WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk'))
AND ST_Length(geometry) > 8000
;
CREATE TABLE IF NOT EXISTS osm_transportation_name_linestring_gen1 AS
SELECT *
FROM osm_transportation_name_linestring_gen1_view;
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_name_ref_idx ON osm_transportation_name_linestring_gen1((coalesce(name, ref)));
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_geometry_idx ON osm_transportation_name_linestring_gen1 USING gist (geometry);
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_highway_partial_idx CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_highway_partial_idx
ON osm_transportation_name_linestring_gen1(highway, construction) ON osm_transportation_name_linestring_gen1 (highway, construction)
WHERE highway IN ('motorway','trunk', 'construction'); WHERE highway IN ('motorway', 'trunk', 'construction');
-- etldoc: osm_transportation_name_linestring_gen1 -> osm_transportation_name_linestring_gen2 -- etldoc: osm_transportation_name_linestring_gen1 -> osm_transportation_name_linestring_gen2
CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen2 AS ( CREATE OR REPLACE VIEW osm_transportation_name_linestring_gen2_view AS
SELECT ST_Simplify(geometry, 120) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order SELECT ST_Simplify(geometry, 120) AS geometry,
FROM osm_transportation_name_linestring_gen1 osm_id,
WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 14000 name,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; name_en,
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_geometry_idx ON osm_transportation_name_linestring_gen2 USING gist(geometry); name_de,
tags,
ref,
highway,
construction,
brunnel,
network,
z_order
FROM osm_transportation_name_linestring_gen1
WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk'))
AND ST_Length(geometry) > 14000
;
CREATE TABLE IF NOT EXISTS osm_transportation_name_linestring_gen2 AS
SELECT *
FROM osm_transportation_name_linestring_gen2_view;
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_name_ref_idx ON osm_transportation_name_linestring_gen2((coalesce(name, ref)));
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_geometry_idx ON osm_transportation_name_linestring_gen2 USING gist (geometry);
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_highway_partial_idx CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_highway_partial_idx
ON osm_transportation_name_linestring_gen2(highway, construction) ON osm_transportation_name_linestring_gen2 (highway, construction)
WHERE highway IN ('motorway','trunk', 'construction'); WHERE highway IN ('motorway', 'trunk', 'construction');
-- etldoc: osm_transportation_name_linestring_gen2 -> osm_transportation_name_linestring_gen3 -- etldoc: osm_transportation_name_linestring_gen2 -> osm_transportation_name_linestring_gen3
CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen3 AS ( CREATE OR REPLACE VIEW osm_transportation_name_linestring_gen3_view AS
SELECT ST_Simplify(geometry, 200) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order SELECT ST_Simplify(geometry, 200) AS geometry,
FROM osm_transportation_name_linestring_gen2 osm_id,
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 20000 name,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; name_en,
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_geometry_idx ON osm_transportation_name_linestring_gen3 USING gist(geometry); name_de,
tags,
ref,
highway,
construction,
brunnel,
network,
z_order
FROM osm_transportation_name_linestring_gen2
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway')
AND ST_Length(geometry) > 20000
;
CREATE TABLE IF NOT EXISTS osm_transportation_name_linestring_gen3 AS
SELECT *
FROM osm_transportation_name_linestring_gen3_view;
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_name_ref_idx ON osm_transportation_name_linestring_gen3((coalesce(name, ref)));
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_geometry_idx ON osm_transportation_name_linestring_gen3 USING gist (geometry);
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_highway_partial_idx CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_highway_partial_idx
ON osm_transportation_name_linestring_gen3(highway, construction) ON osm_transportation_name_linestring_gen3 (highway, construction)
WHERE highway IN ('motorway', 'construction'); WHERE highway IN ('motorway', 'construction');
-- etldoc: osm_transportation_name_linestring_gen3 -> osm_transportation_name_linestring_gen4 -- etldoc: osm_transportation_name_linestring_gen3 -> osm_transportation_name_linestring_gen4
CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen4 AS ( CREATE OR REPLACE VIEW osm_transportation_name_linestring_gen4_view AS
SELECT ST_Simplify(geometry, 500) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order SELECT ST_Simplify(geometry, 500) AS geometry,
FROM osm_transportation_name_linestring_gen3 osm_id,
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 20000 name,
) /* DELAY_MATERIALIZED_VIEW_CREATION */; name_en,
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen4_geometry_idx ON osm_transportation_name_linestring_gen4 USING gist(geometry); name_de,
tags,
ref,
highway,
construction,
brunnel,
network,
z_order
FROM osm_transportation_name_linestring_gen3
WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway')
AND ST_Length(geometry) > 20000
;
CREATE TABLE IF NOT EXISTS osm_transportation_name_linestring_gen4 AS
SELECT *
FROM osm_transportation_name_linestring_gen4_view;
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen4_name_ref_idx ON osm_transportation_name_linestring_gen4((coalesce(name, ref)));
CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen4_geometry_idx ON osm_transportation_name_linestring_gen4 USING gist (geometry);
-- Handle updates -- Handle updates
CREATE SCHEMA IF NOT EXISTS transportation_name; CREATE SCHEMA IF NOT EXISTS transportation_name;
CREATE TABLE IF NOT EXISTS transportation_name.updates(id serial primary key, t text, unique (t)); -- Trigger to update "osm_transportation_name_network" from "osm_route_member" and "osm_highway_linestring"
CREATE OR REPLACE FUNCTION transportation_name.flag() RETURNS trigger AS $$
CREATE TABLE IF NOT EXISTS transportation_name.network_changes
(
osm_id bigint,
UNIQUE (osm_id)
);
CREATE OR REPLACE FUNCTION transportation_name.route_member_store() RETURNS trigger AS
$$
BEGIN BEGIN
INSERT INTO transportation_name.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; INSERT INTO transportation_name.network_changes(osm_id)
RETURN null; VALUES (CASE WHEN tg_op IN ('DELETE', 'UPDATE') THEN old.member ELSE new.member END)
ON CONFLICT(osm_id) DO NOTHING;
RETURN NULL;
END; END;
$$ language plpgsql; $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION transportation_name.refresh() RETURNS trigger AS CREATE OR REPLACE FUNCTION transportation_name.highway_linestring_store() RETURNS trigger AS
$BODY$ $$
BEGIN BEGIN
RAISE LOG 'Refresh transportation_name'; INSERT INTO transportation_name.network_changes(osm_id)
VALUES (CASE WHEN tg_op IN ('DELETE', 'UPDATE') THEN old.osm_id ELSE new.osm_id END)
ON CONFLICT(osm_id) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS transportation_name.updates_network
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION transportation_name.flag_network() RETURNS trigger AS
$$
BEGIN
INSERT INTO transportation_name.updates_network(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION transportation_name.refresh_network() RETURNS trigger AS
$$
DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh transportation_name_network';
PERFORM update_osm_route_member(); PERFORM update_osm_route_member();
REFRESH MATERIALIZED VIEW osm_transportation_name_network;
REFRESH MATERIALIZED VIEW osm_transportation_name_linestring; -- REFRESH osm_transportation_name_network
REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen1; DELETE
REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen2; FROM osm_transportation_name_network AS n
REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen3; USING
REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen4; transportation_name.network_changes AS c
DELETE FROM transportation_name.updates; WHERE n.osm_id = c.osm_id;
RETURN null;
END; INSERT INTO osm_transportation_name_network
$BODY$ SELECT
language plpgsql; geometry,
osm_id,
name,
name_en,
name_de,
tags,
ref,
highway,
construction,
brunnel,
level,
layer,
indoor,
network_type,
z_order
FROM (
SELECT hl.geometry,
hl.osm_id,
CASE WHEN length(hl.name) > 15 THEN osml10n_street_abbrev_all(hl.name) ELSE NULLIF(hl.name, '') END AS name,
CASE WHEN length(hl.name_en) > 15 THEN osml10n_street_abbrev_en(hl.name_en) ELSE NULLIF(hl.name_en, '') END AS name_en,
CASE WHEN length(hl.name_de) > 15 THEN osml10n_street_abbrev_de(hl.name_de) ELSE NULLIF(hl.name_de, '') END AS name_de,
slice_language_tags(hl.tags) AS tags,
rm.network_type,
CASE
WHEN rm.network_type IS NOT NULL AND NULLIF(rm.ref::text, '') IS NOT NULL
THEN rm.ref::text
ELSE NULLIF(hl.ref, '')
END AS ref,
hl.highway,
hl.construction,
brunnel(hl.is_bridge, hl.is_tunnel, hl.is_ford) AS brunnel,
CASE WHEN highway IN ('footway', 'steps') THEN layer END AS layer,
CASE WHEN highway IN ('footway', 'steps') THEN level END AS level,
CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor,
ROW_NUMBER() OVER (PARTITION BY hl.osm_id
ORDER BY rm.network_type) AS "rank",
hl.z_order
FROM osm_highway_linestring hl
JOIN transportation_name.network_changes AS c ON
hl.osm_id = c.osm_id
LEFT JOIN osm_route_member rm ON
rm.member = hl.osm_id
WHERE (hl.name <> '' OR hl.ref <> '')
AND NULLIF(hl.highway, '') IS NOT NULL
) AS t
WHERE ("rank" = 1 OR "rank" IS NULL);
-- noinspection SqlWithoutWhere
DELETE FROM transportation_name.network_changes;
-- noinspection SqlWithoutWhere
DELETE FROM transportation_name.updates_network;
RAISE LOG 'Refresh transportation_name network done in %', age(clock_timestamp(), t);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_store_transportation_route_member
AFTER INSERT OR UPDATE OR DELETE
ON osm_route_member
FOR EACH ROW
EXECUTE PROCEDURE transportation_name.route_member_store();
CREATE TRIGGER trigger_store_transportation_highway_linestring
AFTER INSERT OR UPDATE OR DELETE
ON osm_highway_linestring
FOR EACH ROW
EXECUTE PROCEDURE transportation_name.highway_linestring_store();
CREATE TRIGGER trigger_flag_transportation_name CREATE TRIGGER trigger_flag_transportation_name
AFTER INSERT OR UPDATE OR DELETE ON osm_route_member AFTER INSERT
ON transportation_name.network_changes
FOR EACH STATEMENT FOR EACH STATEMENT
EXECUTE PROCEDURE transportation_name.flag(); EXECUTE PROCEDURE transportation_name.flag_network();
CREATE TRIGGER trigger_flag_transportation_name CREATE CONSTRAINT TRIGGER trigger_refresh_network
AFTER INSERT OR UPDATE OR DELETE ON osm_highway_linestring AFTER INSERT
FOR EACH STATEMENT ON transportation_name.updates_network
EXECUTE PROCEDURE transportation_name.flag();
CREATE CONSTRAINT TRIGGER trigger_refresh
AFTER INSERT ON transportation_name.updates
INITIALLY DEFERRED INITIALLY DEFERRED
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE transportation_name.refresh(); EXECUTE PROCEDURE transportation_name.refresh_network();
-- Trigger to update "osm_transportation_name_linestring" from "osm_transportation_name_network"
CREATE TABLE IF NOT EXISTS transportation_name.name_changes
(
id serial PRIMARY KEY,
is_old boolean,
osm_id bigint,
name character varying,
name_en character varying,
name_de character varying,
ref character varying,
highway character varying,
construction character varying,
brunnel character varying,
level integer,
layer integer,
indoor boolean,
network_type route_network_type
);
CREATE OR REPLACE FUNCTION transportation_name.name_network_store() RETURNS trigger AS
$$
BEGIN
IF (tg_op IN ('DELETE', 'UPDATE'))
THEN
INSERT INTO transportation_name.name_changes(is_old, osm_id, name, name_en, name_de, ref, highway, construction,
brunnel, level, layer, indoor, network_type)
VALUES (TRUE, old.osm_id, old.name, old.name_en, old.name_de, old.ref, old.highway, old.construction,
old.brunnel, old.level, old.layer, old.indoor, old.network_type);
END IF;
IF (tg_op IN ('UPDATE', 'INSERT'))
THEN
INSERT INTO transportation_name.name_changes(is_old, osm_id, name, name_en, name_de, ref, highway, construction,
brunnel, level, layer, indoor, network_type)
VALUES (FALSE, new.osm_id, new.name, new.name_en, new.name_de, new.ref, new.highway, new.construction,
new.brunnel, new.level, new.layer, new.indoor, new.network_type);
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE IF NOT EXISTS transportation_name.updates_name
(
id serial PRIMARY KEY,
t text,
UNIQUE (t)
);
CREATE OR REPLACE FUNCTION transportation_name.flag_name() RETURNS trigger AS
$$
BEGIN
INSERT INTO transportation_name.updates_name(t) VALUES ('y') ON CONFLICT(t) DO NOTHING;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION transportation_name.refresh_name() RETURNS trigger AS
$BODY$
DECLARE
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
BEGIN
RAISE LOG 'Refresh transportation_name';
-- REFRESH osm_transportation_name_linestring
-- Compact the change history to keep only the first and last version, and then uniq version of row
CREATE TEMP TABLE name_changes_compact AS
SELECT DISTINCT ON (name, name_en, name_de, ref, highway, construction, brunnel, level, layer, indoor, network_type)
name,
name_en,
name_de,
ref,
highway,
construction,
brunnel,
level,
layer,
indoor,
network_type,
coalesce(name, ref) AS name_ref
FROM ((
SELECT DISTINCT ON (osm_id) *
FROM transportation_name.name_changes
WHERE is_old
ORDER BY osm_id,
id ASC
)
UNION ALL
(
SELECT DISTINCT ON (osm_id) *
FROM transportation_name.name_changes
WHERE NOT is_old
ORDER BY osm_id,
id DESC
)) AS t;
DELETE
FROM osm_transportation_name_linestring AS n
USING name_changes_compact AS c
WHERE coalesce(n.name, '') = coalesce(c.name, '')
AND coalesce(n.ref, '') = coalesce(c.ref, '')
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.level IS NOT DISTINCT FROM c.level
AND n.layer IS NOT DISTINCT FROM c.layer
AND n.indoor IS NOT DISTINCT FROM c.indoor
AND n.network IS NOT DISTINCT FROM c.network_type;
INSERT INTO osm_transportation_name_linestring
SELECT (ST_Dump(geometry)).geom AS geometry,
NULL::bigint AS osm_id,
name,
name_en,
name_de,
tags || get_basic_names(tags, geometry) AS tags,
ref,
highway,
construction,
brunnel,
level,
layer,
indoor,
network_type AS network,
z_order
FROM (
SELECT ST_LineMerge(ST_Collect(n.geometry)) AS geometry,
n.name,
n.name_en,
n.name_de,
hstore(string_agg(nullif(slice_language_tags(tags ||
hstore(ARRAY ['name', n.name, 'name:en', n.name_en, 'name:de', n.name_de]))::text,
''), ',')) AS tags,
n.ref,
n.highway,
n.construction,
n.brunnel,
n.level,
n.layer,
n.indoor,
n.network_type,
min(n.z_order) AS z_order
FROM osm_transportation_name_network AS n
JOIN name_changes_compact AS c ON
coalesce(n.name, '') = coalesce(c.name, '')
AND coalesce(n.ref, '') = coalesce(c.ref, '')
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.level IS NOT DISTINCT FROM c.level
AND n.layer IS NOT DISTINCT FROM c.layer
AND n.indoor IS NOT DISTINCT FROM c.indoor
AND n.network_type IS NOT DISTINCT FROM c.network_type
GROUP BY n.name, n.name_en, n.name_de, n.ref, n.highway, n.construction, n.brunnel, n.level, n.layer, n.indoor, n.network_type
) AS highway_union;
-- REFRESH osm_transportation_name_linestring_gen1
DELETE FROM osm_transportation_name_linestring_gen1 AS n
USING name_changes_compact AS c
WHERE
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
INSERT INTO osm_transportation_name_linestring_gen1
SELECT n.*
FROM osm_transportation_name_linestring_gen1_view AS n
JOIN name_changes_compact AS c ON
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
-- REFRESH osm_transportation_name_linestring_gen2
DELETE FROM osm_transportation_name_linestring_gen2 AS n
USING name_changes_compact AS c
WHERE
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
INSERT INTO osm_transportation_name_linestring_gen2
SELECT n.*
FROM osm_transportation_name_linestring_gen2_view AS n
JOIN name_changes_compact AS c ON
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
-- REFRESH osm_transportation_name_linestring_gen3
DELETE FROM osm_transportation_name_linestring_gen3 AS n
USING name_changes_compact AS c
WHERE
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
INSERT INTO osm_transportation_name_linestring_gen3
SELECT n.*
FROM osm_transportation_name_linestring_gen3_view AS n
JOIN name_changes_compact AS c ON
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
-- REFRESH osm_transportation_name_linestring_gen4
DELETE FROM osm_transportation_name_linestring_gen4 AS n
USING name_changes_compact AS c
WHERE
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
INSERT INTO osm_transportation_name_linestring_gen4
SELECT n.*
FROM osm_transportation_name_linestring_gen4_view AS n
JOIN name_changes_compact AS c ON
coalesce(n.name, n.ref) = c.name_ref
AND n.name IS NOT DISTINCT FROM c.name
AND n.name_en IS NOT DISTINCT FROM c.name_en
AND n.name_de IS NOT DISTINCT FROM c.name_de
AND n.ref IS NOT DISTINCT FROM c.ref
AND n.highway IS NOT DISTINCT FROM c.highway
AND n.construction IS NOT DISTINCT FROM c.construction
AND n.brunnel IS NOT DISTINCT FROM c.brunnel
AND n.network IS NOT DISTINCT FROM c.network_type;
DROP TABLE name_changes_compact;
DELETE FROM transportation_name.name_changes;
DELETE FROM transportation_name.updates_name;
RAISE LOG 'Refresh transportation_name done in %', age(clock_timestamp(), t);
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER trigger_store_transportation_name_network
AFTER INSERT OR UPDATE OR DELETE
ON osm_transportation_name_network
FOR EACH ROW
EXECUTE PROCEDURE transportation_name.name_network_store();
CREATE TRIGGER trigger_flag_name
AFTER INSERT
ON transportation_name.name_changes
FOR EACH STATEMENT
EXECUTE PROCEDURE transportation_name.flag_name();
CREATE CONSTRAINT TRIGGER trigger_refresh_name
AFTER INSERT
ON transportation_name.updates_name
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE transportation_name.refresh_name();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 406 KiB

View File

@ -1,39 +1,38 @@
generalized_tables: generalized_tables:
# etldoc: osm_water_polygon_gen_z7 -> osm_water_polygon_gen_z6
# etldoc: imposm3 -> osm_water_polygon_gen6 water_polygon_gen_z6:
water_polygon_gen6: source: water_polygon_gen_z7
source: water_polygon_gen5
sql_filter: area>power(ZRES5,2) sql_filter: area>power(ZRES5,2)
tolerance: ZRES7 tolerance: ZRES7
# etldoc: imposm3 -> osm_water_polygon_gen5 # etldoc: osm_water_polygon_gen_z8 -> osm_water_polygon_gen_z7
water_polygon_gen5: water_polygon_gen_z7:
source: water_polygon_gen4 source: water_polygon_gen_z8
sql_filter: area>power(ZRES6,2) sql_filter: area>power(ZRES6,2)
tolerance: ZRES8 tolerance: ZRES8
# etldoc: imposm3 -> osm_water_polygon_gen4 # etldoc: osm_water_polygon_gen_z9 -> osm_water_polygon_gen_z8
water_polygon_gen4: water_polygon_gen_z8:
source: water_polygon_gen3 source: water_polygon_gen_z9
sql_filter: area>power(ZRES7,2) sql_filter: area>power(ZRES7,2)
tolerance: ZRES9 tolerance: ZRES9
# etldoc: imposm3 -> osm_water_polygon_gen3 # etldoc: osm_water_polygon_gen_z10 -> osm_water_polygon_gen_z9
water_polygon_gen3: water_polygon_gen_z9:
source: water_polygon_gen2 source: water_polygon_gen_z10
sql_filter: area>power(ZRES8,2) sql_filter: area>power(ZRES8,2)
tolerance: ZRES10 tolerance: ZRES10
# etldoc: imposm3 -> osm_water_polygon_gen2 # etldoc: osm_water_polygon_gen_z11 -> osm_water_polygon_gen_z10
water_polygon_gen2: water_polygon_gen_z10:
source: water_polygon_gen1 source: water_polygon_gen_z11
sql_filter: area>power(ZRES9,2) sql_filter: area>power(ZRES9,2)
tolerance: ZRES11 tolerance: ZRES11
# etldoc: imposm3 -> osm_water_polygon_gen1 # etldoc: osm_water_polygon -> osm_water_polygon_gen_z11
water_polygon_gen1: water_polygon_gen_z11:
source: water_polygon source: water_polygon
sql_filter: area>power(ZRES10,2) AND ST_IsValid(geometry) sql_filter: area>power(ZRES10,2)
tolerance: ZRES12 tolerance: ZRES12
tunnel_field: &tunnel tunnel_field: &tunnel
@ -88,6 +87,7 @@ tables:
landuse: landuse:
- reservoir - reservoir
- basin - basin
- salt_pond
leisure: leisure:
- swimming_pool - swimming_pool
natural: natural:

Some files were not shown because too many files have changed in this diff Show More