Friday, December 10, 2010

OSM data to shapefile with specific OSM Tags

Well I had a unique problem or I should say not so unique problem in preparing some OpenStreetMap (OSM) data for import into PostGIS and then export to Shapefiles for my students.

Job at hand:
Generate some shapefiles based on specific OSM data tags more specifically wheelchair access tags.

Tools:
  1. osm2pgsql.exe
  2. python 3.1 custom script see below
  3. pgsql2shp.exe  this is installed with PostGIS located in the /bin  directory
Prerequisites:
  • Postgresql 8.4.4 with PostGIS 1.5.2
  • Download and unzip the osm2pgsql.exe for import
  • Windows 7 Pro  (this is not a prereq, just letting you know what I used)
Procedure:
  1. Download OSM data as .osm for your region using the web tab "Export" on the osm website (see screenshot) or visit GeoFabrik or Cloudmade for shapefiles/OSM data.
  2. Prepare data for osm2pgsql.exe by 
    1. Edit the import   .style file  to limit what is actually going into PostGIS so only our needed fields come across.  See the wiki page for details
    2. Edit the .osm file to replace all the Tag names so they conform to support the shapefile limitations.  I used a custom PYTHON 3.1 script shown below to do this dirty work.
Quick example of what is not supported by shapefiles:
  1. field names larger than 10 characters
  2. field names with ":", ";" "  " 
I wanted to for example use this osm tag "wheelchair:access"  as my field header but it would only use "wheelchair:" if I don't modify the .osm data (xml data)  Not good so the job is to rename this to something that is able to be used in a shapefile like "wch_access". 

Here is the python code that I used to do the data text search and replace of multiple words in preparing the .osm file for import.  Just copy the code below and save it as  myfilename.py  and be sure to change the location of your .osm file and the name of the new output file.

 import sys, os  
 def replace_all(text, dic):  
   for i, j in dic.items():  
     text = text.replace(i, j)  
   return text  
 # create a dictionary / hash to store the values to replace  
 # keys are the current words to replace and values are the new replacement words  
 #so the first word is replaced with the second word  
 dic = {  
 'wheelchair:':'wch_',  
 'wheelchair':'wch',  
 'surface':'surf',  
 'smoothness':'smth',  
 'inclination':'incl',  
 'capacity:disabled':'cap_dis',  
 'footway:left:':'fw_L_',  
 'footway:left.':'fw_L_',  
 'footway:right:':'fw_R_',  
 'footway:right.':'fw_R_',  
 'opening_hours':'open_hrs',  
 'addr:':'addr_',  
 'housenumber':'housnum',  
 'guided_tour':'guidtour'  
 }  
 # Here we open the osm file we want to update and prepare so that the shapefile we produce is happy  
 osmfile = open('map.osm', encoding='utf-8')  
 filein = osmfile.read()  
 # now create the new file that we will use for conversion  
 newfile = open('map2.osm', 'w', encoding='utf-8')  
 # write the output into the new file  
 newfile.write(replace_all(filein, dic))  
 #close the 2 open files  
 newfile.close()  
 osmfile.close()  

  1. Finally import the .osm file into PostGIS using osm2pgsql.exe
  2. Immediately EXPORT to shapefile with pgsql2shp.exe
wheeoowee   it should now be working...this all could be automated into one singel python script but I just haven't had the time to do it but when I do I'll post it up on www.openstreetmap.org and here on my blog.

later spatial geeks

No comments:

Post a Comment