|
| 1 | +# Geospatial analysis with osm2pgsql # |
| 2 | + |
| 3 | +An osm2pgsql database and PostGIS is well-suited for geospatial analysis using |
| 4 | +OpenStreetMap data where topology is not a consideration. |
| 5 | + |
| 6 | +PostGIS provides an [extensive number of geometry functions](http://postgis.net/docs/manual-2.1/reference.html) |
| 7 | +and a full description of how to perform analysis with them is beyond the |
| 8 | +scope of a readme, but a simple example of finding the total road lengths by |
| 9 | +classification for a municipality should help. |
| 10 | + |
| 11 | +To start with, we'll download the data for the region as an [extract from Geofabrik](http://download.geofabrik.de/) and import it with osm2pgsql. |
| 12 | + |
| 13 | + osm2pgsql --database gis --number-processes 4 --multi-geometry british-columbia-latest.osm.pbf |
| 14 | + |
| 15 | +``--multi-geometry`` (``-G``) is necessary for most analysis as it prevents |
| 16 | +MULTIPOLYGONs from being split into multiple POLYGONs, a step that is |
| 17 | +normally used to [increase rendering speed](http://paulnorman.ca/blog/2014/03/osm2pgsql-multipolygons) |
| 18 | +but increases the complexity of analysis SQL. |
| 19 | + |
| 20 | +Loading should take about 10 minutes, depending on computer speed. Once this |
| 21 | +is done we'll open a PostgreSQL terminal with ``psql -d gis``, although a GUI |
| 22 | +like pgadmin or any standard tool could be used instead. |
| 23 | + |
| 24 | +To start, we'll create a partial index to speed up highway queries. |
| 25 | + |
| 26 | +```sql |
| 27 | +CREATE INDEX planet_osm_line_highways_index ON planet_osm_line USING GiST (way) WHERE (highway IS NOT NULL); |
| 28 | +``` |
| 29 | + |
| 30 | +We'll first find the ID of the polygon we want |
| 31 | + |
| 32 | +```sql |
| 33 | +gis=# SELECT osm_id FROM planet_osm_polygon |
| 34 | +WHERE boundary='administrative' AND admin_level='8' AND name='New Westminster'; |
| 35 | + osm_id |
| 36 | +---------- |
| 37 | + -1377803 |
| 38 | +``` |
| 39 | + |
| 40 | +The negative sign tells us that the geometry is from a relation, and checking |
| 41 | +on [the OpenStreetMap site](https://www.openstreetmap.org/relation/1377803) |
| 42 | +confirms which it is. |
| 43 | + |
| 44 | +We want to find all the roads in the city and get the length of the portion in |
| 45 | +the city, sorted by road classification. Roads are in the ``planet_osm_line`` |
| 46 | +table, not the ``planet_osm_roads`` table which is only has a subset of data |
| 47 | +for low-zoom rendering. |
| 48 | + |
| 49 | +```sql |
| 50 | +gis=# SELECT |
| 51 | + round(SUM( |
| 52 | + ST_Length(ST_Transform( |
| 53 | + ST_Intersection(way, (SELECT way FROM planet_osm_polygon WHERE osm_id=-1377803)) |
| 54 | + ,4326)::geography) |
| 55 | + )) AS "distance (meters)", highway AS "highway type" |
| 56 | + FROM planet_osm_line |
| 57 | + WHERE highway IS NOT NULL |
| 58 | + AND ST_Intersects(way, (SELECT way FROM planet_osm_polygon WHERE osm_id=-1377803)) |
| 59 | + GROUP BY highway |
| 60 | + ORDER BY "distance (meters)" DESC |
| 61 | + LIMIT 10; |
| 62 | + distance (meters) | highway type |
| 63 | +-------------------+--------------- |
| 64 | + 138122 | residential |
| 65 | + 79519 | service |
| 66 | + 51890 | footway |
| 67 | + 25610 | tertiary |
| 68 | + 23434 | secondary |
| 69 | + 14900 | cycleway |
| 70 | + 6468 | primary |
| 71 | + 5217 | motorway |
| 72 | + 4389 | motorway_link |
| 73 | + 3728 | track |
| 74 | +``` |
| 75 | + |
| 76 | +The ``ST_Transform(...,4326)::geography`` is necessary because the data was |
| 77 | +imported in Mercator. This step could have been avoided by importing in a local |
| 78 | +projection like a suitable UTM projection. |
| 79 | + |
| 80 | +More complicated analysises can be completed, but this simple example shows how |
| 81 | +to use the tables and put conditions on the columns. |
0 commit comments