├── .env ├── .gitignore ├── LICENSE ├── README.md ├── css ├── style_amenity.css ├── style_boundary.css ├── style_buildings.css ├── style_country.css ├── style_county.css ├── style_district.css ├── style_forestpark.css ├── style_lakes.css ├── style_minor_roads.css ├── style_motorway.css ├── style_pedestrian.css ├── style_rails.css ├── style_roads.css ├── style_settlements.css ├── style_subdistrict.css ├── style_trunk_primary.css ├── style_water.css └── style_waterway.css ├── docker-compose.yml ├── docker └── db │ ├── .env │ ├── Dockerfile │ └── initdb-postgis.sh ├── img ├── cached2.png ├── gridset.png ├── layergroup.png └── preview2.png └── sql ├── create_separate_tables.sql └── drop_unnecessary_tables.sql /.env: -------------------------------------------------------------------------------- 1 | POSTGIS_VERSION=latest 2 | 3 | TIMEZONE=Europe/Budapest 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Gergely Padányi-Gulyás 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # osmgwc 2 | 3 | > A step-by-step tutorial to create a geowebcache layer from OSM data which will look a lot like Google Maps 4 | 5 | [![Join the chat at https://gitter.im/osmgwc/Lobby](https://badges.gitter.im/osmgwc/Lobby.svg)](https://gitter.im/osmgwc/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | ## What is osmgwc? 8 | 9 | Osmgwc is a step-by-step tutorial of how to create a fast cached WMS layer which will hopefully look similar to Google Maps' design. The main difference is that it will be based on the free and open source OpenStreetMap (OSM) data, stored in a PostGIS database and served with GeoServer. Another difference is that it will be stored in the spatial reference system (SRS) of your choice. 10 | 11 | If you follow the steps below, you will download OSM data, create an empty database, populate it with geodata in the desired SRS, then split the data into different tables (settlements, rivers etc.), add them as layers in GeoServer, style them with CSS styles, create a combined layer group, define a grid for your SRS, then finally publish a cached layer. 12 | 13 | In this tutorial the data for Hungary will be used. The size of this country's OSM data requires reasonable time to process. 14 | 15 | ## Live demo 16 | 17 | You can check the outcome of this tutorial by clicking [here](http://188.166.116.137:8080/geoserver/gwc/demo/osmWsp:osm_hungary?gridSet=EPSG:900913&format=image/png). 18 | 19 | ## Prerequisites 20 | 21 | * PostgreSQL with PostGIS: 22 | 23 | For this tutorial I used [PostgreSQL v.9.6.1 with PostGIS v.2.3.0](http://www.enterprisedb.com/products-services-training/pgdownload) 24 | 25 | * GeoServer with the CSS plugin: 26 | 27 | For this tutorial I used [GeoServer v.2.10.0](http://geoserver.org/release/2.10.0/). Download the CSS plugin from [here](https://sourceforge.net/projects/geoserver/files/GeoServer/2.10.0/extensions/geoserver-2.10.0-css-plugin.zip/download), then unzip it into GeoServer's lib folder which can be found here: [GeoServer install dir]/webapps/geoserver/WEB-INF/lib, then restart GeoServer. 28 | 29 | * osm2pgsql 30 | 31 | osm2pgsql is an open source tool to populate a PostGIS database with osm data. For Windows download from [here](https://ci.appveyor.com/project/openstreetmap/osm2pgsql/build/artifacts), for Linux run this command: `apt-get install -y osm2pgsql` 32 | 33 | * bzip2 34 | 35 | bzip2 is an unzipper tool that can be used to extract data from .bz2 files. For Windows download from [here](http://www.bzip.org/downloads.html), for Linux run this command: `apt-get install -y bzip2` 36 | 37 | * proj 38 | 39 | To be able to store OSM data in an SRS of your choice the proj library is needed. If you use Windows, the usage of [OSGeo4W](http://trac.osgeo.org/osgeo4w/) is recommended. With advanced install you should select the proj package from the commandline utilities as well as from the libs. If you use Linux run this command: `apt-get install -y libproj-dev` 40 | 41 | ## Download OSM data 42 | 43 | The data is freely available on GEOFABRIK's [download site](http://download.geofabrik.de/). For Hungary download the latest dataset in bz2 format from [here](http://download.geofabrik.de/europe/hungary-latest.osm.bz2) (~200 MB). After download, extract it to a folder of your choice. Its extension is .osm and its size is about 2.5 GB. 44 | 45 | ## Create a new PostGIS database 46 | 47 | Create a new database (in this tutorial this will be called 'osm'), then run this for the newly created database: 48 | 49 | ```sql 50 | create extension postgis; 51 | ``` 52 | 53 | ## Populate the database with OSM data 54 | 55 | Navigate to the folder of the extracted .osm file, and run osm2pgsql (here with Windows syntax): 56 | 57 | ```bat 58 | C:\Programok\osm2pgsql\osm2pgsql -s -H localhost -P 5432 -U postgres -W -d osm hungary-latest.osm --cache-strategy sparse --cache 100 -E 23700 -S C:\Programs\osm2pgsql\default.style 59 | ``` 60 | 61 | Parameters are: 62 | 63 | * H: host (in this case: localhost) 64 | * P: port (the default port is 5432 for PostgreSQL) 65 | * U: PostgreSQL user (default user is postgres) 66 | * d: database name (in this case: osm) 67 | * E: coordinate reference system (in this case: 23700) 68 | * S: sometimes osm2pgsql requires a default.style file, you can find it in osm2pgsql's install dir 69 | * cache-strategy and cache: if your machine is not very strong use these parameters, otherwise you can omit them 70 | 71 | This will take a while based on the size of your data and your machine's capabilities. For me it took around 10 minutes to process. 72 | 73 | If the command ran successfully, you will see the following new tables in the 'public' schema: planet_osm_line, planet_osm_nodes, planet_osm_point, planet_osm_polygon, planet_osm_rels, planet_osm_roads, planet_osm_ways. Make sure you have all of them! 74 | 75 | ## Create some PostGIS tables 76 | 77 | Now you have a lot of uncategorized data in your database now. It would be great to have a separate table for every category you wish to visualize on your map e.g. settlements, rivers, roads etc. Fortunately you only have to execute one single SQL script from the "sql" folder of this project (`create_separate_tables.sql`). After running it (via [pgAdmin](https://www.pgadmin.org/download/) for instance), you will have a new schema called "osm" populated with 18 new tables, including the necessary (spatial) indexes. 78 | 79 | If you wish to use a different SRS (other than EPSG:23700) make sure you manually change all occurences of "23700" to the desired EPSG code in the provided SQL file before execute it! 80 | 81 | After execution, if you would like to free up some space from the database you can delete the unnecessary tables from the public schema by executing the `drop_unnecessary_tables.sql` file. 82 | 83 | ## Create some GeoServer CSS styles 84 | 85 | In this step you will create styles by importing CSS files from this project's css folder. With these CSS files your map will look a lot like Google Maps. 86 | 87 | First log into GeoServer's admin page, navigate to "Styles", then hit "Add a new style". There, from the "Format" dropdown select "CSS" and click on the "Choose File" button below. Navigate to this project's "css" folder, click on the first CSS file (`style_amenity.css`) and after opening it hit "Upload" on the admin page. In the style editor you will see this: 88 | 89 | ```css 90 | [@scale < 100001] { 91 | fill: #f9edd5; 92 | } 93 | ``` 94 | 95 | Add a name to the style like "style_amenity" and hit "Submit". Repeat it with all the remaining CSS files. At the end, you will have 18 GeoServer styles. 96 | 97 | ## Create some GeoServer layers 98 | 99 | In this step you will connect GeoServer to the PostGIS database's "osm" schema with a Store. From this store you will add all the layers from the database schema with a default style from one of the styles you just added recently. 100 | 101 | From the admin page, hit "Stores" and then "Add new store". Select "PostGIS" and fill the form with the necessary parameters (Data Source Name, dbtype, host, port, database, schema, user, password), then hit save. Set the schema to "osm" since this is the schema that was created by the SQL script which stores the data of the categorized geometries. 102 | 103 | If you succeeded (managed to connect to the database) you will see the list of available tables that you can add as layers. Select the first one ("amenity") by hitting "Publish". You are then navigated to the "Edit layer" page where you have to fill the "Bounding Boxes" part by hitting on "Compute from data" and "Compute from native bounds". You will see that the Coordinate Reference System is recognized as EPSG:23700. 104 | 105 | On the second tab ("Publishing") set the default style according to the layer name (in this case: "style_amenity") and at the end of the page hit "Save". You just have successfully created a layer which looks like a Google Maps layer! 106 | 107 | You have to add all the other layers as well like this: on the admin page, hit "Layers", then "Add new layer", choose the recently created store, and select the next layer by hitting "Publish". From this you can continue just like the previous example. 108 | 109 | At the end you will have 18 new layers, all set with a previously created GeoServer style. 110 | 111 | ## Create a Layer Group 112 | 113 | Most likely you wish to publish your cached WMS service as one single layer instead of a bunch of individual layers. With GeoServer you can create a layer group that combines individual layers with an appearance order. You can define which layers should be on top and which ones on bottom. 114 | 115 | Click on "Layer Groups" on the admin page, then "Add new layer group". Name your layer group e.g. "osm_hungary". Next, add your layers individually by clicking on the "Add Layer..." button. The order of the layers is very important. This is how your layer order should look like: 116 | 117 | ![layergroup](img/layergroup.png) 118 | 119 | After you added all the 18 layers, click on "Generate Bounds", then on "Save". 120 | 121 | ## Preview the layer group 122 | 123 | Before creating a cached WMS service it would be nice to look what you've accomplished so far. Click on "Layer Preview" on the admin page, scroll down to the "osm_hungary" layer group and click on "OpenLayers". You will be navigated to a new page with a live WMS service of your layer group. You can zoom & pan the interactive map, and you should see that it is reasonably fast (at least compared to how many layers and styles the GeoServer has to synchronize not to mention the amount of data). You should see that it indeed looks a lot like Google Maps itself: 124 | 125 | ![preview](img/preview2.png) 126 | 127 | ## Why cached? 128 | 129 | If you tried to preview the layer group as suggested above you requested the GeoServer to do a lot of calculation each time you zoomed or panned the map. For one user this was relatively fast, but imagine a lot of users requesting the same layer group at the same time. After a while, GeoServer will not be able to serve the clients with an acceptable speed. However, if the server stores a generated tile for a given zoom level in an image file (jpg, png etc.), it does not have to render it again, but instead simply send that image back to the client. It saves a LOT of computation. Every major WMS tile servers (OpenStreetMap, Google, Bing etc.) use some caching method. 130 | 131 | ## Create a Gridset for your SRS 132 | 133 | A Gridset is a collection of different zoom levels for a given spatial reference system with a tile size (256x256 pixels usually). However, if you create a cached WMS service with an SRS other than EPSG:4326 or EPSG:900913, you have to define your own gridset. Since the OSM data is now in EPSG:23700 you will define a gridset for EPSG:23700. 134 | 135 | To do that, click on "Gridsets" on the admin page, then on "Create a new gridset". Give it a name (e.g. EPSG:23700), at the "Coordinate Reference System" section click on "Find...", find the one with the code "23700" (description: HD72/EOV), click on the code. Then click on "Compute from maximum extent of CRS". Next you will add the above mentioned zoom levels. Click on "Scale denominators" at the "Tile Matrix Set" section, and click on "Add zoom level" 15 times. Enter a scale and a name for each level. At the end, your gridset should look like this: 136 | 137 | ![gridset](img/gridset.png) 138 | 139 | After that, click on "Save". Your newly created gridset should be visible among the other gridsets. 140 | 141 | ## Create a cached WMS service 142 | 143 | Navigate to your layer group by click on "Layer Groups" and select "osm_hungary". Click the tab called "Tile Caching", and check the checkbox for "Create a cached layer for this layer group". After that, a lot of options are visible, but only these are important: 144 | 145 | * check the checkbox for "Enable tile caching for this layer" 146 | * "Metatiling factors" should be 4 tiles wide, 4 tiles high 147 | * "Tile Image Formats": only select "image/png" 148 | * at the "Gridset" section remove "EPSG:900913" and "EPSG:4326" by clicking on the red circle at the end of their line 149 | * add your gridset with the "Add grid subset" dropdown (after selecting "EPSG:23700", don't forget to click on the green plus icon next to it) 150 | 151 | If all parameters are set correctly, hit "Save". 152 | 153 | To see how your cached service looks like, go to "Tile Layers". You must see your layer group in the list. There is a dropdown for the "Preview" column, select "EPSG:23700 / png". You will jump to a new preview site of the layer group. You can zoom & pan just like before. But there is one big difference: if you zoom & pan, you will experience that it is a bit slower than before. It is because this is the exact moment when GeoServer stores the rendered images in its folder hierarchy and it takes some extra time. But if you refresh the page, however, the map should be visible instantly. If you zoom & pan to an area you have been before, the map will refresh also in no time. This is because of the tile caching. 154 | 155 | ![cached](img/cached2.png) 156 | 157 | Or you can always check the live demo [here](http://188.166.116.137:8080/geoserver/gwc/demo/osmWsp:osm_hungary?gridSet=EPSG:23700&format=image/png). 158 | 159 | ## Final words 160 | 161 | If you successfully completed this tutorial you hopefully learned a lot about GeoServer and its CSS styling. Using CSS is much more easier and fun than the old SLD styling. If you don't like my design you can easily add your own styles and create a better map, it is completely up to you. I just hope that I made the whole process a bit easier so that you can focus on the styling from a solid base. 162 | 163 | ## Author 164 | 165 | Osmgwc was created by [Gergely Padányi-Gulyás](mailto:fegyi001@gmail.com) 166 | -------------------------------------------------------------------------------- /css/style_amenity.css: -------------------------------------------------------------------------------- 1 | [@scale < 100001] { 2 | fill: #f9edd5; 3 | } 4 | -------------------------------------------------------------------------------- /css/style_boundary.css: -------------------------------------------------------------------------------- 1 | * { 2 | fill: #eaeaea; 3 | font-family: "DejaVu Sans"; 4 | halo-color: white; 5 | halo-radius: 1; 6 | font-weight: normal; 7 | font-fill: #000000; 8 | font-size: 9; 9 | font-style: italic; 10 | } -------------------------------------------------------------------------------- /css/style_buildings.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "DejaVu Sans"; 3 | halo-color: #ffffff; 4 | halo-radius: 0.3; 5 | font-weight: normal; 6 | font-fill: #999; 7 | font-style: normal; 8 | label-anchor: 0.5 0; 9 | label-offset: 0 5; 10 | } 11 | 12 | [@scale < 10001] [@scale > 5000] { 13 | fill: #000000, #f0f0f0; 14 | fill-opacity: 0.4, 1; 15 | geometry: [offset(way, 0.5, -0.5)], [way]; 16 | } 17 | 18 | [@scale < 5001] [@scale > 2500] { 19 | fill: #000000, #f0f0f0; 20 | fill-opacity: 0.4, 1; 21 | geometry: [offset(way, 0.4, -0.4)], [way]; 22 | font-size: 8.5; 23 | label: [name]; 24 | } 25 | 26 | [@scale < 2501] { 27 | fill: #000000, #f0f0f0; 28 | fill-opacity: 0.4, 1; 29 | geometry: [offset(way, 0.3, -0.3)], [way]; 30 | font-size: 8.5; 31 | label: [name]; 32 | } 33 | -------------------------------------------------------------------------------- /css/style_country.css: -------------------------------------------------------------------------------- 1 | * { 2 | stroke: #b2aea6; 3 | stroke-width: 3; 4 | } -------------------------------------------------------------------------------- /css/style_county.css: -------------------------------------------------------------------------------- 1 | * { 2 | stroke: #C5AB8E; 3 | font-family: "DejaVu Sans"; 4 | stroke-opacity: 0.6; 5 | halo-color: white; 6 | halo-radius: 0.7; 7 | font-weight: normal; 8 | font-fill: #b0824b; 9 | font-style: italic; 10 | label-anchor: 0.5 0; 11 | label-offset: 0 5; 12 | } 13 | 14 | [@scale > 8000001] { 15 | stroke-opacity: 0; 16 | } 17 | 18 | [@scale < 8000001] [@scale > 5000001] { 19 | stroke-width: 0.7; 20 | } 21 | 22 | [@scale < 5000001] [@scale > 2000001] { 23 | stroke-width: 1; 24 | font-size: 8; 25 | label: [uppername]; 26 | label-geometry: [centroid(geom)]; 27 | } 28 | 29 | [@scale < 2000001] [@scale > 1000001] { 30 | stroke-width: 1.5; 31 | font-size: 10; 32 | label: [uppername]; 33 | label-geometry: [centroid(geom)]; 34 | } 35 | 36 | [@scale < 1000001] [@scale > 500001] { 37 | stroke-width: 2; 38 | font-size: 10; 39 | label: [uppername]; 40 | label-geometry: [centroid(geom)]; 41 | } 42 | 43 | [@scale < 500001] [@scale > 200001] { 44 | stroke-width: 3; 45 | font-size: 12; 46 | label: [uppername]; 47 | label-geometry: [centroid(geom)]; 48 | } 49 | 50 | [@scale < 200001] [@scale > 100001] { 51 | stroke-width: 3.5; 52 | font-size: 12; 53 | label: [uppername]; 54 | label-geometry: [centroid(geom)]; 55 | } 56 | 57 | [@scale < 100001] [@scale > 50001] { 58 | stroke-width: 4; 59 | font-size: 12; 60 | label: [uppername]; 61 | label-geometry: [centroid(geom)]; 62 | } 63 | 64 | [@scale < 50001] { 65 | stroke-width: 4; 66 | } -------------------------------------------------------------------------------- /css/style_district.css: -------------------------------------------------------------------------------- 1 | * { 2 | stroke: #C5AB8E; 3 | font-family: "Dialog.plain"; 4 | font-weight: normal; 5 | font-fill: #777; 6 | font-style: normal; 7 | label-anchor: 0.5 0; 8 | label-offset: 0 5; 9 | -gt-label-max-displacement: 600; 10 | -gt-label-repeat: 600; 11 | } 12 | 13 | [@scale > 200001] { 14 | stroke-opacity: 0; 15 | } 16 | 17 | [@scale < 200001] [@scale > 100001] { 18 | stroke-width: 0.1; 19 | stroke-opacity: 0.3; 20 | font-size: 8.5; 21 | label: [name]; 22 | label-geometry: [centroid(geom)]; 23 | } 24 | 25 | [@scale < 100001] [@scale > 20001] { 26 | stroke-width: 0.1; 27 | stroke-opacity: 0.3; 28 | font-size: 10; 29 | label: [name]; 30 | label-geometry: [centroid(geom)]; 31 | } 32 | 33 | [@scale < 20001] { 34 | /*font-size: 10; 35 | label: [name];*/ 36 | stroke-opacity: 0; 37 | } -------------------------------------------------------------------------------- /css/style_forestpark.css: -------------------------------------------------------------------------------- 1 | * { 2 | fill: #d2e4c8; 3 | font-family: "DejaVu Sans"; 4 | halo-color: white; 5 | halo-radius: 0.3; 6 | font-weight: normal; 7 | font-fill: #8ba464; 8 | font-style: normal; 9 | label-anchor: 0.5 0; 10 | label-offset: 0 5; 11 | } 12 | 13 | [@scale < 5001] { 14 | font-size: 8.5; 15 | label: [name]; 16 | } 17 | -------------------------------------------------------------------------------- /css/style_lakes.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "DejaVu Sans"; 3 | font-weight: normal; 4 | font-fill: #5588cb; 5 | font-style: italic; 6 | label-anchor: 0.5 0; 7 | label-offset: 0 5; 8 | -gt-label-follow-line: true; 9 | -gt-label-max-angle-delta: 90; 10 | -gt-label-max-displacement: 800; 11 | -gt-label-repeat: 500; 12 | } 13 | 14 | [@scale < 2000001] [@scale > 200001] [way_area > 541714434]{ 15 | font-size: 8.5; 16 | label: [name]; 17 | } 18 | 19 | [@scale < 200001] [@scale > 100001] [way_area > 20000000]{ 20 | font-size: 8.5; 21 | label: [name]; 22 | } 23 | 24 | [@scale < 1000001] [@scale > 50001] [way_area > 5000000]{ 25 | font-size: 8.5; 26 | label: [name]; 27 | } 28 | 29 | [@scale < 50001] [@scale > 20001] [way_area > 300000]{ 30 | font-size: 8.5; 31 | label: [name]; 32 | } 33 | 34 | [@scale < 20001] { 35 | font-size: 8.5; 36 | label: [name]; 37 | } -------------------------------------------------------------------------------- /css/style_minor_roads.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #484848; 3 | font-family: "DejaVu Sans"; 4 | font-weight: normal; 5 | halo-color: white; 6 | halo-radius: 1; 7 | -gt-label-follow-line: true; 8 | -gt-label-max-angle-delta: 90; 9 | -gt-label-max-displacement: 400; 10 | -gt-label-repeat: 300; 11 | stroke-linecap: round; 12 | } 13 | 14 | [@scale < 50001] [@scale > 25001] { 15 | stroke: #c2c2c2; 16 | stroke-opacity: 0.5; 17 | stroke-width: 0.1; 18 | } 19 | 20 | [@scale < 25001] [@scale > 10001] { 21 | stroke: #c2c2c2, white; 22 | stroke-opacity: 0.5, 1; 23 | stroke-width: 2, 1; 24 | z-index: 0, 1; 25 | } 26 | 27 | [@scale < 10001] [@scale > 5001]{ 28 | stroke: #c2c2c2, white; 29 | stroke-opacity: 0.5, 1; 30 | stroke-width: 5, 3; 31 | z-index: 0, 1; 32 | label: [name]; 33 | font-size: 7; 34 | } 35 | 36 | [@scale < 5001] { 37 | stroke: #c2c2c2, white; 38 | stroke-opacity: 0.5, 1; 39 | stroke-width: 8, 6; 40 | z-index: 0, 1; 41 | label: [name]; 42 | font-size: 9; 43 | } -------------------------------------------------------------------------------- /css/style_motorway.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #895519; 3 | font-family: "DejaVu Sans"; 4 | font-weight: normal; 5 | halo-color: white; 6 | halo-radius: 1; 7 | -gt-label-follow-line: true; 8 | -gt-label-max-angle-delta: 90; 9 | -gt-label-max-displacement: 400; 10 | -gt-label-repeat: 300; 11 | stroke-linecap: round; 12 | stroke: #f6cb8c; 13 | stroke-width: 2; 14 | } 15 | 16 | [@scale < 200001] [@scale > 100001] { 17 | stroke: #8f8f8f, #f6cb8c; 18 | stroke-width: 3, 2; 19 | stroke-opacity: 0.5, 1; 20 | z-index: 0, 1; 21 | label: [name]; 22 | font-size: 8; 23 | } 24 | 25 | [@scale < 100001] [@scale > 50001] { 26 | stroke: #8f8f8f, #f6cb8c; 27 | stroke-width: 3, 2; 28 | stroke-opacity: 0.5, 1; 29 | z-index: 0, 1; 30 | label: [name]; 31 | font-size: 9; 32 | } 33 | 34 | [@scale < 50001] [@scale > 25001] { 35 | stroke: #8f8f8f, #f6cb8c; 36 | stroke-width: 4, 3; 37 | stroke-opacity: 0.5, 1; 38 | z-index: 0, 1; 39 | label: [name]; 40 | font-size: 10; 41 | } 42 | 43 | [@scale < 25001] [@scale > 10001] { 44 | stroke: #8f8f8f, #f6cb8c; 45 | stroke-width: 7, 6; 46 | stroke-opacity: 0.5, 1; 47 | z-index: 0, 1; 48 | label: [name]; 49 | font-size: 11; 50 | } 51 | 52 | [@scale < 10001] [@scale > 5001] { 53 | stroke: #8f8f8f, #f6cb8c; 54 | stroke-width: 8, 7; 55 | stroke-opacity: 0.8, 1; 56 | z-index: 0, 1; 57 | label: [name]; 58 | font-size: 12; 59 | } 60 | 61 | [@scale < 5001] { 62 | stroke: #8f8f8f, #f6cb8c; 63 | stroke-width: 14, 12; 64 | stroke-opacity: 0.8, 1; 65 | z-index: 0, 1; 66 | label: [name]; 67 | font-size: 13; 68 | } 69 | -------------------------------------------------------------------------------- /css/style_pedestrian.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #484848; 3 | font-family: "DejaVu Sans"; 4 | font-weight: normal; 5 | halo-color: white; 6 | halo-radius: 1; 7 | -gt-label-follow-line: true; 8 | -gt-label-max-angle-delta: 90; 9 | -gt-label-max-displacement: 400; 10 | -gt-label-repeat: 300; 11 | stroke-linecap: round; 12 | } 13 | 14 | [@scale < 50001] [@scale > 25001] { 15 | stroke: #d5d4c8; 16 | stroke-opacity: 0.5; 17 | stroke-width: 0.1; 18 | } 19 | 20 | [@scale < 25001] [@scale > 10001] { 21 | stroke: #c8c4b8, #d5d4c8; 22 | stroke-opacity: 0.5, 1; 23 | stroke-width: 0.5, 0.3; 24 | z-index: 0, 1; 25 | } 26 | 27 | [@scale < 10001] [@scale > 5001]{ 28 | stroke: #888, #ddd; 29 | stroke-opacity: 0.5, 1; 30 | stroke-width: 2, 1.5; 31 | z-index: 0, 1; 32 | label: [name]; 33 | font-size: 6; 34 | } 35 | 36 | [@scale < 5001] { 37 | stroke: #888, #ddd; 38 | stroke-opacity: 0.5, 1; 39 | stroke-width: 3.5, 3; 40 | z-index: 0, 1; 41 | label: [name]; 42 | font-size: 7; 43 | } -------------------------------------------------------------------------------- /css/style_rails.css: -------------------------------------------------------------------------------- 1 | [@scale < 50001] [@scale > 10000] { 2 | stroke: #444; 3 | stroke-opacity: 0.2; 4 | stroke-width: 0.3; 5 | } 6 | 7 | [@scale < 10001] [@scale > 5000] { 8 | stroke: #8f8f8f, symbol("shape://vertline"); 9 | stroke-opacity: 0.8; 10 | stroke-width: 0.3; 11 | } 12 | 13 | [@scale < 10001] [@scale > 5000] :nth-stroke(2) { 14 | size: 3; 15 | stroke: #8f8f8f; 16 | stroke-opacity: 0.2; 17 | stroke-width: 0.3; 18 | } 19 | 20 | [@scale < 5001] { 21 | stroke: #8f8f8f, symbol("shape://vertline"); 22 | stroke-opacity: 0.8; 23 | stroke-width: 0.3; 24 | } 25 | 26 | [@scale < 5001] :nth-stroke(2) { 27 | size: 5; 28 | stroke: #8f8f8f; 29 | stroke-opacity: 0.2; 30 | stroke-width: 0.5; 31 | } -------------------------------------------------------------------------------- /css/style_roads.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #484848; 3 | font-family: "DejaVu Sans"; 4 | font-weight: normal; 5 | halo-color: white; 6 | halo-radius: 1; 7 | -gt-label-follow-line: true; 8 | -gt-label-max-angle-delta: 90; 9 | -gt-label-max-displacement: 400; 10 | -gt-label-repeat: 300; 11 | stroke-linecap: round; 12 | } 13 | 14 | [@scale < 100001] [@scale > 50001] { 15 | stroke: white; 16 | stroke-width: 0.3; 17 | } 18 | 19 | [@scale < 50001] [@scale > 25001] { 20 | stroke: #c2c2c2, white; 21 | stroke-width: 2.2, 1; 22 | stroke-opacity: 0.5, 1; 23 | z-index: 0, 1; 24 | } 25 | 26 | [@scale < 25001] [@scale > 10001] { 27 | stroke: #c2c2c2, white; 28 | stroke-width: 5, 4; 29 | stroke-opacity: 0.5, 1; 30 | z-index: 0, 1; 31 | label: [name]; 32 | font-size: 8; 33 | } 34 | 35 | [@scale < 10001] [@scale > 5001] { 36 | stroke: #c2c2c2, white; 37 | stroke-width: 7, 6; 38 | stroke-opacity: 0.5, 1; 39 | z-index: 0, 1; 40 | label: [name]; 41 | font-size: 10; 42 | } 43 | 44 | [@scale < 5001] { 45 | stroke: #c2c2c2, white; 46 | stroke-width: 10, 8; 47 | stroke-opacity: 0.5, 1; 48 | z-index: 0, 1; 49 | label: [name]; 50 | font-size: 10; 51 | } -------------------------------------------------------------------------------- /css/style_settlements.css: -------------------------------------------------------------------------------- 1 | * { 2 | stroke: #C5AB8E; 3 | font-family: "Dialog.plain"; 4 | stroke-opacity: 0.6; 5 | font-weight: normal; 6 | font-fill: #777; 7 | font-style: normal; 8 | label-anchor: 0.5 0; 9 | label-offset: 0 5; 10 | -gt-label-max-displacement: 600; 11 | -gt-label-repeat: 600; 12 | } 13 | 14 | [@scale > 500001] { 15 | stroke-opacity: 0; 16 | } 17 | 18 | [@scale < 500001] [@scale > 200001] { 19 | stroke-width: 0.1; 20 | } 21 | 22 | [@scale < 200001] [@scale > 10001] { 23 | stroke-width: 0.3; 24 | } 25 | 26 | [@scale < 200001] [@scale > 10001] [way_area > 326122] [way_area < 9275414]{ 27 | font-size: 8.5; 28 | label: [name]; 29 | label-geometry: [centroid(geom)]; 30 | } 31 | [@scale < 200001] [@scale > 10001] [way_area > 9275414] [way_area < 15043800] { 32 | font-size: 9.5; 33 | label: [name]; 34 | label-geometry: [centroid(geom)]; 35 | } 36 | [@scale < 200001] [@scale > 10001] [way_area > 15043800] [way_area < 22999260] { 37 | font-size: 10.5; 38 | label: [name]; 39 | label-geometry: [centroid(geom)]; 40 | } 41 | [@scale < 200001] [@scale > 10001] [way_area > 22999260] [way_area < 39459160] { 42 | font-size: 13; 43 | label: [name]; 44 | label-geometry: [centroid(geom)]; 45 | } 46 | [@scale < 200001] [@scale > 10001] [way_area > 39459160] { 47 | font-size: 16; 48 | label: [name]; 49 | label-geometry: [centroid(geom)]; 50 | } 51 | 52 | [@scale < 10001] { 53 | stroke-width: 0.8; 54 | } -------------------------------------------------------------------------------- /css/style_subdistrict.css: -------------------------------------------------------------------------------- 1 | [@scale < 20001] { 2 | /*stroke: #777; 3 | stroke-width: 0.5; 4 | stroke-opacity: 0.5;*/ 5 | font-family: "Dialog.plain"; 6 | font-weight: normal; 7 | font-fill: #777; 8 | font-style: normal; 9 | font-size: 12; 10 | label: [name]; 11 | } -------------------------------------------------------------------------------- /css/style_trunk_primary.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #895519; 3 | font-family: "DejaVu Sans"; 4 | font-weight: normal; 5 | halo-color: white; 6 | halo-radius: 1; 7 | -gt-label-follow-line: true; 8 | -gt-label-max-angle-delta: 90; 9 | -gt-label-max-displacement: 400; 10 | -gt-label-repeat: 300; 11 | stroke-linecap: round; 12 | stroke: #ffebaf; 13 | stroke-width: 1px; 14 | } 15 | 16 | [@scale < 200001] [@scale > 100001] { 17 | stroke: #8f8f8f, #ffebaf; 18 | stroke-width: 2.6, 1.5; 19 | stroke-opacity: 0.3, 1; 20 | z-index: 0, 1; 21 | label: [name]; 22 | font-size: 7; 23 | } 24 | 25 | [@scale < 100001] [@scale > 50001] { 26 | stroke: #8f8f8f, #ffebaf; 27 | stroke-width: 3, 2; 28 | stroke-opacity: 0.5, 1; 29 | z-index: 0, 1; 30 | label: [name]; 31 | font-size: 8; 32 | } 33 | 34 | [@scale < 50001] [@scale > 25001] { 35 | stroke: #8f8f8f, #ffebaf; 36 | stroke-width: 3, 2; 37 | stroke-opacity: 0.5, 1; 38 | z-index: 0, 1; 39 | label: [name]; 40 | font-size: 9; 41 | } 42 | 43 | [@scale < 25001] [@scale > 10001] { 44 | stroke: #8f8f8f, #ffebaf; 45 | stroke-width: 5, 4; 46 | stroke-opacity: 0.5, 1; 47 | z-index: 0, 1; 48 | label: [name]; 49 | font-size: 10; 50 | } 51 | 52 | [@scale < 10001] [@scale > 5001] { 53 | stroke: #8f8f8f, #ffebaf; 54 | stroke-width: 7, 6; 55 | stroke-opacity: 0.5, 1; 56 | z-index: 0, 1; 57 | label: [name]; 58 | font-size: 11; 59 | } 60 | 61 | [@scale < 5001] { 62 | stroke: #8f8f8f, #ffebaf; 63 | stroke-width: 12, 11; 64 | stroke-opacity: 0.5, 1; 65 | z-index: 0, 1; 66 | label: [name]; 67 | font-size: 12; 68 | } 69 | -------------------------------------------------------------------------------- /css/style_water.css: -------------------------------------------------------------------------------- 1 | * { 2 | fill: #a3ccff; 3 | } 4 | -------------------------------------------------------------------------------- /css/style_waterway.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-fill: #5588cb; 3 | font-family: "DejaVu Sans"; 4 | font-weight: italic; 5 | -gt-label-follow-line: true; 6 | -gt-label-max-angle-delta: 90; 7 | -gt-label-max-displacement: 800; 8 | -gt-label-repeat: 500; 9 | -gt-label-padding: 10; 10 | stroke-linecap: round; 11 | label-offset: 7px; 12 | } 13 | 14 | [@scale > 1000001] [waterway = 'river'] { 15 | stroke: #a3ccff; 16 | stroke-opacity: 0.7; 17 | stroke-width: 0.5; 18 | } 19 | 20 | [@scale < 1000001] [@scale > 200001] [waterway = 'river']{ 21 | stroke-opacity: 0.7; 22 | stroke-width: 1; 23 | stroke: #a3ccff; 24 | } 25 | 26 | [@scale < 200001] [@scale > 100001] { 27 | stroke-opacity: 0.7; 28 | stroke-width: 1.2; 29 | stroke: #a3ccff; 30 | } 31 | 32 | [@scale < 100001] { 33 | stroke: #a3ccff; 34 | stroke-opacity: 0.7; 35 | stroke-width: 1.5; 36 | font-size: 8.5; 37 | label: [name]; 38 | } 39 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | db: 4 | build: 5 | context: ./docker/db 6 | dockerfile: Dockerfile 7 | args: 8 | POSTGIS_VERSION: ${POSTGIS_VERSION} 9 | TIMEZONE: ${TIMEZONE} 10 | image: osmgwc-db 11 | volumes: 12 | - db:/var/lib/postgresql/data 13 | ports: 14 | - '5432:5432' 15 | env_file: ./docker/db/.env 16 | environment: 17 | - DB_PASSWORD=${OSMGWC_DB_PASSWORD:-abc123} 18 | - POSTGRES_PASSWORD=${OSMGWC_POSTGRES_PASSWORD:-postgres} 19 | 20 | volumes: 21 | db: 22 | -------------------------------------------------------------------------------- /docker/db/.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fegyi001/osmgwc/3b26872cde8890c534c8921eac6c82a62a34f854/docker/db/.env -------------------------------------------------------------------------------- /docker/db/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG POSTGIS_VERSION 2 | 3 | FROM postgis/postgis:${POSTGIS_VERSION} 4 | 5 | ARG TIMEZONE 6 | 7 | RUN mkdir -p /opt/apps 8 | 9 | RUN apt-get update \ 10 | && apt-get install -y --no-install-recommends \ 11 | wget osm2pgsql bzip2 libproj-dev \ 12 | gdal-bin \ 13 | && ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \ 14 | && echo ${TIMEZONE} > /etc/timezone 15 | 16 | WORKDIR /opt/downloads 17 | 18 | RUN wget http://download.geofabrik.de/europe/hungary-latest.osm.bz2 \ 19 | && bzip2 -d hungary-latest.osm.bz2 20 | 21 | # add init script 22 | RUN mkdir -p /docker-entrypoint-initdb.d 23 | COPY ./initdb-postgis.sh /docker-entrypoint-initdb.d/postgis.sh 24 | -------------------------------------------------------------------------------- /docker/db/initdb-postgis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # Perform all actions as $POSTGRES_USER 6 | export PGUSER="$POSTGRES_USER" 7 | 8 | # https://pgtune.leopard.in.ua/ 9 | # DB Version: 11 10 | # OS Type: linux 11 | # DB Type: web 12 | # Total Memory (RAM): 4 GB 13 | # CPUs num: 2 14 | # Connections num: 150 15 | # Data Storage: ssd 16 | psql -c "ALTER SYSTEM SET max_connections = '150';" 17 | psql -c "ALTER SYSTEM SET shared_buffers = '1GB';" 18 | psql -c "ALTER SYSTEM SET effective_cache_size = '3GB';" 19 | psql -c "ALTER SYSTEM SET maintenance_work_mem = '256MB';" 20 | psql -c "ALTER SYSTEM SET checkpoint_completion_target = '0.7';" 21 | psql -c "ALTER SYSTEM SET wal_buffers = '16MB';" 22 | psql -c "ALTER SYSTEM SET default_statistics_target = '100';" 23 | psql -c "ALTER SYSTEM SET random_page_cost = '1.1';" 24 | psql -c "ALTER SYSTEM SET effective_io_concurrency = '200';" 25 | psql -c "ALTER SYSTEM SET work_mem = '6990kB';" 26 | psql -c "ALTER SYSTEM SET min_wal_size = '1GB';" 27 | psql -c "ALTER SYSTEM SET max_wal_size = '2GB';" 28 | psql -c "ALTER SYSTEM SET max_worker_processes = '2';" 29 | psql -c "ALTER SYSTEM SET max_parallel_workers_per_gather = '1';" 30 | psql -c "ALTER SYSTEM SET max_parallel_workers = '2';" 31 | -------------------------------------------------------------------------------- /img/cached2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fegyi001/osmgwc/3b26872cde8890c534c8921eac6c82a62a34f854/img/cached2.png -------------------------------------------------------------------------------- /img/gridset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fegyi001/osmgwc/3b26872cde8890c534c8921eac6c82a62a34f854/img/gridset.png -------------------------------------------------------------------------------- /img/layergroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fegyi001/osmgwc/3b26872cde8890c534c8921eac6c82a62a34f854/img/layergroup.png -------------------------------------------------------------------------------- /img/preview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fegyi001/osmgwc/3b26872cde8890c534c8921eac6c82a62a34f854/img/preview2.png -------------------------------------------------------------------------------- /sql/create_separate_tables.sql: -------------------------------------------------------------------------------- 1 | create schema if not exists osm; 2 | 3 | drop table if exists osm.country; 4 | create table osm.country( 5 | id serial not null primary key, 6 | osm_id integer, 7 | name text, 8 | uppername text, 9 | geom geometry(multipolygon, 23700) 10 | ); 11 | create index gix_country on osm.country using gist(geom); 12 | delete from osm.country; 13 | insert into osm.country(osm_id, name, uppername, geom) 14 | SELECT planet_osm_polygon.osm_id, 15 | planet_osm_polygon.name as name, 16 | upper(planet_osm_polygon.name) AS uppername, 17 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 18 | FROM planet_osm_polygon 19 | WHERE planet_osm_polygon.admin_level = '2'::text AND planet_osm_polygon.boundary = 'administrative'::text; 20 | 21 | drop table if exists osm.amenity; 22 | create table osm.amenity( 23 | id serial not null primary key, 24 | osm_id integer, 25 | geom geometry(multipolygon, 23700) 26 | ); 27 | create index gix_amenity on osm.amenity using gist(geom); 28 | delete from osm.amenity; 29 | insert into osm.amenity(osm_id, geom) 30 | SELECT planet_osm_polygon.osm_id, 31 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 32 | FROM planet_osm_polygon 33 | WHERE planet_osm_polygon.amenity IS NOT NULL AND (planet_osm_polygon.amenity = ANY (ARRAY['college'::text, 'community_centre'::text, 'courthouse'::text, 'doctors'::text, 'embassy'::text, 'grave_yard'::text, 'hospital'::text, 'library'::text, 'marketplace'::text, 'prison'::text, 'public_building'::text, 'school'::text, 'simming_pool'::text, 'theatre'::text, 'townhall'::text, 'university'::text])); 34 | --delete from osm.amenity where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 35 | 36 | drop table if exists osm.boundary; 37 | create table osm.boundary( 38 | id serial not null primary key, 39 | osm_id integer, 40 | name text, 41 | uppername text, 42 | geom geometry(multipolygon, 23700) 43 | ); 44 | create index gix_boundary on osm.boundary using gist(geom); 45 | delete from osm.boundary; 46 | insert into osm.boundary(osm_id, name, uppername, geom) 47 | SELECT planet_osm_polygon.osm_id, 48 | planet_osm_polygon.name as name, 49 | upper(planet_osm_polygon.name) AS uppername, 50 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 51 | FROM planet_osm_polygon 52 | WHERE planet_osm_polygon.admin_level = '2'::text AND planet_osm_polygon.boundary = 'administrative'::text; 53 | 54 | drop table if exists osm.buildings; 55 | create table osm.buildings( 56 | id serial not null primary key, 57 | osm_id integer, 58 | name text, 59 | housename text, 60 | housenumber text, 61 | geom geometry(multipolygon, 23700) 62 | ); 63 | create index gix_buildings on osm.buildings using gist(geom); 64 | delete from osm.buildings; 65 | insert into osm.buildings(osm_id, name, housename, housenumber, geom) 66 | SELECT planet_osm_polygon.osm_id, 67 | planet_osm_polygon.name, 68 | planet_osm_polygon."addr:housename", 69 | planet_osm_polygon."addr:housenumber", 70 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 71 | FROM planet_osm_polygon 72 | WHERE planet_osm_polygon.building IS NOT NULL AND st_area(planet_osm_polygon.way) < 100000::double precision; 73 | --delete from osm.buildings where not st_intersects(geom, (select geom from osm.country)); 74 | 75 | drop table if exists osm.county; 76 | create table osm.county( 77 | id serial not null primary key, 78 | osm_id integer, 79 | name text, 80 | uppername text, 81 | geom geometry(multipolygon, 23700) 82 | ); 83 | create index gix_county on osm.county using gist(geom); 84 | delete from osm.county; 85 | insert into osm.county(osm_id, name, uppername, geom) 86 | SELECT planet_osm_polygon.osm_id, 87 | planet_osm_polygon.name as name, 88 | upper(planet_osm_polygon.name) AS uppername, 89 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 90 | FROM planet_osm_polygon 91 | WHERE (planet_osm_polygon.place = 'county'::text OR planet_osm_polygon.admin_level = '6'::text AND planet_osm_polygon.name = 'Budapest'::text) AND planet_osm_polygon.boundary = 'administrative'::text; 92 | delete from osm.county where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 93 | 94 | drop table if exists osm.district; 95 | create table osm.district( 96 | id serial not null primary key, 97 | osm_id integer, 98 | name text, 99 | uppername text, 100 | geom geometry(multipolygon, 23700) 101 | ); 102 | create index gix_district on osm.district using gist(geom); 103 | delete from osm.district; 104 | insert into osm.district(osm_id, name, uppername, geom) 105 | SELECT planet_osm_polygon.osm_id, 106 | planet_osm_polygon.name, 107 | upper(planet_osm_polygon.name) AS uppername, 108 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 109 | FROM planet_osm_polygon 110 | WHERE planet_osm_polygon.admin_level = '9'::text AND planet_osm_polygon.boundary = 'administrative'::text; 111 | delete from osm.district where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 112 | 113 | drop table if exists osm.forestpark; 114 | create table osm.forestpark( 115 | id serial not null primary key, 116 | osm_id integer, 117 | name text, 118 | geom geometry(multipolygon, 23700) 119 | ); 120 | create index gix_forestpark on osm.forestpark using gist(geom); 121 | delete from osm.forestpark; 122 | insert into osm.forestpark(osm_id, name, geom) 123 | SELECT planet_osm_polygon.osm_id, 124 | planet_osm_polygon.name, 125 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 126 | FROM planet_osm_polygon 127 | WHERE (planet_osm_polygon.landuse = ANY (ARRAY['forest'::text, 'orchard'::text, 'park'::text, 'plant_nursery'::text, 'grass'::text, 'greenfield'::text, 'meadow'::text, 'recreation_ground'::text, 'village_green'::text, 'vineyard'::text])) OR (planet_osm_polygon.leisure = ANY (ARRAY['nature_reserve'::text, 'park'::text, 'dog_park'::text, 'garden'::text, 'golf_course'::text, 'horse_riding'::text, 'recreation_ground'::text, 'stadium'::text])); 128 | delete from osm.forestpark where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 129 | 130 | drop table if exists osm.lakes; 131 | create table osm.lakes( 132 | id serial not null primary key, 133 | osm_id integer, 134 | name text, 135 | way_area real, 136 | geom geometry(multipolygon, 23700) 137 | ); 138 | create index gix_lakes on osm.lakes using gist(geom); 139 | delete from osm.lakes; 140 | insert into osm.lakes(osm_id, name, way_area, geom) 141 | SELECT planet_osm_polygon.osm_id, 142 | planet_osm_polygon.name, 143 | planet_osm_polygon.way_area, 144 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 145 | FROM planet_osm_polygon 146 | WHERE planet_osm_polygon."natural" = 'water'::text AND (planet_osm_polygon.water IS NULL OR planet_osm_polygon.water IS NOT NULL AND planet_osm_polygon.water <> 'river'::text); 147 | delete from osm.lakes where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 148 | 149 | drop table if exists osm.minor_roads; 150 | create table osm.minor_roads( 151 | id serial not null primary key, 152 | osm_id integer, 153 | name text, 154 | geom geometry(multilinestring, 23700) 155 | ); 156 | create index gix_minor_roads on osm.minor_roads using gist(geom); 157 | delete from osm.minor_roads; 158 | insert into osm.minor_roads(osm_id, name, geom) 159 | SELECT planet_osm_line.osm_id, 160 | planet_osm_line.name, 161 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 162 | FROM planet_osm_line 163 | WHERE planet_osm_line.highway IS NOT NULL AND (planet_osm_line.highway <> ALL (ARRAY['motorway'::text, 'motorway_link'::text, 'trunk'::text, 'primary'::text, 'trunk_link'::text, 'primary_link'::text, 'secondary'::text, 'secondary_link'::text, 'road'::text, 'tertiary'::text, 'tertiary_link'::text, 'steps'::text, 'footway'::text, 'path'::text, 'pedestrian'::text, 'walkway'::text, 'service'::text, 'track'::text])) AND planet_osm_line.railway IS NULL OR planet_osm_line.railway = 'no'::text; 164 | --delete from osm.minor_roads where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 165 | 166 | drop table if exists osm.motorway; 167 | create table osm.motorway( 168 | id serial not null primary key, 169 | osm_id integer, 170 | name text, 171 | geom geometry(multilinestring, 23700) 172 | ); 173 | create index gix_motorway on osm.motorway using gist(geom); 174 | delete from osm.motorway; 175 | insert into osm.motorway(osm_id, name, geom) 176 | SELECT planet_osm_line.osm_id, 177 | planet_osm_line.name, 178 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 179 | FROM planet_osm_line 180 | WHERE planet_osm_line.highway = 'motorway'::text; 181 | delete from osm.motorway where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 182 | 183 | drop table if exists osm.pedestrian; 184 | create table osm.pedestrian( 185 | id serial not null primary key, 186 | osm_id integer, 187 | name text, 188 | geom geometry(multilinestring, 23700) 189 | ); 190 | create index gix_pedestrian on osm.pedestrian using gist(geom); 191 | delete from osm.pedestrian; 192 | insert into osm.pedestrian(osm_id, name, geom) 193 | SELECT planet_osm_line.osm_id, 194 | planet_osm_line.name, 195 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 196 | FROM planet_osm_line 197 | WHERE planet_osm_line.highway = ANY (ARRAY['steps'::text, 'footway'::text, 'path'::text, 'pedestrian'::text, 'walkway'::text, 'service'::text, 'track'::text]); 198 | --delete from osm.pedestrian where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 199 | 200 | drop table if exists osm.rails; 201 | create table osm.rails( 202 | id serial not null primary key, 203 | osm_id integer, 204 | name text, 205 | geom geometry(multilinestring, 23700) 206 | ); 207 | create index gix_rails on osm.rails using gist(geom); 208 | delete from osm.rails; 209 | insert into osm.rails(osm_id, name, geom) 210 | SELECT planet_osm_line.osm_id, 211 | planet_osm_line.name, 212 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 213 | FROM planet_osm_line 214 | WHERE planet_osm_line.railway IS NOT NULL AND (planet_osm_line.railway = ANY (ARRAY['light rail'::text, 'rail'::text, 'rail;construction'::text, 'tram'::text, 'yes'::text, 'traverser'::text])) OR planet_osm_line.railway ~~ '%rail%'::text; 215 | --delete from osm.rails where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 216 | 217 | drop table if exists osm.roads; 218 | create table osm.roads( 219 | id serial not null primary key, 220 | osm_id integer, 221 | name text, 222 | geom geometry(multilinestring, 23700) 223 | ); 224 | create index gix_roads on osm.roads using gist(geom); 225 | delete from osm.roads; 226 | insert into osm.roads(osm_id, name, geom) 227 | SELECT planet_osm_line.osm_id, 228 | planet_osm_line.name, 229 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 230 | FROM planet_osm_line 231 | WHERE planet_osm_line.highway = ANY (ARRAY['trunk_link'::text, 'primary_link'::text, 'secondary'::text, 'secondary_link'::text, 'road'::text, 'tertiary'::text, 'tertiary_link'::text]); 232 | --delete from osm.roads where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 233 | 234 | drop table if exists osm.settlements; 235 | create table osm.settlements( 236 | id serial not null primary key, 237 | osm_id integer, 238 | name text, 239 | uppername text, 240 | way_area real, 241 | geom geometry(multipolygon, 23700) 242 | ); 243 | create index gix_settlements on osm.settlements using gist(geom); 244 | delete from osm.settlements; 245 | insert into osm.settlements(osm_id, name, uppername, way_area, geom) 246 | SELECT planet_osm_polygon.osm_id, 247 | planet_osm_polygon.name, 248 | upper(planet_osm_polygon.name) AS uppername, 249 | planet_osm_polygon.way_area, 250 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 251 | FROM planet_osm_polygon 252 | WHERE planet_osm_polygon.admin_level = '8'::text AND planet_osm_polygon.boundary = 'administrative'::text; 253 | delete from osm.settlements where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 254 | 255 | drop table if exists osm.subdistrict; 256 | create table osm.subdistrict( 257 | id serial not null primary key, 258 | osm_id integer, 259 | name text, 260 | uppername text, 261 | geom geometry(multipolygon, 23700) 262 | ); 263 | create index gix_subdistrict on osm.subdistrict using gist(geom); 264 | delete from osm.subdistrict; 265 | insert into osm.subdistrict(osm_id, name, uppername, geom) 266 | SELECT planet_osm_polygon.osm_id, 267 | planet_osm_polygon.name, 268 | upper(planet_osm_polygon.name) AS uppername, 269 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 270 | FROM planet_osm_polygon 271 | WHERE planet_osm_polygon.admin_level = '10'::text AND planet_osm_polygon.boundary = 'administrative'::text; 272 | delete from osm.subdistrict where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 273 | 274 | drop table if exists osm.trunk_primary; 275 | create table osm.trunk_primary( 276 | id serial not null primary key, 277 | osm_id integer, 278 | name text, 279 | geom geometry(multilinestring, 23700) 280 | ); 281 | create index gix_trunk_primary on osm.trunk_primary using gist(geom); 282 | delete from osm.trunk_primary; 283 | insert into osm.trunk_primary(osm_id, name, geom) 284 | SELECT planet_osm_line.osm_id, 285 | planet_osm_line.name, 286 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 287 | FROM planet_osm_line 288 | WHERE planet_osm_line.highway = ANY (ARRAY['motorway_link'::text, 'trunk'::text, 'primary'::text]); 289 | --delete from osm.trunk_primary where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 290 | 291 | drop table if exists osm.water; 292 | create table osm.water( 293 | id serial not null primary key, 294 | osm_id integer, 295 | name text, 296 | geom geometry(multipolygon, 23700) 297 | ); 298 | create index gix_water on osm.water using gist(geom); 299 | delete from osm.water; 300 | insert into osm.water(osm_id, name, geom) 301 | SELECT planet_osm_polygon.osm_id, 302 | planet_osm_polygon.name, 303 | st_multi(planet_osm_polygon.way)::geometry(MultiPolygon, 23700) as way 304 | FROM planet_osm_polygon 305 | WHERE planet_osm_polygon."natural" = 'water'::text OR planet_osm_polygon.water IS NOT NULL OR planet_osm_polygon.waterway ~~ '%riverbank%'::text; 306 | --delete from osm.water where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 307 | 308 | drop table if exists osm.waterway; 309 | create table osm.waterway( 310 | id serial not null primary key, 311 | osm_id integer, 312 | name text, 313 | waterway text, 314 | geom geometry(multilinestring, 23700) 315 | ); 316 | create index gix_waterway on osm.waterway using gist(geom); 317 | delete from osm.waterway; 318 | insert into osm.waterway(osm_id, name, waterway, geom) 319 | SELECT planet_osm_line.osm_id, 320 | planet_osm_line.name, 321 | planet_osm_line.waterway, 322 | st_multi(planet_osm_line.way)::geometry(MultiLineString, 23700) as way 323 | FROM planet_osm_line 324 | WHERE planet_osm_line.waterway = ANY (ARRAY['drain'::text, 'canal'::text, 'waterfall'::text, 'river'::text, 'stream'::text, 'yes'::text]); 325 | --delete from osm.waterway where not st_intersects(st_centroid(geom), (select geom from osm.country limit 1)); 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /sql/drop_unnecessary_tables.sql: -------------------------------------------------------------------------------- 1 | drop table if exists planet_osm_line; 2 | drop table if exists planet_osm_nodes; 3 | drop table if exists planet_osm_point; 4 | drop table if exists planet_osm_polygon; 5 | drop table if exists planet_osm_rels; 6 | drop table if exists planet_osm_roads; 7 | drop table if exists planet_osm_ways; --------------------------------------------------------------------------------