Contour lines from other Sources

From OpenStreetMap Wiki
Jump to navigation Jump to search

This page describes by example how to transform an ESRI shapefile containing contour data into a garmin img file.

While SRTM data cover a vast area and are good starting point, they have shortcomings: some areas aren't covered at all, the level of detail (especially outside the US) could be better, and there are sometimes gaps in the data where clouds have obscured the view of the earth's surface. But SRTM data aren't the only source of terrain data, and it's quite feasible to make use of other data sources, if you know how to. I've gone through using some possible sources, and I'll describe what I had to do to get the data all the way from the source to my GPS unit. My methods may or may not work for you; your chances are best if your starting point is similar. I'm working on a Linux system (Kubuntu 11.4 on intel 32bit) and my GPS unit is a Garmin Etrex Vista hcx. If your environment is different, your mileage will vary, but I hope my process is reasonably portable.

Data sources

To get data for contour lines, there are two levels of data to start from. The most basic level is an actual 'DEM', a digital elevation model. DEMs are raster data, meaning that they consist of a set of elevation measurements along a grid. The data formats are typically trivial and well-understood by free tools. A good tool to work with DEM data is QGIS - it has plugins to create contour lines directly from DEM data without much fuss. You can also create the contour lines by using gdal_contour, one of the command line tools from the gdal toolset, which is free and available for several platforms. While I won't explain how to use these tools, it's important to note that the resulting contour lines will be in a specific format: ESRI shapefiles.

This takes us to the second source for contours - you might get readymade contour lines as, for example, shapefiles. My reason for developing this particular workflow was that I have discovered (on top of DEM data, which are also available) readymade contour shapefiles for my area of interest, the Piedmont in Italy. I'll start my detailed description from a shapefile, and if you want to follow it, you may want to download some data to play with. You can browse the available datasets for the Piedmont here:

http://www.dati.piemonte.it/dato/item/100290-ctrn-vettoriale-1-10-000-1991-2005-singole-sezioni-cc-by-.html

These files are zip files and contain other (very intersting) data as well. You'll have to accept their license. I'll assume you just want the data for your own GPS unit, which is certainly permissible. Just pick any of these files and download them - best pick one from a mountainous area.

Shapefiles aren't the only possible vector data source in my workflow, since the tool I'm using to import the data into OSM will process all OGR-compatible data, but I haven't tried any other source data types, and ESRI shapefiles are very common, so it's quite likely you'll find them rather than anything else.

From Shapefiles to OSM

Shapefiles store the attributes of the geometrical entities they contain in a simple database format, where the data are kept in records which have a predefined structure. This structure would define several fields which would contain specific values for every record. It's like a table: you might have fields 'type' and 'height', and a record would contain, say the pair of values 'majour contour' and '1000'. This storage scheme is different from the one OSM uses - OSM stores an unspecified number of key/value pairs with each geometrical entity, so there is no fixed record structure. This looks like a problem, but the fixed record structure can easily be converted into a key/value scheme, which is actually more flexible. And there is a readymade tool for it: ogr2osm, see

Ogr2osm

You'll need this tool, so download a version that suits you.

Let's assume you have downloaded ogr2osm as ~/src/ogr2osm/ogr2osm.py And let's also assume you have picked a packet of CTRN data and unpacked it in the present working directory - I'll assume you've picked CTRN_s052140.zip for this example.

The shapefiles containing the contour data are the ones ending in l_arc.*, and to convert them to an OSM file, you can simply call ogr2osm without any 'advanced' parameters:

~/src/ogr2osm/ogr2osm.py CTRN_s052140l_arc.shp

A Strange OSM File

The result is an OSM file called CTRN_s052140l_arc.osm, and we'll have a brief look at it to see what the translation from the shapefile's database format to OSM has produced. If you open the OSM file in a normal text editor and scoll down a good way, you'll see how the ways in the OSM file have tags like these:

<tag k="TNODE_" v="1253" />
<tag k="ENT_LIN" v="2.08.02" />
<tag k="TIPO" v="1.08.02" />
<tag k="RPOLY_" v="271" />
<tag k="LPOLY_" v="271" />
<tag k="FNODE_" v="1339" />
<tag k="QUOTA" v=" 1720.00" />
<tag k="LENGTH" v="    890.98168177800" />
<tag k="COD" v="" />
<tag k="S052140L_" v="1249" />
<tag k="S052140L_I" v="3075" />

The data we're interested in are the tag 'ENT_LIN', which codes the type of the line in question, and the field 'QUOTA', which contains it's height. Now this is quite different to the way OSM usually codes contours, which uses the tags 'ele', 'elevation' and 'elevation_ext', but as it turns out we don't need to follow the standard OSM way to get contours for our GPS unit. I'll nevertheless hint at the possibility of editing shapefiles, there are tools to do this quite easily - either manually, for example in QGIS, or script-driven in python with the pyshape module.

So how do we proceed? We use a 'style' and mkgmap. In the style we can write specifications on what style of symbol we want to have for specific geometric entities. It's probably easiest if I just give an example here - the most important bit for now is the 'lines' file inside the style folder, all the other files can be left at their defaults or omitted. So here's a lines file for the specific case:

# only major and medium lines receive a name. Note the conversion to feet.
ENT_LIN=2.08.01 & ( QUOTA ~ '.*[05]00\.0+' )
 { name '${QUOTA|conv:m=>ft}' } [0x22 level 2]
ENT_LIN=2.08.01 & ( QUOTA ~ '.*[05]0\.0+' )
 { name '${QUOTA|conv:m=>ft}' } [0x21 level 1]
# any remaining contours will be rendered as minor, without name
ENT_LIN=2.08.01 [0x20 level 0]
ENT_LIN=2.08.02 [0x20 level 0]

This line style defines major, medium and minor contours, based on the data found in the OSM file. As it turns out, we don't need the standard OSM tags 'ele' etc. at all!

Making an image file

So now we're ready to feed the data into mkgmap. Let's assume you've got the style's directory in your present working directory, and it's called 'contours'. Apart from the 'lines' file above, it really only needs the 'version' file (containing a single line with the character '0'). Let's assume you have mkgmap.jar in ~/src. Here's the call:

java -jar ~/src/mkgmap-r2179/mkgmap.jar --mapname=88052140 --description="Höhenlinien Piemont" --country-name="Italia" --region-name="Piemonte" --style-file=contours --show-profiles=1 --draw-priority=10000 --transparent CTRN_s052140l_arc.osm

Quite a mouthful, but most of the parameters are just for bookkeeping. Once mkgmap has finished, you should have a garmin image file called 88052140.img in your present working directory.

The resulting image file is now ready to be combined with other data to form the final gmapsupp.img file to load into the GPS unit. If you want to take a look beforehand, you can make a tdb file with mkgmap and have a look at the data with QLandkarteGT. You can also make a gmapsupp.img just from the contour data, but it won't show the different types of contour lines differently, unless you use a .TYP file and pass the .TYP file's family-id to the mkgmap call.

I'll end this description here and leave you to continue as described elsewhere.