Last time, I wrote about the little details that make a good flow map. The data in that post was made up and simpler than your typical flow map. That’s why I wanted to redo it with real-world data. In this post, I’m using domestic migration data of Austria.
With 9 states, that makes 72 potential flow arrows. Since that’s too much to map, I’ve decided in a first step to only show flows with more than 1,000 people.
Following the recommendations mentioned in the previous post, I first designed a basic flow map where each flow direction is rendered as a black arrow:
Even with this very limited number of flows, the map gets pretty crowded, particularly around the north-eastern node, the Austrian capital Vienna.
To reduce the number of incoming and outgoing lines at each node, I therefore decided to change to colored one-sided arrows that share a common geometry:
The arrow color is determined automatically based on the arrow direction using the following expression:
CASE WHEN "weight" < 1000 THEN color_rgba( 0,0,0,0) WHEN x(start_point( $geometry)) - x(end_point($geometry)) < 0 THEN '#1f78b4' ELSE '#ff7f00' END
The same approach is used to control the side of the one-sided arrow head. The arrow symbol layer has two “arrow type” options for rendering the arrow head: on the inside of the curve or on the outside. This means that, if we wouldn’t use a data-defined approach, the arrow head would be on the same side – independent of the line geometry direction.
CASE WHEN x(start_point( $geometry)) - x(end_point($geometry)) < 0 THEN 1 ELSE 2 END
Obviously, this ignores the corner case of start and end points at the same x coordinate but, if necessary, this case can be added easily.
Of course the results are far from perfect and this approach still requires manual tweaking of the arrow geometries. Nonetheless, I think it’s very interesting to see how far we can push the limits of data-driven styling for flow maps.
Give it a try! You’ll find the symbol and accompanying sample data on the QGIS resource sharing plugin platform: