1

Is there a setting in graphviz to generate balanced diagrams like this:

correct diagram http://img3.imageshack.us/img3/6423/testaah.png

When diagram is more complex like below - it isn't balanced like that above (4 is below **).

not correctly balanced http://img51.imageshack.us/img51/6632/test2b.png

Code to generate second diagram:

graph
{
  n1 [label="+"];
  n1 -- n2;
  n2 [label="/"];
  n2 -- n3;
  n3 [label="*"];
  n3 -- n4;
  n4 [label="1"];
  n3 -- n5;
  n5 [label="2"];
  n2 -- n6;
  n6 [label="3"];
  n1 -- n7;
  n7 [label="**"];
  n7 -- n8;
  n8 [label="4"];
  n7 -- n9;
  n9 [label="5"];
}
user360872
  • 1,261
  • 4
  • 15
  • 15

3 Answers3

2

You can "introduce new, invisible nodes to re-balance the layout." (see https://graphviz.org/faq/#FaqBalanceTree). So your code becomes :

graph
{
  n1 [label="+"];
  n2 [label="/"];
  n1 -- n2;
  n1b1 [label="", width=.1, style=invis]
  n1 -- n1b1 [style=invis]  
  n1b2 [label="", width=.1, style=invis]
  n1 -- n1b2 [style=invis]  
  n1b3 [label="", width=.1, style=invis]
  n1 -- n1b3 [style=invis]  
  n7 [label="**"];
  n1 -- n7;
  { rank=same n2 -- n1b1 -- n1b2 -- n1b3 -- n7 [style=invis] }

  n3 [label="*"];
  n2 -- n3;
  n2b1 [label="", width=.1, style=invis]
  n2 -- n2b1 [style=invis]
  n6 [label="3"];
  n2 -- n6;
  { rank=same n3 -- n2b1 -- n6 [style=invis] }

  n8 [label="4"];
  n7 -- n8;
  n7b1 [label="", width=.1, style=invis]
  n7 -- n7b1 [style=invis]
  n9 [label="5"];
  n7 -- n9;
  { rank=same n8 -- n7b1 -- n9 [style=invis] }
  
  n3 -- n4;
  n4 [label="1"];
  n3 -- n5;
  n5 [label="2"];
}

With this output :

Diagram

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
greg
  • 844
  • 4
  • 11
2

A variation on @greg's answer, that's a bit more compact and less dependent on the order of statements in the graph.

Upsides:

  1. It doesn't use rank=same at all
  2. Generally the source organization is a bit more 'tree-like', which makes edits easy.
  3. Only 2 minor changes to show/hide the all nodes if needed.
  4. It doesn't matter what order any of the edges are declared in, as long as the parent and children are all on the same line.

Downside:

Like the FAQ, it still depends on hidden nodes to balance the tree.

graph calc {
  graph[nodesep=0.25, ranksep=0.3, splines=line];
  node [fontname = "Bitstream Vera Sans", fontsize=14,
        style=filled, fillcolor=lightblue,
        shape=circle, fixedsize=true, width=0.3];

  // layout all nodes 1 row at a time
  // order matters on each line, but not the order of lines
  "+";
  "/", am, "**";

  // or can be more spread out if you need to . . .
  n1 [label="1"];
  dm;
  n2 [label="2"];
  "*", bm, "3", "4", cm, "5";

  // make 'mid' nodes invisible
  am, bm, cm, dm [style=dotted, label=""];

  // layout all visible edges as parent -> left_child, right_child
  "+" -- "/","**";
  "/" -- "*","3"
  "**"-- "4","5";
  "*" -- n1, n2;

  // link mid nodes with a larger weight:
  edge [style=dotted, weight=10];
  "+" -- am;
  "/" -- bm;
  "**"-- cm;
  "*" -- dm;
}

Which results in:

balanced tree graph

This is the technique I usually use when I need to draw a tree.

I don't often use gvpr because it doesn't play well in environments where I often want to use a graph (sphinx, doxygen, etc.). But if you can use a standard pipeline to make your graph and you don't care what the resulting graph source looks like, then gvpr is your friend.

albert
  • 8,285
  • 3
  • 19
  • 32
DaveParillo
  • 2,233
  • 22
  • 20
1

For this particular example, all you need is to loosen up the weight of the edges between the top 3 edges:

graph g{    
  n1 [label="+"];
  n1 -- n2 [weight=0];
  n2 [label="/"];
  n2 -- n3;
  n3 [label="*"];
  n3 -- n4;
  n4 [label="1"];
  n3 -- n5;
  n5 [label="2"];
  n2 -- n6;
  n6 [label="3"];
  n1 -- n7 [weight=0];
  n7 [label="**"];
  n7 -- n8;
  n8 [label="4"];
  n7 -- n9;
  n9 [label="5"];
}

Output:

graphviz output

In more complex cases where invisible nodes and edges and setting weights gets difficult to manage, you may try Emden R. Gansner's gvpr script to layout binary trees as described in an answer to this question.

Community
  • 1
  • 1
marapet
  • 54,856
  • 12
  • 170
  • 184