Details of good flow maps

In my previous post, I shared a flow map style that was inspired by a hand drawn map. Today’s post is inspired by a recent academic paper recommended to me by Radoslaw Panczak  and Thomas Gratier :

Jenny, B., Stephen, D. M., Muehlenhaus, I., Marston, B. E., Sharma, R., Zhang, E., & Jenny, H. (2016). Design principles for origin-destination flow maps. Cartography and Geographic Information Science, 1-15.

Jenny et al. (2016)  performed a study on how to best design flow maps. The resulting design principles are:

  • number of flow overlaps should be minimized;
  • sharp bends and excessively asymmetric flows should be avoided;
  • acute intersection angles should be avoided;
  • flows must not pass under unconnected nodes;
  • flows should be radially arranged around nodes;
  • quantity is best represented by scaled flow width;
  • flow direction is best indicated with arrowheads;
  • arrowheads should be scaled with flow width, but arrowheads for thin flows should be enlarged; and
  • overlaps between arrowheads and flows should be avoided.

Many of these points concern the arrangement of flow lines but I want to talk about those design principles that can be implemented in a QGIS line style. I’ve summarized the three core ideas:

  1. use arrow heads and scale arrow width according to flow,
  2. enlarge arrow heads for thin flows, and
  3. use nodes to arrange flows and avoid overlaps of arrow heads and flows

This slideshow requires JavaScript.

To get started, we can use a standard QGIS arrow symbol layer. To represent the flow value (“weight”) according to the first design principle, all arrow parameters are data-defined:


To enlarge the arrow heads for thin flow lines, as required by the second design principle, we can add a fixed value to the data-defined head length and thickness:



The main issue with this flow map is that it gets messy as soon as multiple arrows end at the same location. The arrow heads are plotted on top of each other and at some point it is almost impossible to see which arrow starts where. This is where the third design principle comes into play!

To fix the overlap issue, we can add big round nodes at the flow start and end points. These node buffers are both used to render circles on the map, as well as to shorten the arrows by cutting off a short section at the beginning and end of the lines:

    buffer( start_point($geometry), 10000 )
  buffer( end_point( $geometry), 10000 )

Note that the buffer values in this expression only produce appropriate results for line datasets which use a CRS in meters and will have to be adjusted for other units.


It’s great to have some tried and evaluated design guidelines for our flow maps. As always: Know your cartography rules before you start breaking them!

