| 1 | '''This Page is still a work in progress, expect glitches! ''' |
| 2 | |
| 3 | = Rendering !OpenStreetMap Data with MapServer = |
| 4 | |
| 5 | The map displayed on the from page of the [http://www.mapserver.org/ MapServer website] is an example of MapServer's rendering capabilities. |
| 6 | |
| 7 | !OpenStreetMap data can be used freely under the terms of the [http://creativecommons.org/licenses/by-sa/2.0/ Creative Commons Attribution-ShareAlike 2.0 license]: |
| 8 | |
| 9 | > !OpenStreetMap creates and provides free geographic data such as street maps to anyone who wants them. The project was started because most maps you think |
| 10 | > of as free actually have legal or technical restrictions on their use, holding back people from using them in creative, productive, or unexpected ways. |
| 11 | |
| 12 | == Which MapServer version to use == |
| 13 | |
| 14 | The mapfile presented here assumes a very recent version of MapServer is used, i.e. at least 5.4 . (Until 5.4 is released, you must checkout and compile the [http://www.mapserver.org/development/svn.html#code-developer-s-subversion-access trunk version]). You will have to include (at least) support for AGG rendering,postgis, and wms server.). Once you're done compiling, copy the ''mapserv'' binary to a cgi executable directory of your mapserver (/usr/lib/cgi-bin on debian) |
| 15 | |
| 16 | == Importing !OpenStreetMap Data == |
| 17 | |
| 18 | This howto will take australian data as an example. |
| 19 | |
| 20 | === Download === |
| 21 | |
| 22 | * Download an osm excerpt, for example from http://downloads.cloudmade.com/oceania/australia/australia.osm.bz2 |
| 23 | |
| 24 | * Optionally, download and unzip the shapefiles containing the world coastlines from http://hypercube.telascience.org/~kleptog/processed_p.zip (this shapefile isn't included or rendered with the supplied mapfile) |
| 25 | |
| 26 | === Import into Postgis === |
| 27 | |
| 28 | ==== Preparing the postgis database ==== |
| 29 | |
| 30 | We'll assume that the data will be imported into a database named {{{osm}}}. We will also add the 900913 crs, and grant access to a {{{www-data}}} user. |
| 31 | On a debian-ish system, this goes like: |
| 32 | |
| 33 | {{{ |
| 34 | # sudo su postgres |
| 35 | # createdb -E utf8 osm |
| 36 | # cat /usr/share/postgresql-8.3-postgis/lwpostgis.sql | psql -d osm |
| 37 | # cat /usr/share/postgresql-8.3-postgis/spatial_ref_sys.sql | psql -d osm |
| 38 | }}} |
| 39 | |
| 40 | Now log into the created database (as postgres user): |
| 41 | |
| 42 | {{{ |
| 43 | # psql -d osm |
| 44 | }}} |
| 45 | |
| 46 | And run these two commands: |
| 47 | |
| 48 | {{{ |
| 49 | INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, srtext, proj4text) |
| 50 | VALUES (900913, 'spatialreference.org', 900913, |
| 51 | 'PROJCS["unnamed",GEOGCS["unnamed ellipse",DATUM["unknown", |
| 52 | SPHEROID["unnamed",6378137,0]],PRIMEM["Greenwich",0], |
| 53 | UNIT["degree",0.0174532925199433]],PROJECTION["Mercator_2SP"], |
| 54 | PARAMETER["standard_parallel_1",0],PARAMETER["central_meridian",0], |
| 55 | PARAMETER["false_easting",0],PARAMETER["false_northing",0], |
| 56 | UNIT["Meter",1], |
| 57 | EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 |
| 58 | +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"]]', |
| 59 | '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 |
| 60 | +k=1.0 +units=m +nadgrids=@null +wktext +no_defs'); |
| 61 | |
| 62 | create user "www-data" with password 'www-data'; |
| 63 | }}} |
| 64 | |
| 65 | ==== Importing the OSM data ==== |
| 66 | * Install the [http://wiki.openstreetmap.org/wiki/Osm2pgsql Osm2pgsql] helper program |
| 67 | |
| 68 | * Run the importation process (as the postgres user) (this will take some time, depending on your processing power and the quantity of data you want to import): |
| 69 | |
| 70 | {{{ |
| 71 | # osm2pgsql -d osm -p osm -s -C 1024 /path/to/australia.osm.bz2 |
| 72 | }}} |
| 73 | |
| 74 | * Postprocess the imported data: |
| 75 | |
| 76 | {{{ |
| 77 | # psql -d osm |
| 78 | }}} |
| 79 | |
| 80 | {{{ |
| 81 | -- optional, makes it easier to wrap place names |
| 82 | update osm_point set name = replace(name,'-',' '); |
| 83 | |
| 84 | -- grant our user access to the data |
| 85 | grant SELECT on osm_line to "www-data"; |
| 86 | grant SELECT on osm_point to "www-data"; |
| 87 | grant SELECT on osm_polygon to "www-data"; |
| 88 | |
| 89 | -- correct a few common typos |
| 90 | update osm_line set tunnel='yes' where tunnel='true'; |
| 91 | update osm_line set tunnel='no' where tunnel='false'; |
| 92 | update osm_line set tunnel='yes' where tunnel='yel'; |
| 93 | update osm_line set bridge='yes' where bridge='true'; |
| 94 | |
| 95 | update osm_line set oneway='yes' where oneway='Yes'; |
| 96 | update osm_line set oneway='yes' where oneway='true'; |
| 97 | update osm_line set oneway='yes' where oneway='1'; |
| 98 | |
| 99 | -- rename one of the columns to make it easier to write mapserver expressions |
| 100 | alter table osm_polygon rename column "natural" to nature; |
| 101 | |
| 102 | -- create a few indexes on the data for speedier access |
| 103 | create index osm_polygon_building_idx on osm_polygon(building); |
| 104 | create index osm_polygon_amenity_idx on osm_polygon(amenity); |
| 105 | create index osm_polygon_landuse_idx on osm_polygon(landuse); |
| 106 | create index osm_line_highway_idx on osm_line(highway); |
| 107 | create index osm_line_aeroway_idx on osm_line(aeroway); |
| 108 | create index osm_line_railway_idx on osm_line(railway); |
| 109 | create index osm_line_bridge_idx on osm_line(bridge); |
| 110 | create index osm_polygon_leisure_idx on osm_polygon(leisure); |
| 111 | create index osm_polygon_aeroway_idx on osm_polygon(aeroway); |
| 112 | create index osm_polygon_waterway_idx on osm_polygon(waterway); |
| 113 | create index osm_polygon_natural_idx on osm_polygon(nature); |
| 114 | create index osm_point_place_idx on osm_point(place); |
| 115 | create index osm_line_zorder_idx on osm_line(z_order); |
| 116 | }}} |
| 117 | |
| 118 | == Creating the Mapfile == |
| 119 | |
| 120 | checkout the mapfile and dependencies: |
| 121 | |
| 122 | {{{ |
| 123 | # svn checkout http://mapserver-utils.googlecode.com/svn/trunk/ mapserverosm |
| 124 | }}} |
| 125 | |
| 126 | this is a work in progress mapfile, that compiles a template and a style file into a full-blown MapServer mapfile. The supplied Makefile supposes that the C preprocessor is installed on your system. The ''fonts.lst'' file contains the path to the two fonts used: adapt to reference similar fonts if the ones in the file don't exist on your system. |
| 127 | |
| 128 | {{{ |
| 129 | # cd mapserverosm |
| 130 | # make |
| 131 | }}} |
| 132 | |
| 133 | check that you now have a full mapfile, named ''osm.map'', and that all the paths and database accesses are ok by running : |
| 134 | {{{ |
| 135 | # /path/to/mapserver/shp2img -m osm.map -o osm.png |
| 136 | }}} |
| 137 | |
| 138 | ''osm.png'' should be an image centered on sydney |
| 139 | |
| 140 | == Creating the !OpenLayers page == |
| 141 | copy/paste this block to a file accessible on your webserver. you will have to adapt at least the path to ''osm.map'' file, and the url of your ''mapserv'' binary: |
| 142 | {{{ |
| 143 | <html xmlns="http://www.w3.org/1999/xhtml"> |
| 144 | <head> |
| 145 | |
| 146 | <style type="text/css"> |
| 147 | body { |
| 148 | width:100%; |
| 149 | height:100%; |
| 150 | border: 0px; |
| 151 | margin: 0px; |
| 152 | padding: 0px; |
| 153 | font:sans-serif; |
| 154 | font-size:small; |
| 155 | } |
| 156 | #map { |
| 157 | width: 800px; |
| 158 | height: 600px; |
| 159 | border: 1px solid black; |
| 160 | padding: 0px; |
| 161 | margin:0px auto; |
| 162 | margin-top:30px; |
| 163 | position:relative; |
| 164 | } |
| 165 | #controls { |
| 166 | width: 600px; |
| 167 | margin:0px auto; |
| 168 | margin-top:5px; |
| 169 | } |
| 170 | </style> |
| 171 | |
| 172 | <script src="http://www.openlayers.org/api/OpenLayers.js"></script> |
| 173 | <script type="text/javascript"> |
| 174 | var lon = 16831422; |
| 175 | var lat=-4012608; |
| 176 | var zoom = 3; |
| 177 | var map, layer; |
| 178 | |
| 179 | function init(){ |
| 180 | map = new OpenLayers.Map( 'map' ); |
| 181 | |
| 182 | var wms = new OpenLayers.Layer.WMS( "WMS", |
| 183 | |
| 184 | /* |
| 185 | change here to suite your setup |
| 186 | */ |
| 187 | "http://myserver/cgi-bin/mapserv-trunk?", |
| 188 | {map: '/path/to/osm.map', |
| 189 | |
| 190 | |
| 191 | layers: 'default', |
| 192 | format: 'aggpng24', |
| 193 | transparent: 'off'}, |
| 194 | {maxExtent: new OpenLayers.Bounds(11548635,-5889094,18604187,-597430), |
| 195 | scales: [5000,10000,25000,50000,100000,250000,500000, |
| 196 | 1000000,2500000,5000000,10000000,25000000,50000000,100000000], |
| 197 | units: 'm', |
| 198 | projection:new OpenLayers.Projection("EPSG:900913"), |
| 199 | gutter:0, |
| 200 | ratio:1, |
| 201 | wrapDateLine: true, |
| 202 | isBaselayer:true, |
| 203 | singleTile:true, |
| 204 | transitionEffect:'resize'} ); |
| 205 | |
| 206 | map.addLayers([wms]); |
| 207 | if(!map.getCenter()) |
| 208 | map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); |
| 209 | map.addControl(new OpenLayers.Control.Scale('scale')); |
| 210 | map.addControl(new OpenLayers.Control.Permalink('permalink')); |
| 211 | map.addControl(new OpenLayers.Control.MousePosition()); |
| 212 | } |
| 213 | </script> |
| 214 | </head> |
| 215 | |
| 216 | <body onload="init()"> |
| 217 | <div id="map"> |
| 218 | </div> |
| 219 | <div id="controls"> |
| 220 | <span id="scale" style="float:left"></span> |
| 221 | <a href="#" id="permalink" style="float:right">lien direct</a> |
| 222 | </div> |
| 223 | </body> |
| 224 | </html> |
| 225 | }}} |
| 226 | |
| 227 | == And now? == |
| 228 | |
| 229 | * you can change the color scheme by editing the ''osm1.style'' file, and rerunning ''make'' |
| 230 | |
| 231 | * feel free to edit this page to include any solutions to problems you might have had following these steps |
| 232 | |
| 233 | * for more info: thomas.bonfort at gmail dot com |
| 234 | |
| 235 | |
| 236 | |