We’ve been talking a lot about 3D buildings on maps lately. Mapbox Streets buildings now include heights, and we just launched extrusions in Mapbox GL JS. Some of our coolest demos are powered by building shape and height data from OpenStreetMap.
As of this week, there are over 201 million buildings mapped in OpenStreetMap, but fewer than 13 million of them have height information.
OpenStreetMap data is based on a combination of observations by volunteers on the ground and information that can be derived from certain freely available imagery and open data sources. Most OpenStreetMap contributors don’t have rangefinding or lidar equipment, and most buildings don’t have freely-published architectural plans. So how do building heights fit into the picture of volunteer data collection?
Building levels
For many buildings, we don’t need exact measurements to draw a reasonably accurate map of building heights. It’s often good enough to make an approximation based on how many floors are in a building - data that can be easily observed on the ground or in photos.
When you don’t know the exact height of a building, but you know it’s four stories tall, you can tag it with building:levels=4
in OpenStreetMap. Our Mapbox Streets processing code will convert that to 12 meters in the vector tiles since we approximate the height of one level as 3 meters (about 10 feet).
Mapillary images can be useful for mapping building levels as well as many other types of features.
Mapping sub-parts
Even a building that has a flat roof may vary in height from wing to wing. In these cases, you may want to map different parts of the building individually to capture a more accurate representation of the whole structure.
Chicago’s Willis Tower (formerly Sears Tower) is a great example of a building that benefits from simple mapping of subparts. If you view it from the top, you can think of the building as being made up of a grid of 3×3 squares.
To map a building like this in OpenStreetMap, first draw a single outline of the full footprint of the building. This object should hold all of the information that applies to the building as a whole. For example, tag it with building=yes
, building:levels=108
, and name=Willis Tower
.
Next, draw each of the subparts. The 108-story section occupies two neighboring sections of the 3×3 grid, so we’ve got seven squares and one rectangle. Each of these eight ways is tagged with building:part=yes
and has a building:levels
tag of 50, 66, 90, or 108, depending on the section.
Tip: Overlapping shapes like this can be tricky to select. In JOSM, click while holding down Alt
/ Option
to cycle through overlapping objects and make the selection you want.
Getting really detailed
Some buildings just don’t fit into the approach of using building:levels
as an approximation for height, and you’ll need to figure out actual measurements in meters. For well-known buildings, you may be able to find measurements published on an official website or open data source such as Wikidata.
If you can’t find a published measurement, it may be possible to derive a reasonably accurate measurement from a photo.
One of my favorite buildings in Washington, D.C., both inside and out, is the National Gallery of Art east building.
I’m familiar with the building from the street and there is good aerial imagery to work with in JOSM, so picturing the pieces I needed to fit together was relatively straightforward. But mapping it with building:levels
alone wouldn’t give an accurate sense of the shape or scale of the building in 3D.
Except for the patios on the south side of the building, there are two main height measurements to figure out: the main foyer area, and the towers and office sections which are all the same height.
If you can take a photo of the building, looking straight-on at one of its sides from a distance, using a telephoto lens to minimize perspective distortion, you can calculate the approximate width/height ratio of a section of the building by measuring pixels in an image editor. If you can measure the real-world length of the side of the building (for example, from a geo-referenced aerial photo), you can use the ratio of meters to pixels to calculate the approximate height as well.
If you draw a line in JOSM, the status bar at the bottom of the window will tell you the distance in meters between those two points. The distance between A↔B in the photo above was 3,570 pixels in my image editor. The same edge of the building is clearly visible in Mapbox Satellite imagery and measures 74 meters in JOSM. 74 meters divided by 3,570 pixels is about 0.02073. We can take this number and multiply it by other pixel distances in the image to convert to meters. B↔C at 1,592 pixels is about 33 meters tall, and D↔E at 874 pixels is about 18 meters tall.
Another significant feature of the architecture is the large inset entrance areas. We can map them in OpenStreetMap too! In the above diagram, the height of the entrance area is F↔G, and we can calculate that it’s about 9.5 meters off of the ground.
I’ve mapped the parts of the building that are above the entrance area separately, tagging them with building:part=yes
and height=18
, just like the foyer area. However, I’ve also added min_height=9.5
to indicate that this part of the building starts not on the ground but 9.5 meters above it.
All together, here is the result in 3D:
This photo measurement approach won’t work in all situations, especially for very tall buildings that can’t be photographed without significant perspective distortion. (Luckily for me, that isn’t a big problem in Washington, D.C.)
Looking for more?
We’ve only just covered the basics - you can learn lots more about 3D mapping on the OpenStreetMap wiki. And check out the Mapbox GL Style Specification and our Mapbox GL JS examples to learn how to use 3D extrusions in your own Mapbox maps.