PS: To draw a curved arrow, the line needs to have one intermediate point between start and end – so three points in total. Depending on the intermediate point’s position, the line is more or less curved.

    • Hi Ricardo! The dataset in this example is completely made up. I’m current working on a follow-up with actual migration data.

  1. dn said:

    Looks great, I might try it out!

  2. Renato Arbex said:

    Hi, great post. I am having difficulty trying to implement this style. How to properly use the geometry generator? I’ve chosen single symbol, added the arrows (ok), then tried inserting the Geometry generator symbol with the expression in the post. But it does not work. Any thoughts? Thanks!!

    • Renato Arbex said:

      Now it works ok! My the layer should be in the correct CRS (was using lat/lon and not UTM). And to show the circles one would need another Geometry Generator for the circles using buffer(end_point($geometry), 500) for example, or adding another layer with the points. Hope it helps.

      • Antony Zonato said:

        Yes, it was also my problem! Thank you for putting up the answer here!

  3. Wojtek said:

    Which CRS is ok?

    • Any CRS with units in meters will be ok. For other units, the values in the styles have to be adjusted.

      • Wojtek said:

        Excuse me. I thought about doing a curved arrows I can’t do that. I marked the curved arrows, but it doesn’t work.

      • To draw a curved arrow, the line needs to have one intermediate point between start and end. Depending on the intermediate point’s position, the line is more or less curved.

      • Wojtek said:

        Thank you Anita! Now is ok

  4. Edmond said:

    if we create one intermediate point between start and end, there will is a new circle?
    No ?

    • A circle piece will be constructed that goes through start, intermediate, and end point.

  5. Kristoffer said:

    Such a nice styling, you have made there!
    Is it possible to make the labels follow the curved lines?

    • Unfortunately, currently it is not possible to automatically generate labels that follow the shape of curved arrow symbol layers, as far as I know.

      • Kristoffer said:

        Thanks for your reply! Hopefully it will be possible in the future :-).

        Another question…I can see that you put in the following in the data defined override:

        scale_linear(“weight” ,1000,10000,0.1,8)
        * CASE WHEN “weight” < 1000 THEN 0 ELSE 1 END

        What does the * do in relation to the expression syntax?

      • * CASE WHEN “weight” < 1000 THEN 0 ELSE 1 END is just a multiplication with 0 or 1.

      • Hi, I have found a workaround for this by using the intermediate point as the reference for the label. This won´t bend the label in any way but has done the trick for my visualization.

  6. Is there a way to use the gradient fill to make the first part of the line transparent? I have a hard time fiddling with this and have not found a solution so far. The only line which should be transparent is the one which starts at the point – so only the outgoing ones, not the ingoing ones.

  7. Brent Edwards said:

    Great post! How can I control the styling of the circular nodes created with the geometry generator? Mine don’t seem to have a border – or maybe it is white?!

    • Hi Brent, you need to adjust the style of the buffer polygon’s fill symbol layer.

      • Brent Edwards said:

        Thanks for the reply. I still can’t get it to work. When you say :

        “To fix the overlap issue, we can add big round nodes at the flow start and end points. These node buffers are both used to render circles on the map, as well as to shorten the arrows by cutting off a short section at the beginning and end of the lines:”

        My lines are shortened, but I am not getting the”circles on the map” part.

        I am adding a “Geometry generator” using the “LineString / MultiLineString” “Geometry Type”.

        Do I need to add a second “Geometry generator”? I so, what options should I use?

      • That’s correct. As shown in the post’s last screenshot, there are two additional geometry generators which define buffers around the line start and end points.

      • Brent Edwards said:

        Ok, I got it work using a second Geometry generator:

        Geometry type – Polygon/MultiPolygon
        Expression – buffer(start_point($geometry), 1000)

        I had to separate the two Geometry generators into two layers (one to shorten the lines and another for the node buffers) in order to get my node buffers (white fill, black outline) to draw on top of the lines to mask the lines passing under the node buffers. When using both Geometry generators in the same layer, the lines always draw on top of the nodes, irrespective of the order they a placed in the symbol layer hierarchy. I’m using QGIS 2.18.3 on Windows.

        Thanks again for this awesome post! I had been following the flow maps research at and your implementations are really impressive!

  8. Arthur said:

    Hello, thank you for this nice trick. I still can’t figure how to make those node and therefore cut arrow.
    Also I can’t find where you make your flow “round”and not a straight line.

    Thank you again

    • Please see the previous comments. Both issues have been discussed there.

      • Arthur said:

        Ok I got it, but had to read a couple of times each comments.

        To made the nodes you need to had 2 layers (1 for the beginning of the line and 1 for the ending). With parameters given by Brent Edwards

        And if you whant to make the lines “round” you have to add manually a point in the midle of the line then drag this point. There is no automatic way to do it right now.


  9. Olivia said:

    Could you post a step by step explanation of how to create these curved lines? I have read through the post, other posts, and all the comments multiple times and I am unable to figure out the steps I need to take. E.g. what did the input(s) consist of? Could I use one shapefile with a beginpoint geom and an endpoint geom? Then, how do I make a line? How do I add a third point in and how do I manually drag it to create a curve? This is a beautiful style and I’d love to be able to recreate it.

  10. Igor de Sousa said:

    Hi Anita, how are you? I accompany your posts about QGIS and congratulate you for your excellent explanations, so I am having difficulty producing my first flow map regarding slave labor here in the state of Maranhão in Brazil, so I wanted to learn the first steps to the elaboration Of this kind of very complex map, since I could not find a tutorial or video of this nature. Thank you for your attention.

      • Igor de Sousa said:

        Ah yes, I understood the process of creating the arrows, but Anita after looking at the official document that you indicated to me and your last post, I realized that when I open my property of the layer and I try to edit the symbol layer type appear only three options: Geometry generator, marker line and simple line, unfortunately, does not appear the ARROW option as you demonstrate in your gif, how do I display this option? I use QGIS 2.14.8.

      • Igor de Sousa said:

        Thank you so much Anita,you really helped me, thank you for your attention and your patience hahaha.


  11. Raquel Espinoza said:


    What a nice Styling this one :)
    Is there a way to automate the process of creation of the new point to make the lines curved?

    • As far as I know, there are no ready-to-use tools yet.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: