Skip to content

German Cities by Population

In this tutorial, we will learn how to visualize German cities by population size in Blender 5.0.1.

Here's how the final result looks as an image:

Cities by size

And here as a video:

Download cities_by_size.blend

Preparing Data

We start with a CSV file that contains German cities with more than 90,000 inhabitants, sourced from the Statistisches Bundesamt (as of 31.12.2023).

Download german_towns_with_more_then_90k.csv

German towns CSV screenshot

From this dataset, we want the following columns:

  • Latitude and Longitude — the geographic coordinates
  • Population — the number of inhabitants per city

Import into Blender

First, install the CSV Importer add-on and drag'n'drop the dataset into Blender's viewport.

Next, we add a background map of Germany. Similar to the world population tutorial, we use an equirectangular projection so that latitude and longitude values map directly to x and y coordinates. A good base map is the Germany location map from Wikimedia Commons.

Germany location map

Source: Wikimedia Commons — Germany location map

We scale the map to match the geographic coordinates and adjust the colors with shader nodes.

Germany map with shader nodes in Blender

With this in place, we add the data as circles using Geometry Nodes. Each city is represented by a circle whose radius corresponds to its population.

Cities as circles with Geometry Nodes

To color the circles, we create a reference object and assign a material to it. The Geometry Nodes setup then applies this material to all instances automatically.

Circle material with transparency and emission

Next, we define an active_range attribute. Cities are sorted by population, and this parameter ramps from 0 to 1 based on each city's rank relative to the total number of frames. At any given frame, the largest cities already have a value of 1 while smaller cities are still at 0. Now we can do revealing of cities one by one over time, from largest to smallest. This is very useful for animation, as it lets us control which cities are visible at each point in the timeline.

Active range Geometry Nodes setup

Active range values in the spreadsheet

Next, we add city labels using a dedicated Geometry Nodes tree. It iterates over each city using a For Each Element node, reads the stadt_name attribute, and converts it to a text curve via String to Curves. The label is then positioned at the city's coordinates with a small offset. A Float Curve node controls the opacity based on the active_range attribute — labels fade in as their city becomes active, and a Less Than check ensures fully inactive cities stay hidden. This gives us animated labels that appear in sync with the circles.

City labels Geometry Nodes tree

City labels on the map

Finally, we add a legend and the animation is done! The legend shows circle sizes for different population levels (100k–600k), generated with another Geometry Nodes setup using an Index Switch.

Legend and final result

Download cities_by_size.blend

If you come up with your own creations and post them online, you're welcome to tag me on Bluesky!