Recent diary entries
(following on from this diary entry)
Supposing you would like to overlay a set of boundaries over the top of any existing map style - what would you need to do?
Using this as a reference, create a database to hold the new boundary data.
If a historical data file is what you want, download the data for the desired date and rename it to a file name that the “update_boundaries” script will recognise:
-rw-rw-r-- 1 renderaccount renderaccount 459723464 Nov 2 01:46 ukraine_2018-11-01T21:14:02Z.osm.pbf
You can also make other changes to this data if you wish using tools like osmium, osmfilter, osmosis, etc.
Modify this script to process your data.
Run the script to load the data that you have already downloaded:
sudo update_boundaries.sh current
Create a version of “mapnik.xml” (or whatever style file you are using) that looks in the database that you’ve loaded your boundary data into. In this case I just changed “dbname” references from “gis” to “gis3”.
Ensure that “/usr/local/etc/renderd.conf” knows about the new tile layer. The default one I use just has “ajt” in it; I created a copy of the last section, called it “ajt3” and changed URI and XML values.
[ajt3] URI=/hot3/ TILEDIR=/var/lib/mod_tile XML=/home/renderaccount/src/openstreetmap-carto/mapnik3.xml HOST=localhost TILESIZE=256 MAXZOOM=20
Restart renderd and apache2, and your new tiles will appear. Then in a simple Leaflet map add an overlay layer for your new tiles. This is an example that shows Leaflet overlays but there are many, many others, including on the main Leaflet site itself.
Here’s what it looks like:
It’s not perfect - there may be name label collisions between the two layers of data, especially as the labels from OSM Carto haven’t been removed (unlike with this style). It is however a very easy way to see boundaries corresponding to a particular viewpoint over the top of existing map tiles.
If you find downloading a processing OSM data too complicated, then you can just use the tiles I created for this example. An example tile is:
and the generic definition for a Leaflet overlay layer is:
Note - something like this approach to boundaries is something that’s been written about before. See for example this diary entry by PlaneMad from 2 years ago that replaced one set of boundaries in the data with another. This approach is I hope easier, although it doesn’t change the actual data used to create the main map tiles.
When I developed the map style that you can see here from OSM-carto one thing that I didn’t carry forward was the representation of borders. Partly this was because it’s not easy to separate maritime ones from non-maritime ones, the the purple maritime country borders frankly don’t look very nice:
Partly it was also due to “clutter” - I didn’t want an arbitary boundary to get in the way of a river or stream or other feature.
Sometimes however, it would be useful to see what borders are where, so why not do it as an overlay? This turned out to be rather easier than anticipated.
Firstly, a separate database was created (called “gis2”; by default an OSM Carto-based style will use “gis” as a database). That was set up as per the createdb section of the switch2osm guide. The reason for using a separate database was mainly to allow boundaries to be loaded independently of the rest of the data (and for a larger area if desired), but it would also allow different sets of boundaries to be loaded, if that was needed (some countries have legal requirements about how they are displayed on maps, and these may not match on-the-ground reality or the requirements of neighbouring countries).
The next job was to load some data into it. Normally I’d reload data using this script. For boundaries I created a version of that that used osmium, osmconvert and osmfilter to select only boundaries from the data and remove non-boundary tags that might render too.
After processing, the file with just boundaries in it was around 1/30 the size of the original file, so loading the second database with all of Europe’s boundaries wasn’t a problem.
Next the style that needed to be changed so that boundaries were displayed over transparent tiles. This was done by changing water-color and land-color in style.mss to “rgba(0,0,0,0)” in each case.
Finally and most importantly, the style needs to read data from “gis2” rather than “gis”, and that’s defined as the “dbname” in project.mml.
The results can be seen here. Select “Controls” and then “Boundaries” from the layer switcher to turn them on and off.
An example of a map without boundaries is:
and with is
Surprisingly, even though walking routes and boundaries are both labelled in purple, because boundaries are the only purple linear feature, there isn’t any real confusion between the two.
I’ve been wanting to write an explainer for this for a while (even before this diary comment). The problem was that I wasn’t aware of a Docker example that (a) was reasonably up to date and (b) was designed around tile serving (rather than style design for example).
However, this docker example was recently mentioned by its author on IRC. It’s based on the building a tile server for 18.04 instructions and also handles importing data and running the tile server afterwards.
First things first, I installed Centos 7 on a virtual machine. I got a “minimal” iso image for that from here. I installed it (which involved turning the network on inside the installer and selecting the disk to install on). I also set a root password and added a non-root user (I’ll use the example “renderaccount” below), and noted the IP address that it obtained. I did a “yum update” to install any available software updates.
There are a few sets of instructions for “installing Docker on Centos” - DigitalOcean have one, and there’s one here which also contains lots of other useful information. Following the instructions there:
su - yum install yum-utils device-mapper-persistent-data lvm2 wget yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install docker-ce systemctl start docker
If you then do this:
systemctl status docker
In the output you should see “active (running)”. Do this:
systemctl enable docker
in order to have docker start every time and then exit from root and do this from you’re non-root user:
sudo usermod -aG docker $USER
So that you can control docker from that non-root user. Log out and back in and do this:
docker container run hello-world
It should say “Hello from Docker!” to show that everything is working OK. If instead you see “permission denied” it probably means you haven’t logged out and back in again.
Next, we’ll follow the openstreetmap-tile-server Docker instructions here. In this example run-through I’ll download data for Zambia and import it, but any OSM .pbf file should work.
When logged in as our non-root user, download the data for Zambia into the root directory of the non-root user:
cd wget http://download.geofabrik.de/africa/zambia-latest.osm.pbf
Create a docker volume for the data:
docker volume create openstreetmap-data
And install it and import the data:
time docker run -v /home/renderaccount/zambia-latest.osm.pbf:/data.osm.pbf -v openstreetmap-data:/var/lib/postgresql/10/main overv/openstreetmap-tile-server import
Obviously “renderaccount” will need to be changed to the name of your non-root user.
How long this takes depends very much on the local network speed. The largest part of the download will probably be actually the land polygons that OSM’s standard style uses to differentiate land from sea; that file is a fixed size regardless of how large or how small the OSM data file you choose to import is (Zambia, used in this example, is relatively small).
One important thing to note - the path to the .osm.pbf must be the absolute path to the file; it can’t be a relative path. Also note that if something goes wrong the error messages may be somewhat cryptic - you might get “… is a directory” if the data file isn’t found. The “time” at the start of the command isn’t necessary for the installation and import; it just tells you how long it took for future reference.
For more details about what it’s actually doing, have a look at this file. You’ll see that it closely matches the “manually building a tile server” instructions, with some minor changes such as the tile URL and the internal account used. Internally you can see that it’s using Ubuntu 18.04, though you don’t need to interact with that directly.
When the import is complete you should see something like this:
Osm2pgsql took 500s overall real 157m54.159s user 0m2.098s sys 0m0.722s
That tells you how long things took in total (in this case 2.5 hours), and how much of that was spent import data (6 minutes). The second of these numbers is the rough time that it will take to import data again, since the big data files used by the OSM Carto style have already been downloaded.
To start the tile server running:
docker run -p 80:80 -v openstreetmap-data:/var/lib/postgresql/10/main -d overv/openstreetmap-tile-server run
and to check that it’s working, browse to:
You should see a map of the world in your browser.
For a simple “slippy map” we can use an html file “sample_leaflet.html” which is here in mod_tile’s “extra” folder. Just open that file in a web browser on the machine where you installed the docker. If that isn’t possible because you’re installing on a server without a local web browser, you can edit it to replace “127.0.0.1” with the IP address of the server and copy it to below “/var/www/html” on that server.
If you want to load a different area, just repeat the process from “wget” above. It’ll be quicker the next time because the static data needed by the map style won’t be needed.
If you’re not using Centos
Centos was chosen above mainly because the “mod_tile” software isn’t adapted to run there natively. If using Ubuntu 18.04, you can follow some instructions from DigitalOcean here, or you can install it using “apt”. From a non-root account that has access to “sudo” do this:
sudo add-apt-repository universe sudo apt update sudo apt install docker.io sudo usermod -aG docker $USER
then logout and back in again and:
docker run hello-world
and continue from that stage above.
Thanks to the authors of all the guides linked to above, especially the Alexander Overvoorde’s “openstreetmap-tile-server” repository Dockerfile in it, and the (many) original authors of the “building a tile server” instructions.
I’m in the process of changing map.atownsend.org.uk so that zoom level 13 can still be used as a “route planning” layer but walls, hedges and ditches don’t get in the way. This wasn’t originally a problem, but people have since mapped lots of fences, hedges,walls and ditches, and it can be difficult to see footpaths at that zoom level now. Here’s a screen showing half new tiles, half old ones:
That corresponds to here on the site and here in OSM. The new version will probably be rolled out in a week or so’s time. Other zoom levels will be unchanged - you’ll still see hedges and ditches a couple of zoom levels earlier than with OSM’s “standard” style, and paths will still be legible 2 or 3 zoom levels earlier.
Although Ubuntu 18.04 (“Bionic Beaver”) isn’t released yet, it’s due out fairly soon and daily builds can be downloaded from here. There are actually very few changes from the 16.04 version - mostly just updated versions of software (including some Mapnik fixes). Following these instructions shouldn’t take more than a couple of hours for small areas - the longest period of the setup is waiting for the shapefiles used by the style to download.
As before, the page is designed to be “the least you need to do” to get a rendering server working. As before I also wrote a wiki page which goes into a bit more detail, including other things that you might want to do.
It’s also worth mentioning than there are many more resources available now than there were a couple of years ago - see for example Ircama’s tutorials, and also this guide that covers the setup of an OSM Carto renderer within Docker.
Yesterday was a nice day, so I decided to walk from Derby to Alfreton (roughly here). The criteria were pretty simple:
- No muddy paths
- Only roads with footpaths alongside (sidewalks in OSM terms), or if necessary, grass verges (or very minor roads)
- Somewhere to stop for something decent to drink and a bite to eat.
Ignoring “automatic routing” altogether, what map provider in the UK has that data? OSM does (at least in the area that I’m interested in). Google sort-of does - I’m sticking to roads here, and via their StreetView I can see that e.g. Codnor Denby Lane does have somewhere to safely walk, but it’s not really practical to “virtually walk” an entire route in Google’s StreetView to check it before setting off. HERE has some aerial imagery but not with enough detail. The UK’s Ordnance Survey surely has most of the data, but getting at it is hard (even if you pay them money). The small map on this page can be zoomed in to hint at sidewalk info, but neither the buyable OS Explorer map (which I have a copy of) nor this page which I presume is based on OS OpenData, do. Bing can show basic road info and their own or OS Explorer’s map style, but no “is this walkable” information.
With regard to POI data, Google was (until yesterday) the only one that had the correct name for this pub, and does link through to food and beer details (even CAMRA, usually the go-to guide for this sort of thing, are out of date). However, there’s no differentiation on the map beyond a “place that serves food” icon and a mousover blurb (“family friendly chain pub and restaurant”).
So am I missing something - is there anyone out there with this level of data that’s available in an accessible format, other than OSM?
There’s a discussion over on talk about contributions to OSM’s Standard map style. This diary entry explains what I did in order for a change to fix a problem with bus guideways that was visible in that style. It’s provided here so that hopefully it can help more people that want to (but don’t necessarily know how to) to contribute.
The first thing I did was log an issue for the problem that needed to be fixed. As well as describing the problem that also outlined the fix (actually I referenced some code in a different map style where I’d already fixed the problem). The initial discussion on the issue was helpful in that other people said that yes, they thought that it was a problem too.
However, describing the problem is only part of the way towards actually fixing it. In order to do that, I started by reading the “contributing” guidelines and the links from there.
I already had a github account. I forked OSM Carto into my area to create this. Within there, I created a new branch “guideways_low_zoom” (since deleted) just by typing the name in into the github UI.
I already had a virtual machine running Ubuntu 16.04.3 LTS (server) with all the pre-requisites in place. I’d set it up as per the switch2osm guide, but mainly use it for developing a different map style based on an older version of OSM Carto. Another option is to follow the recommendation in the OSM Carto repository and use Docker.
I then had to “git clone” my forked repository to set it up on that machine, and I then did:
git fetch --all git checkout --track origin/guideways_low_zoom
to get the correct branch there.
In order to actually get the vanilla copy of OSM Carto working, I had to follow the instructions in the “Shapefile download” section of the switch2osm instructions (essentially running “scripts/get-shapefiles.py”).
I then created a shell script to load a small section of data, similar to this script which I use for my own map style, but with slightly different osm2pgql parameters as specified both in the “switch2osm” guide and also OSM Carto’s “install” guide.
The next thing to do was the actual code change. 2 files were affected, as can be seen here. The “project.mml” file decides what data is sent through to each layer and the “roads.mss” file contains the layer that we’re interested in (“guideways”).
There’s one change to “project.mml” - reduce the minimum zoom that’s sent through to the “guideways” layer from 13 to 11.
There are two changes to “roads.mss”. The existing code just contained “[zoom >= 13]”, so I added a new section for “[zoom >= 11][zoom < 13]” based on the equivalent zoom railways code.
I also changed the colour slightly from “#6666ff;” to “#6699ff;”, and used the much maligned w3schools to “nudge” the colour in the direction that I wanted to go. The reason for the colour change was to make the bus guideway blue at zoom 13 less “in your face” at that zoom level; it previously dominated the view of that area. Colours need to be varied with line width to balance the overall visual impact.
In order to test the change locally I used a variant of a script that I already had, changed just to get the latest version of the OSM Carto style, reload it, restart renderd and apache2 and remove previously rendered map tiles. To bypass the browser cache of tiles I used “shift reload” to fetch tiles from the server.
I had to tweak both the line width at the new lower zooms and also the colour until I was happy with both. Once that was done I checked my changes into my repository (“git checkin” with a sensible description and then “git push”) and created a pull request via “New pull request” in the github UI. This created this pull reqest.
What I should have done next was upload examples of the new rendering in the discussion of the new pull request. I’d actually already added them to the original issue instead.
I then answered a couple of questions about the change. On the original issue, I tried to explain why treating bus guideways as trams was not a good idea (they’re similar forms of transport but used very differently in OSM). Also on the pull request I explained why the new guideway rendering should be handled by “[zoom >= 11][zoom < 13]” rather than just “[zoom >= 11]”. The inclusion of that code was actually accidental (it had come from the railways low zoom section) but a check of the resultant mapnik.xml showed that it was smaller with “[zoom >= 11][zoom < 13]” so I kept that version.
The code was then merged within a few days and I deleted the local branch that I’d created and did a “git checkout master” to switch to the master branch again.
In order to keep my copy of OSM Carto up to date with changes that were made subsequently, I needed to do this:
git remote add upstream https://github.com/gravitystorm/openstreetmap-carto git fetch upstream git checkout master git rebase upstream/master git push -f origin master
In github it now says “This branch is even with gravitystorm:master.”, so the whole process can now be repeated for the next change.
I’ve just noticed that this page exists - those tutorials are really useful so if you’ve read this far I’d definitely read that too.
I’ve finally got a reasonable rendering of linear barriers working - like the cattle grid in this picture:
The key to getting it working was to ensure that the width of lines used at high zooms mostly matched the real width of the feature on the map (see here for cattle grids), except for gates and stiles which are designed to stand out slightly. Walls and fences are slightly different, allowing you to tell them apart.
It’s been possible to run Linux software on Windows for some time using Microsoft’s “Windows Subsystem for Linux”. Here’s what needs to be done to run a simple tile server there, based on the existing instructions here .
Firstly, install “Bash on Ubuntu on Windows”. There’s are some intructions here (but don’t worry where that says “This won’t work with server software”). Continue down to where it says “You’ll be asked to create a user account and password for use in the Bash environment”. It’s easiest if that user account is the one that you use in the rest of the switch2osm instructions.
Once installed, at a shell prompt “lsb_release -a” should say:
No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.3 LTS Release: 16.04 Codename: xenial
What you get is surprisingly similar to a standard Ubuntu server machine. Some things don’t work (e.g. “screen”), and you’ll have to manually start some of the services that will need, but otherwise things are very familiar.
Run “sudo apt update” and “sudo apt upgrade” to upgrade to the latest version of everything.
Next, go over to the switch2osm instructions and follow those as normal, except for the caveats pointed out below:
If you want to ssh in (you probably will) you’ll need to “sudo service ssh start”.
You’ll likely want to allow access to ports 22 (for ssh) and 80 (for http) and possibly others at the Windows Firewall (inbound rules / new rule / port / tcp port 80 / allow / all / “name”).
After installing postgresql but before doing e.g. “createuser renderaccount” you’ll need to start postgresql manually. “sudo service postgresql status” will say “down”, but after “sudo service postgresql start” it will say “Starting PostgreSQL 9.5 database server” and “service postgresql status” will then say “9.5/main (port 5432): online”.
Where the switch2osm instructions say “service apache2 reload” you’ll need to do two things. One is to work around a “Protocol not available: AH00076: Failed to enable APR_TCP_DEFER_ACCEPT” error that is described here, and the solution is to add “AcceptFilter http none” to the end of the /etc/apache2/apache2.conf file, and the other is to start Apache2 manually via “sudo service apache2 start”.
Pointing a web browser at http://yourserveraddress/ should display an Ubuntu Apache “It works” page. If it doesn’t, check firewall access and any error messages displayed when trying to start apache.
Before you run “renderd -f -c /usr/local/etc/renderd.conf” you’ll need to ensure that postgresql and apache2 are both started (they’d start automatically on Ubuntu but not here). Requests are passed from Apache and mod_tile to renderd, and here’s an example of what you might get (this is with Hereford, an English county, loaded):
There’s a suggestion here to use UTF8 in the createdb when setting up a tile server on Windows 10 this way. I didn’t notice any issues without it, but my example above doesn’t need any non-Latin names.
A previous diary entry explains how I created a basic map legend for a map that I maintain that highlights various things common near me that tend not to get shown very well elsewhere - public footpaths, hiking trails, offices, that sort of thing. It struck me that a lot more things had names than almost any other map (other than OSM Bright) actually shows.
I therefore went through a process of looking to see what tags people used names with (it’s almost everything - here’s a named cattle grid), and what they used as the “naming tag” for various things (mostly “name”, obviously). The result is here:
although to get a better idea of things click here and zoom around.
Why might you want to do this?
You might want to set up a rendering server for a short period of time, or you might want a server that has lots of memory while you’re importing data, but much less afterwards. An “always on” Azure server will probably cost more that a comparable VPS somewhere else, but if you only want it for an hour or two at a time, it may cost considerably less.
This page describes using Microsoft Azure to do this, but of course other cloud providers are available, and depending on what you want to do may be better suited to your needs.
I have no commercial relationship with Microsoft (beyond occasionally buying hardware with Windows preinstalled and then later removing it) and this isn’t a “recommendation”, beyond providing another option to setting up a server yourself.
Sign up to Azure
If you haven’t already got one that you want to use, create a Microsoft account. Jump through whatever validation hoops you have to (for me that was an email address or a phone number, but this may vary depending on where you are).
Next, go to portal.azure.com and sign in. There will probably be a few “free trial” buttons around; click one of them to get a 30-day trial of up to £150 / $200. You’ll need to provide the Microsoft account details (from above), a phone number (again) and a credit card. If you’re in Germany and want to keep your data there see here.
Create a virtual machine
This page is a good starting point. You’ll want to install the Azure CLI because it’s a lot less fiddly than than the alternatives, though there is a “Cloud Shell” option in the portal (actually that’s an account on a remote Ubuntu 16.04.2 LTS VM!) and a “clicky pointy” interface in there too.
First, create a “resource group” to tie everything associated with this machine together, and make it easier to tidy up later. I created this in “uk south”, you can pick somewhere closed to you:
az group create -n MyResourceGroup -l uksouth
If you already have a public key associated with the account that you are running “az” from (typically $HOME/.ssh/id_rsa.pub) then:
az vm create -n MyVM -g MyResourceGroup --image UbuntuLTS --data-disk-sizes-gb 20
az vm create -n MyVM -g MyResourceGroup --image UbuntuLTS --data-disk-sizes-gb 20 --generate-ssh-keys
to create them and create a remote machine. If you’ve generated ssh keys in Cloud Shell you’ll want to store them locally and use them later for access, otherwise you won’t be able to log in again.
That’ll get a a “default sized machine” - you can easily change it later if you want to. Allow access in on ports 80,443 and 22:
az vm open-port --port 80 --resource-group MyResourceGroup --name MyVM az vm open-port --port 443 --resource-group MyResourceGroup --name MyVM --priority 901 az vm open-port --port 22 --resource-group MyResourceGroup --name MyVM --priority 902
Click “Virtual Machines” in the portal - you can see the IP address to connect to there.
At this point you can head over to the switch2osm instructions and follow those.
Once complete, come back to the portal and click “Virtual Machines” at the left. Click the name of the machine you just created, and then “public IP address” at the right. That’ll allow you to type in a personal DNS name (perhaps “mynameswitch2osm”), and the FQDN will consist of that plus “.azureregion.cloudapp.azure.com”, for example “mynameswitch2osm.uksouth.cloudapp.azure.com”.
If you have control of a DNS you can set up a CNAME record so that the name that you want to refer to the server as (e.g. “myname.mydomain.com” points at “mynameswitch2osm.uksouth.cloudapp.azure.com”), and you can create a certificate for “myname.mydomain.com” using “letsencrypt” if you want to.
When you’ve finished using the server, stop it from the portal (click the three dots to the right of the server name). In the portal the server will change from “running” to “deallocating” and then “Stopped (deallocated)”.
To start it again click the three dots and then “Start” - it’ll take a couple of minutes to start up (you may need to wait a minute or so after it has started before yo can ssh in).
When you want to completely delete the VM and everything associated with it, click “Resource Groups” in the portal, click the resource group you created at the top of this process and then “delete” at the top right. You’ll need to type in the resource group name as confirmation to delete it.
There’s recently been a thread on the talk-gb mailing list where someone has decided that, despite previous custom and practice there, the “name” field in both English- and Welsh-speaking areas of Wales should be a compound of both the English and Welsh names. No-one says “I’m climbing up Snowdon / Yr Wyddfa today”, they’ll use one name or the other, not both together.
In the Welsh-speaking areas the Welsh names are more likely to be used; in the English-speaking areas the English names. It’s not a hard-and-fast rule; this peak in the Black Mountains is referred to about equally by both the Welsh and English names, despite it being in a predominantly English-speaking area.
Wikipedia gives an idea of Welsh-language take-up here. That’s a bit broad-brush; for example I don’t think there’s an isogloss between Carmerthenshire and Swansea where people gain/lose the ability to speak Welsh.
So how is it possible to extract data from OSM with the Welsh name in the Welsh-speaking areas and the English name in English-speaking ones, both when creating e.g. a rendering database for the first time and when updating it as people update OSM? Firstly we’ll just consider the “loading the database” part.
Very roughly, the Welsh-speaking area of Wales corresponds to this area. That’s not perfect, but it’s not a bad approximation for a rectangle. I downloaded the latest Welsh data from Geofabrik and cut that area out of it:
osmosis --read-pbf wales-latest.osm.pbf --bounding-box left=-4.82 bottom=52.02 right=-3.34 top=53.69 --write-pbf wales_cy_before.pbf
Convert the “Welsh-speaking” part to names based on “name:cy”:
osmosis --read-pbf wales_cy_before.pbf --tag-transform transform_cy.xml --write-pbf wales_cy_after.pbf
Create a copy of the larger file with names based on “name:en”:
osmosis --read-pbf wales-latest.osm.pbf --tag-transform transform_en.xml --write-pbf wales_en_latest.pbf
Merge the two together (do it this way around and the “Welsh” file seems to take precedence):
osmosis --read-pbf wales_cy_after.pbf --read-pbf wales_en_latest.pbf --merge --write-pbf wales_merged.pbf
osm2pgsql --create --slim -d gis -C 2500 --number-processes 2 -S openstreetmap-carto.style --multi-geometry --tag-transform-script ~/src/SomeoneElse-style/style.lua wales_merged.pbf
The “osm2pgsql” command to use obviously varies depending on the data and the style used; I’m using this lua tag transform (that’s unrelated to the “osmosis” tag transforms described above) and this map style.
Edit: There’s an automatic script to do this (for the style I use) here. I’ve updated that to use a .poly file (thanks to SK53 for that). Interestingly that includes St Davids in the “Welsh” part - so Glasfryn Road is now “Ffordd Glasfryn”! I’ve also used Scots Gaelic names for the far northwest of Scotland, and the results can be seen here
This means that it should be possible to follow these instructions to set up a tileserver from scratch that creates tiles in the same style as OpenStreetMap’s “standard” style in just a few hours (for small areas the longest period of the setup is waiting for the shapefiles used by the style to download).
What would be really useful would be if people could test that these notes do actually work for them - is there anything that should be made clearer, especially to someone who might not be familiar with Linux at all?
I’ve created a map legend for the map style that I use. It’s a set of map data that can be appended to a rendering database to create a map legend in a blank bit of map (actually in the middle of Australia).
There are currently two parts - linear features and POIs. As far as the map is concerned these are “real POIs” (though they’re never added to OSM itself of course - just added to the rendering database) so you need to zoom in to see some of the POIs such as the one for vending machines, which only appears in this map style from zoom level 19. You could use it with other map styles, but some of the features are dependent on this lua script.
Here’s a preview of what the “roads” part of the legend looks like:
but to use it properly follow the link and move around.
However, sometimes zoom level 20 isn’t enough. Here:
is part of Nottingham at zoom level 20. At least one of the office names doesn’t appear (it corresponds to here in OSM). The problem is that the way that the “standard” renderd stores metatiles means that only a certain number of tiles can be stored for each zoom level (see this list post for the details). In order to store more I changed renderd slightly so that more zoom levels can be stored - see here and here for the details.
Rendering works fine at higher zoom levels (up to 28 in my example) so that all of those office names now appear. Here’s the same area at zoom level 21:
The principle could be extended to an eventual goal of 1:1 to keep Melchett and Darling happy (roughly zoom level 32 at this latitude) but that seems unnecessary even to me currently.
Because of the way that relations are handled within osm2pgsql, converting route relations into “just another highway type” is pretty straightforward, and once created that new “highway=ldpnwn” can be added to the stylesheet.
In this case the two things to think about are the fill and the text. The “fill” is a short wide purple dot separated by a long gap from the next one. In the code (see the links above) at “line-dasharray” the “1” says “short and the “60” says “separated by a long gap” and further down the “line-width: 4” says “wide”.
The text for most names in the stylesheet is handled in one place. Long distance paths have to be different to distinguish them from road names, and so the text fill is purple, the text-dy larger to place it further from the road and text-spacing is further apart at higher zoom levels.
The big advantage of handling relations “just like any other road” is that all the clever Mapnik stuff “just works” - like text going around corners:
On many occasions in the past I’ve said “it’s really easy to create your own Garmin maps” but I don’t think I’ve ever documented the procedure. This is an attempt to do that.
You’ve got some sort of Garmin device with an SD card in it with some maps that you’ve downloaded from somewhere on it.
You want to replace those with a map you’ve created yourself.
You’ve got a PC with around enough memory in it. The one I used for the examples below had 4Gb; it’s possible that less may be needed for a small file such as the one used in the examples below.
All the path examples below for for Windows (actually tested on Windows 7), but it should be relatively straightforward to adapt them to work on other operating systems.
What you need to do
The easiest way to create Garmin maps from OSM data is to use “mkgmap”. That’s available from:
The download page for the latest mkgmap is http://www.mkgmap.org.uk/download/mkgmap.html and the current version is “3676”.
Unzip the zip file and move the folders intact to a known location. In my case I moved it so that “mkgmap.jar” file was in: C:\Utils\mkgmap-r3676
I didn’t use a path with a space in it or a path that Windows recognises as “special” to avoid any possible confusion later.
“Splitter” is a separate program used to split a large OSM data file into portions small enough for mkgmap to work with (the resultant Garmin map can still route between portions).
The latest Splitter is here: http://www.mkgmap.org.uk/download/splitter.html and the current version is “437”.
Unzip the zip file and move the folders intact to a known location. In my case I moved it so that splitter.jar was in: C:\Utils\splitter-r437
Next, we need to download an OSM extract to use to create maps from. As an example I’ll use Romania, and extract for which can be downloaded from here:
That page currently says:
romania-latest.osm.pbf, suitable for Osmium, Osmosis, imposm, osm2pgsql, mkgmap, and others. This file was last modified 7 hours ago and contains all OSM data up to 2016-05-13T19:45:03Z. File size: 146 MB; MD5 sum: b0554ae9632cc6c2be1c1e3525b5dcb5.
After downloading, check that the file is intact:
md5sum romania-latest.osm.pbf b0554ae9632cc6c2be1c1e3525b5dcb5 *romania-latest.osm.pbf
(see links from https://en.wikipedia.org/wiki/Md5sum for where to get an “md5sum” program from if you don’t already have one)
That matches so we can continue.
Create a directory to work in - in my case I created “D:\doc\gps\romania” and copied romania-latest.osm.pbf to it.
From a command prompt (on Windows), change the current directory to be where the downloaded .pbf file is.
d: cd \doc\gps\romania
See what version of “java” you have installed. Type “java -version” at the command prompt to find out. In my case that says:
java version “1.8.0_91” Java(TM) SE Runtime Environment (build 1.8.0_91-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
so Java is already installed. If you don’t already have Java installed download and install from somewhere like: http://java.com/en/download/windows_xpi.jsp
Next, run splitter. The “-Xmx1200m” tells it how much memory to allocate; the “–max-nodes” how big to make each split piece. The examples for the parameters given here should “just work”:
java -Xmx1200m -jar c:\utils\splitter-r437\splitter.jar romania-latest.osm.pbf --max-nodes=800000 --output=xml
That should create lots of “.osm.gz” files. Then run mkgmap. Here “–style” determines the style of map to create - “default” is actually a folder containing several files that make up that style. Unsurprisingly the style called “default” is the default mkgmap style - not particularly optimised for foot, bicycle or car use.
java -Xmx1200M -jar C:\Utils\mkgmap-r3676\mkgmap.jar --style-file=C:\Utils\mkgmap-r3676\examples\styles\default --route --gmapsupp *.osm.gz
When that finishes it should say something like “Total time taken: 621133ms” (i.e. about 10 minutes on a fairly slow PC for a country that is relatively small in OSM terms).
d:\doc\gps\romania: -rw-rw-rw- 1 A.Townsend None 123359232 05-14 13:31 gmapsupp.img -rw-rw-rw- 1 A.Townsend None 4270 05-14 13:31 osmmap.tdb -rw-rw-rw- 1 A.Townsend None 73728 05-14 13:31 osmmap.img
Create a subdirectory and move those files into there for safekeeping:
d:\doc\gps\romania\default: -rw-rw-rw- 1 A.Townsend None 123359232 05-14 13:31 gmapsupp.img -rw-rw-rw- 1 A.Townsend None 73728 05-14 13:31 osmmap.img -rw-rw-rw- 1 A.Townsend None 4270 05-14 13:31 osmmap.tdb
Copy those files to the GPS. The method to do this varies by device. I’d expect that people reading this will already do this with files they’ve downloaded from elsewhere; if not there are lots of examples on places such as http://help.openstreetmap.org.
When it’s copied across, turn on the GPS and check that the new map is visible.
Next, how to change the style slightly?
In C:\Utils\mkgmap-r3676\examples\styles, take a copy of the “default” folder and call it something like “mystyle”. We’ll leave “default” as it was and make a simple change to “mystyle”. As a test we’re going to make tracks appear like unclassified roads.
Edit c:\Utils\mkgmap-r3676\examples\styles\mystyle\lines in a text editor. The “lines” file is the one that deals with linear items - things such as roads.
Here’s the line in that file that deals with unclassified roads:
highway=unclassified [0x06 road_class=0 road_speed=3 resolution 21]
It’s pretty straightforward what is happening - the OSM feature at the left (“highway=unclassified”) is to be transformed into the Garmin feature at the right (“0x06”).
Here’s the line that deals with tracks:
highway=track [0x0a road_class=0 road_speed=1 resolution 22]
change the latter line to:
highway=track [0x06 road_class=0 road_speed=3 resolution 21]
(i.e. so that “highway=track” is treated as if it was “highway=unclassified”)
Rerun mkgmap with the new style:
java -Xmx1200M -jar C:\Utils\mkgmap-r3676\mkgmap.jar --style-file=C:\Utils\mkgmap-r3676\examples\styles\mystyle --route --gmapsupp *.osm.gz
Create somewhere safe to store the new files, and put them there:
d:\doc\gps\romania\mystyle: -rw-rw-rw- 1 A.Townsend None 123338752 05-14 14:23 gmapsupp.img -rw-rw-rw- 1 A.Townsend None 73728 05-14 14:23 osmmap.img -rw-rw-rw- 1 A.Townsend None 4270 05-14 14:23 osmmap.tdb
Copy to the GPS again, and check that tracks do indeed appear as roads.
… and that’s it.
Obviously there are many more changes that can be made. There’s quite a lot of information on the OSM wiki at places such as http://wiki.openstreetmap.org/wiki/Mkgmap/help .
The resulting example “default” files can be found at this link:
The resulting example “mystyle” files can be found at this link:
A while back I described how I was showing tree types in woodland. The “unfinished business” there was “what about forest areas where the trees have been cleared?”. Mapping of that is a bit hit and miss. “Forestry” has been suggested, but doesn’t have many takers, and “forest” is actually often used for “the entire forestry area” (at least where I’m interested in rendering tiles for - I suspect it varies considerably worldwide). The wiki page and the standard style rendering discussion don’t distinguish, but I thought it was worth trying to separate out “natural=wood” and “landuse=forest” where the latter is used for “the entire forestry area, including where there are currently no trees”.
Here’s the result:
That corresponds to here in OSM’s standard style. The dark green bit corresponds to “trees” (natural=wood; if there’s a surveyed leaftype then obviously that is shown too). The lighter green bit means “forest, but no trees” (landuse=forest - the lighter green is only visible if there’s no natural=wood also there). The forest and wood colours are defined here; here is the leaf_type handling in the stylesheet and here is where the natural and landuse tags are checked to see whether the current object should be treated as “trees with a known leaf type”, “trees without a known leaf type” or “forest, but not necessarily trees”.
(or if you’re English, “Pavements!”)
I finally got this working for tertiary and secondary roads:
That location corresponds to here in OSM.
There were three bits to it:
1) Determining which roads should have a sidewalk rendered. This is done in lua, and creates e.g. a road type “tertiary_sidewalk” to go with “tertiary” and “tertiary_link”:
2) Handle “tertiary_link” the same as “tertiary” in the style’s MML, e.g.:
3) Handle “tertiary_link” the same as “tertiary” in the style’s roads.mss, e.g.:
… except where we want to do something different:
“sidewalk_width-z13” etc. are declared at the top:
There’s scope for further tinkering, and I’ve yet to see how usable it is on a small mobile phone screen in poor light, but it looks OK so far…
As you may be aware, mapping of areas of trees in OSM is complicated. It’s not possible to tell just by looking at the data which of the four(!) approaches described on that page someone is using “natural=wood” and/or “landuse=forest” to mean. It therefore didn’t make a lot of sense to me to display them differently on a map created from OSM data.
Last year there was a proposal to record “leaf_type” and “leaf_cycle” separately, which makes sense (though the wider range of non-European tree types doesn’t seem to be catered for as well as previously. Unfortunately a previous version of that page suggested that “wood=deciduous” should be replaced by “leaf_type=broadleaved”, and a no doubt well-meaning non-local mapper decided to change some areas of mainly deciduous woodland to “leaf_type”. Whilst some of these were correct, clearly there are some issues with this, but as I was changing some that I did have local knowledge of, the thing that mainly struck me was that the situation on the ground was far more complicated than previously mapped, or rendered, on OpenStreetMap. I therefore decided to start trying to record “leaf_type” and (when there was enough data, render it. Initial results can be seen here: That location corresponds to here in OSM. There’s a lot more to do there, but at least there’s a bit more detail than “a large area of trees”.
That rendering is created by a combination of this lua script at osm2pgsql data import time and this stylesheet. It’s primarily designed for showing England-and-Wales-specific rights of way, but trees seemed like a natural extension.