Images on this page contains OS data © Crown Copyright (2021), used under the Open Government License
Some years ago, in 2018, a relative of mine mentioned in passing that they’d quite like a 3D model of the area where they live, as it’s geographically complex and hard to get a sense for from ground level.
In a classic case of nerd-sniping, I thought to myself that surely this must be achievable, what with the availability of open-source mapping products, and so began a slow-burning side project which I’ve moved along in fits and starts around birthdays and Christmases for the past few years.
tl;dr: The source code for the tool I’ve written can be found on Github, for anyone that wants to have a go at producing similar things: https://github.com/usedbytes/osgrid/tree/master/cmd/osmodel
Ordnance Survey Open Data
The Ordnance Survey is a government-owned agency in the United Kingdom, producing all manner of geographical products and services, perhaps most famous for the “Landranger” range of 1:50,000 scale paper maps for hiking.
Presumably under some mandate as a public resource, it turns out that the Ordnance Survey make a large amount of mapping data available for free, for any purpose, under “OS OpenData”.
The full list of products is here: OS OpenData downloads, and includes:
- Terrain50: Elevation data for the whole of the UK, with 50 m horizontal and 0.1 m vertical resolution
- VectorMap District: Region-level maps as vector or raster data.
- A whole host of other maps, at various scales and levels of detail
Basic elevation model
The Terrain 50 data set comes as a set of .zip files, each containing the data for a 10 km * 10 km “grid square”.
The data is indexed using
“National Grid” coordinates,
where a 2-letter tile
identifies a 100 km * 100 km square of the UK, and up to 10 numerical digits
identify a location within that tile, down to 1 m precision using the full
10 digits. For example, the summit of Snowdon has the “grid reference”:
SH 60986 54375.
Therefore, to be able to do anything useful with the OS OpenData products, it is clearly necessary to have a way to work with OS grid references.
My programming language of choice for spare-time projects is
and a quick search didn’t turn up any existing open-source libraries, so I created
This relatively simple package just parses, formats, and manipulates grid
references. Any complexity comes from the slightly strange recursive 5x5 grid
of tile identifiers used by the National Grid, and the fact that tile letters
“increase” North-to-South, but sub-tile digits increase South-to-North
With that base functionality, I wrote another package for pulling data out of the Terrain 50 data set, and hacked together a tool which you give a grid reference and it marches through all the locations in a square around that point, plucking out the elevation from Terrain 50 and writing the resulting array of numbers to a file.
which is generally my CAD program of choice - can import this kind of file using
function, and so using that and proper scaling I could get a pretty decent 3D
model of anywhere in the UK, and export it to a
.stl file for 3D printing! Neat!
Snowdon is my go-to example, as it’s visually quite interesting, and recognisable:
I exported the model of Bath that originally triggered this whole endeavour, and printed it out as big as I could on one of the Makespace Ultimaker 2+s.
I don’t seem to have a picture of the final thing, but I laser cut a base for the model, and it turned out pretty well. The picture with the base is a model with the Z-scale far too exaggerated, I made a second version which is more reasonable (looks less like the Himalayas…).
I’ve made another of these of a region of the Cairngorms, and I think they make quite nice gifts if someone has a particular interest in some part of the country.
Adding some colour
I mentioned that in addition to elevation data, there are “raster” map datasets also available under OS OpenData, so around the start of 2021 I started extending my code to be able to load this, too.
One application is obviously to just get images of any particular region of the map, but more interesting is to apply that as a “texture” to a 3D model.
The image at the top of the page is Snowdon again, but with the VectorMap District map imagery applied to it:
I’d used Shapeways to 3D print all of our wedding jewellery at this point, and I knew that they also offered a full-colour sandstone option, which would be ideal for printing a terrain model with aerial imagery.
One of the file formats they can consume for full-colour 3D prints is X3D, which is an ISO Standard (!) open format for describing 3D scenes/graphics. There’s an XML encoding for X3D, which is slightly quirky but also pretty easy to understand and create, so I extended my code to be able to create X3D files using the Terrain 50 elevation data and imagery from VectorMap District.
Making the X3D “mesh” is more complicated than just outputting the simple grid
of points I needed before for OpenSCAD’s
surface() function, but does make my
code much more flexible in terms of being technically capable of generating 3D
models in almost any format, rather than relying on OpenSCAD to do the heavy
Here’s a close-up of a portion of the mesh representation of Snowdon, again:
The map texture is definitely pretty cool, but what I really wanted was to use aerial imagery to give a more realistic model. I haven’t found a service where I can get cheap/free aerial imagery in a form that I can integrate directly with my code1; but there are online services (Google Maps, Bing Maps) where you can get aerial imagery.
I used my tool and the VectorMap District texture image it created, and got a screenshot of the same area from Bing Maps. Using an image editor, I overlaid the two pictures, and rotated/scaled the screenshot until it lined up with the map texture, and then simply replaced the texture image file with the properly-aligned screenshot.
I am not a lawyer, but my reading of Bing’s Print Rights would allow this for personal use.
The result is pretty good, I think - though Shapeways' Sandstone is not cheap! I really had to scale down the model to avoid spending a fortune.
The final stop on my topographical modelling journey so far has been to make some mountain-shaped chocolates.
For once this actually required zero code changes - the existing functionality was enough to get models of the mountains into OpenSCAD, where I applied an intersection with a rounded (and crucially, sloped!) plug shape.
I printed all the “plugs” and used some 0.5 mm PET sheet to vacuum-form moulds around them, using the vacuum former at Makespace. For my first attempt I printed the plugs with PLA, but it wasn’t able to stand up to the heat and very quickly deformed. I re-printed them in PETG instead, which has a higher melting temperature. I also had to drill a series of holes in the parts to enable all the air to escape to get good results out of the vacuum former.
Tempering chocolate is a skill which I definitely haven’t mastered, but after some stressful/frustrating evenings in the run up to Christmas 2021, I managed to make two sets of chocolates which looked half-way decent. 3D printing (plugs for) and vacuum forming moulds is definitely something I’d like to experiment more with (though not specifically terrain models).
Give it a try!
I’ve spent the past few days tidying up all the code I’ve hacked together for these projects spread over the past few years, and put it all on Github at https://github.com/usedbytes/osgrid.
The main tool is
https://github.com/usedbytes/osgrid/tree/master/cmd/osmodel , which can create
surfaces, images, and 3D (textured) models using the data sets I’ve mentioned
above in various different formats, so hopefully that’s enough to get others
started making their own topographical models if they’re so inclined. I’d love
to see them if you do!
There’s still a few rough edges and things missing (for example for very large models it can be useful to reduce the image and elevation data resolution to reduce the file size), but it’s good enough so I’m writing it up now.