0

I want to make a Legend/Key in GraphViz. I make one successfully, but then how can I position it at the bottom right corner of the graph? I try using pos but it doesn't work (it seems like it's only applicable in neato). This is my test code:

digraph {
    rankdir="LR";
    a -> b -> c -> a
    subgraph cluster_Legend { 
    label = "Legend";
    rank=same;
    e -> f
}

enter image description here


Normally, if the legend is actually an HTML table embeded in the lable, one can use labelloc="b" labeljust="r". However, in my case the items to be explained in the legends are edges, not nodes, so my legend needs to consist two tables. Therefore using labelloc only moves the texts in the legend box, not the legend box itself.

My legend can be coded in two forms: table and non-table

Table version

digraph {    
    subgraph clusterLegend { 
    rank = sink;
    label = "Legend";
    fontsize = 20
    node [ color="white" ]
    {rank=same; key, key2}
    key [ label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
      <tr><td align="right" port="i1">A</td></tr>
      <tr><td align="right" port="i2">A</td></tr>
      </table>> ]
    key2 [ label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
      <tr><td align="left" port="i1">B</td><td>     The reason for A is B</td></tr>
      <tr><td align="left" port="i2">B</td><td>     The solution for A is B</td></tr>
      </table>>]
    key:i1 -> key2:i1 
    key:i2 -> key2:i2 [ arrowhead="odiamond" style=dashed ]
   }
}

Non-table version

{rank=same; a1, b1 }
    {rank=same; a2, b2 }
    a1 [label="A"]
    a2 [label="A"]
    b1 [label="B        The reason for A is B"]
    b2 [label="B        The solution for A is B"]
    a1 -> b1 [ minlen=4 ]
    a2 -> b2 [ minlen=4 arrowhead="odiamond" style=dashed ]

I think if we are to use labelloc and labeljust, then we need to figure out how to put arrows as items of table. Is there a way to do so?

This is my real graph.

See more: Placing Graphviz nodes in fixed positions / Magnus Jacobsson / Observable

Ooker
  • 1,969
  • 4
  • 28
  • 58
  • Use labelloc and labeljust. Here is previous discussion - https://forum.graphviz.org/t/adding-key-or-legend/351/2 – sroush Jun 08 '21 at 14:11
  • Is there a way to not using label? Because if the legend consists two tables, then this doesn't seem to work. Please see my update – Ooker Jun 08 '21 at 15:16

1 Answers1

1

You can draw additional invisible edges and node(s) at the bottom of the diagram and set them the same rank as the legend (also need to turn on the newrank attribute for graph). By adjusting the height and width of the invisible node(s), you can move the legend to the desired distance.

An image that shows the invisible:
position the legend at the bottom right of the graph with showed hidden node and edge made with graphviz dot

Final image:
position the legend at the bottom right of the graph made with graphviz dot

Script:

digraph {    
    newrank=true // enable ranking between nodes and clusters
    
    a->b->c
    
    subgraph clusterLegend { 
    rank = sink;
    label = "Legend";
    fontsize = 20
    node [ color="white" ]
    {rank=same; key; key2}
    key [ label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
      <tr><td align="right" port="i1">A</td></tr>
      <tr><td align="right" port="i2">A</td></tr>
      </table>> ]
    key2 [ label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
      <tr><td align="left" port="i1">B</td><td>     The reason for A is B</td></tr>
      <tr><td align="left" port="i2">B</td><td>     The solution for A is B</td></tr>
      </table>>]
    key:i1 -> key2:i1 
    key:i2 -> key2:i2 [ arrowhead="odiamond" style=dashed ]
    }
   
   // Invisible nodes and edges
    d [style=invis width=5 height=5]
    c->d [style=invis]
   
   // Setting a same rank between cluster and invisible node
   {rank=same;key;key2;d;}
}

Another variant is create two distinct graphs and use gvpack to glue them together.

kirogasa
  • 627
  • 5
  • 19