Search code examples
dot

How to show arrows symmetrically for self-loops in a dot graph


I am working with a DFA which I have described in the dot file format. One of the nodes in my DFA has two self-loops, which I originally described with the following way

digraph {
  rankdir=LR;
  a -> a [color=blue]
  a -> a [color=green]
}

Which produces this output when I run dot graph.gv -Tpng

Arrows on same side

For symmetry reasons, I'd like to have the blue and the green arrows on opposite sides of the node. I can modify the headport and tailport of the green arrow to force it to start from the bottom of the node as follows:

digraph {
  rankdir=LR;
  a -> a [color=blue]
  a:sw -> a:se [color=green]
}

Unfortunately, that produces an absolutely wonky output:

Arrows on either side, but wonky

What's the correct way of getting the two arrows to be symmetrically opposite each other on the node?


Solution

  • I doubt you have a lot of control over the edge layout. But you can experiment with the headport attribute values. Here are some examples.

    Example 1

    digraph {
      rankdir=LR;
    
      a:n -> a [color=blue]
      a:s -> a [color=green headport=center]
    }
    

    View in editor

    dot-1

    Example 2

    digraph {
      rankdir=LR;
    
      a:ne -> a [color=blue]
      a:sw -> a [color=green headport=center]
    }
    

    View in editor

    dot-2


    Other layouts

    You can also experiment with different layouts. Here are some options for the circo layout.

    Example 3

    digraph {
      rankdir=LR;
      layout="circo"
    
      a:n -> a:_ [color=blue headport=n]
      a:s -> a:_ [color=green headport=s dir=back]
    }
    

    View in editor

    circo-1

    Example 4

    digraph {
      rankdir=LR;
      layout="circo"
    
      a:nw -> a:w [color=blue headport=_]
      a:se -> a:e [color=green headport=_]
    }
    

    View in editor

    circo-2