Here is a worked example, from start to finish, showing how to create a map from OpenStreetMap data with the following features:
- urban area shading
- terrain shading
- heights in metres
- contour lines
- coastlines
- routing
The map is of part of Scotland including Perthshire. For the purpose of making a simple example, the bounds of the this map are on lines of longitude and latitude, from 3 to 5 degrees west and from 56 to 57 degrees north.
Requirements
This article assumes you have the appropriate version of makemap, the map creation tool, and have downloaded the coastline data and created a coastlines.makemap file to access it. If not please read How to Create CartoType maps first.
Getting the OpenStreetMap data
To get the data, go to www.openstreetmap.org, find Scotland on the map and choose 'Export', then 'Manually select a different area'. Set the bounds to -5 (west), 56 (south), -3 (east) and 57 (north), then click on 'Overpass API'. The data will arrive as a file called 'map'. Change its name to perthshire.osm and put it in your working directory.
Getting the elevation data
The easiest way to get elevation data for a relatively small area like this map, for which two one-degree tiles are needed, is to use http://rmw.recordist.com/. Fill in the minimum longitude as -5, the minimum latitude as 56, the maximum longitude as -3, and the maximum latitude as 57, choose SRTM 3 (World) from the 'Select product' dropdown menu, then click on 'Get available tiles'. You then need to click on the two links, download the zip files, and put the resulting files, N56W005.hgt and N56W004.hgt, in your working directory.
Creating contours
You can create contours from the elevation data using gdalbuildvrt and gdal_contour from the GDAL suite of free GIS utilities. If you're using Windows the easiest way to get gdal_contour is to install OSGeo4W.
First combine the HGT files into a virtual dataset (VRT file), to avoid artefacts where they abut:
gdalbuildvrt perthshire.vrt N56W004.hgt N56W005.hgt
Then create an ESRI shapefile containing the contours:
gdal_contour -a H -i 10 perthshire.vrt perthshire.contours.shp
The -a option tells gdal_contour to put the contour heights in an attribute called H. The -i option gives the contour interval in metres.
Now you'll need to create a file to tell makemap what to do with contour files. Create a file called contours.makemap, with the following text:
<?xml version="1.0" encoding="UTF-8"?>
<CartoTypeImportRules>
<file_type name='*.contours.shp'> <set name="_h" value='H+0'/> <commit layer='contour'/> </file_type> </CartoTypeImportRules>
The contour heights are put into a string attribute called '_h'; a leading underscore in the attribute name tells makemap not to put these values into the text index. The expression 'H+0' is used to create the height string; gdal_contour creates heights as string values to three decimal places. Adding zero to the string converts it into a number, which is then automatically converted back to a string in standard form, with no trailing zeroes.
For contours in feet rather than metres, assuming you need an interval of 25 feet, use the gdal_contour option -i 7.62 instead of -i 10, because 25 feet is exactly 7.62 metres. Then use import rules like this:
<?xml version="1.0" encoding="UTF-8"?>
<CartoTypeImportRules>
<file_type name='*.contours.shp'>
<set name="_h" value='H/0.3048'/>
<commit layer='contour'/>
</file_type>
</CartoTypeImportRules>
Note: recent versions of the makemap tool, from October 2023, have built-in rules to handle any file with the extension .contours.shp in the way given in the first set of rules above, rendering a contours.makemap file unnecessary.
The makemap command line
It is best to put the makemap command line in a batch file or script so that the options can be stored for re-use and modification. On Windows, for example, put the command line into a file called make-perthshire.bat, with the following contents:
makemap /project=osgb /driveonleft=yes /urbanareas=yes /extent=-5,56,-3,57 /usgs=. /terrain=height-metres /usgs=. perthshire-contours.makemap coastlines.makemap perthshire.osm perthshire.ctm1
This command line assumes that you have put the two HGT files in your working directory. If you have already downloaded a lot of them to a special directory, use that after /usgs= instead of the full stop indicating the working directory.
The options in the command line are:
- /project=osgb - use the Ordnance Survey of Great Britain projection
- /driveonleft=yes - the rule of the road in the UK is to drive on the left; omitting this option doesn't matter unless you need to display traffic information or other highlights on the driver's side of the road
- /urbanareas=yes - create shaded urban areas
- /extent=-5,56,-3,57 - the extent of the map in degrees, in the order west, south, east, north: that is, anticlockwise from the left
- /usgs=. - read the appropriate HGT files and create terrain shading from them
- /terrain=height-metres /usgs=. - read the HGT files again and store point heights in metres
- perthshire-contours.makemap - read the contour files that were created earlier
- coastlines.makemap - read the coastlines
- perthshire.osm - the main input file
- perthshire.ctm1 - the output file
Some important implicit options, which are of course unspecified, are
- /clip=yes - clip to the extent
- /lowreslayers=yes - create low-resolution layers for use at small scales, to improve performance
- /route=yes - create routing data
Now run the command, and you should get a map called perthshire.ctm1, somewhat larger than 60Mb.
Displaying the contours
If you load the map into the CartoType Maps App you will need a contour layer in the style sheet. The most recent version - from October 2023 - of the standard style sheet (standard.ctstyle) has a contour layer, but if you are using a style sheet that lacks it, you can add one. Here is a contour layer that displays 50-metre contours when zoomed out, and all contours when zoomed in, with labels only on the 50-metre contours. The color is mid-brown.
<scale max='100000'> <layer name='contour'> <scale min='50000'> <condition exp='(_h % 50) == 0'> <line fill='#C76300FF+white' width='0.4pt'/> <label priority='-10' font-size='6pt' color='#C76300FF' glow='white' glowWidth='7%,0.5pt' labelFormat='_h'/> </condition> </scale> <scale max='50000'> <condition exp='(_h % 50) == 0'> <line fill='#C76300FF+white' width='0.8pt'/> <label priority='-10' font-size='6pt' color='#C76300FF' glow='white' glowWidth='7%,0.5pt' labelFormat='_h'/> </condition> <condition exp='(_h % 50) != 0'> <line fill='#C76300FF+white' width='0.4pt'/> </condition> </scale> </layer> </scale>