James Adam Buckland
Home Blog Games Resume

2022-04-09 Three-Dimensional Prints with Blender and OpenStreetMap blender graphics osm pen_plotting

Summary

I used blender-osm and Freestyle to render three-dimensional geodata from OpenStreetMap to a pen plotter.

Here is the finished product, a 11in x 17in print on vellum. (Click through for high resolution.)

alt

Here is an overview of the data pipeline I used to generate this print:

┌─────────────┐
│OpenStreetMap│
└┬────────────┘
 │
┌▼──────────┐
│blender-osm│
└┬──────────┘
 │
┌▼──────┐
│Blender│
└┬──────┘
 │
┌▼─────────────────────┐
│Freestyle SVG Exporter│
└┬─────────────────────┘
 │
┌▼──────┐
│AxiDraw│
└───────┘

OpenStreetMap

OpenStreetMap is a Wikipedia-style repository of map data. I have used it before to download and print map data with a pen plotter. It contains high-quality, free, volunteered and compiled 2D and 3D geodata about the real world.

blender-osm

blender-osm is a plugin written by prochitecture which imports geodata from OSM into Blender, a free 3D computer graphics software suite.

After installing the plugin and using it to create a new document, blender-osm links the user to an area selection website which makes it simple to select an area of the map to download.

alt

We can copy/paste the lat/long area selection (in this case, a string like -74.02041,40.73327,-73.98792,40.75015) into the blender-osm interface and select which map layers to import (buildings, forests, water, etc.)

Blender

We end up with a detailed 3D model…

alt

…but of course it looks better in perspective.

alt

I knew I wanted to draw a multicolor print, so I grouped the downloaded layers by pen color. All the buildings went in one group, all primary roads in another, etc. Later I print these layers on the plotter one by one, swapping out the pen in between layers.

alt

Using separate object collections means we can toggle on/off items by layer in the Blender UI. Here is a render of the map with only 3D buildings visible:

alt

and another render of the map with only primary and secondary highways visible:

alt

and another render of the map with only pedestrian roads visible.

alt

Of course, we can render this for any combination of the layers.

The result is a 3D model in Blender which can be exported as a raster image or as an animation. But the pen plotter expects vector data, so we have to use a plugin.

Freestyle SVG Exporter

Freestyle is a Blender plugin which plots the edges of visible objects as SVG lines.

This is perfect for pen plotting, since pen plotters expect vector input.

Freestyle is very powerful but a bit hard to use. First I enabled it like so:

alt

Then I played with the settings until it handled crease angles in the way I expected.

alt

I also applied a Bezier filter which gave the finished edges a cartoonish curve.

alt

It’s hard to tell the effects of these settings until Blender actually renders the scene to SVG.

Camera

Finally I played with the camera location and perspective settings until I had a scene composition I liked. The focal length of the virtual camera makes a big difference:

alt alt alt

It is also possible to swap out a perspective camera for an orthographic one, which looks isometric like a video game. This is a nice effect but I felt it gave the scene some undesirable flatness.

alt

SVG

The default exported PNG has both the raster image and the overlaid vector lines, which makes it easy to see why Freestyle drew lines in certain places.

alt

The default exported SVG is what we eventually send to the plotter.

alt

Layers

We can pop into the SVG file and separate the layers manually, since AxiDraw requires printing one SVG file at a time and cannot filter by layer. Here is the layer for buildings-only:

alt

roads-only:

alt

and highways-only:

alt

Blender rendered these all in the same pass, so objects in the foreground correctly block objects in the background.

Foreground:

alt

Background:

alt

AxiDraw

That’s pretty much it. We can send each layer to the plotter one at a time, swapping out pen colors, and we know that objects in the foreground will appear to obscure objects in the background. Here is the final product:

alt