I have recently been constructing whole cities in Rhino using the Elk plugin. This parses OpenStreetMap data into Grasshopper geometry, allowing you to visualise any city or area in the world in your Rhino viewport.
One of the most interesting ways of getting your cities to look like cities is getting the buildings right. It is possible to extract building data with Elk, but this isn’t intuitive if you aren’t already familiar with OpenStreetMap data. And even if you are, the output is a collection of points, which requires further work to turn it into actual buildings.
This article will show you how I created buildings by extracting the OSM data and converting them into 3D meshes.
OpenStreetMap: Understanding the data
A crash course into OpenStreetMap data: All (well, nearly all) objects in the map are either saved as points or as lists of points. Points are useful for small objects, such as benches, letterboxes or trees. For larger objects, such as roads and buildings, collections of points are used. For roads, these points join together to form lines along the centre of the road. For buildings, these points define the line around the building’s edge. These ‘point collections’ are essentially polylines.
Every object, whether a point or a polyline, has a list of data associated with it. Each item in this list has a key and a value. It is with these keys and values that we describe the object. The most common key is ‘name’, and we describe the name in the value field. Most objects have many tags. For example, if we go into the OpenStreetMap editor and have a look at a local branch of Costa Coffee:
We have a list of keys and a list of values. The values are the data itself; the keys describe the type of data.
If you want to see this for yourself, go into the editor on OpenStreetMap. I personally prefer the Potlatch2 editor, which you can find in the drop-down next to the ‘edit’ button at the top. To see the tags, select an object on the map, then click ‘advanced’ in the bottom left.
Buildings in OpenStreetMap
Similarly, all buildings contain a collection of tags. The great thing about tags is that they are an open concept – you can use any tags that you like. With buildings, the most common tags include the building name and the building type. For example:
Using Elk to extract buildings
Elk can be used to extract the points that form the building outline. Like polylines in Rhino, the data is saved as a collection of points, and not a line itself, so it will be up to us to stitch the points together to create a building outline.
There is no built-in component that returns directly the building points, but we can use the GenericOSM to filter for data containing the ‘building’ key. The Polyline component joins the points together.
Make your buildings 3D
This is all well and good, but don’t they look a bit flat and boring? Let’s make them look a bit more realistic.
The easiest way to turn your polylines into 3D buildings is to extrude them, and then use patch to create a roof. But I can tell you through my own experience that this is a bad idea. For a few buildings it’s okay, but for the city scale, working with surfaces is very slow and you’ll quickly see your computer grind to a halt. To build our buildings at lightning speed, we have to use meshes.
There isn’t anything natively in Grasshopper that does this for us, but we can quickly write something in C#. Basically, we build up the walls with mesh faces, then use a Rhino command to cap the top for the roof.
This script takes in a list of points that describe the building outline, and a value for its height. (Let’s just send it a value of 10m or so for now.)
privatevoid RunScript(List<Point3d> pts, double ht, refobject A)
var building = new Mesh();
//make wallsfor (int p = 0; p < pts.Count; p++)
building.Vertices.Add(new Point3d(pts[p].X, pts[p].Y, pts[p].Z + ht));
for (int p = 0; p < pts.Count - 1; p++)
int j = p * 2;
building.Faces.AddFace(j, j + 1, j + 3, j + 2);
//make roofvar roofpts = new List<Point3d>();
for (int p = 0; p < pts.Count; p++)
roofpts.Add(building.Vertices[p * 2 + 1]);
var pline = new Polyline(roofpts);
var roof = Mesh.CreateFromClosedPolyline(pline);
A = building;
This then gives us:
But not all buildings are 10 metres tall…
It made things a lot easier to assume a height for our buildings. But can we do any better?
Given that we have a height input, we should be able to put something a bit more sensible into it. Some buildings in OSM do come with height data, though most don’t. If they do, this information is under the height key. How can we extract the building’s height information and apply it to our buildings with Elk?
It currently isn’t easy as there isn’t a comprehensive tag filter within Elk. One solution is to use the GenericOSM with k=height. This will return everything with height data; we just have to assume that everything returned is a building (it usually is) and model it as such.
Set up your Grasshopper as below, using the same C# script as above to create the buildings:
For my example of York, barely a single building has any height data. But, very happily, one very patient mapper has recorded the height of all the different elements of York Minster, leading to a very pleasing model.
In the meantime, if you’ve made it this far, you’ve probably realised that there are a lot of gaps in the OSM database. These gaps are best filled by people with local knowledge where you live, so I would encourage you to register and to start mapping! 🙂