How can I control within level node order in graphviz's dot?
Asked Answered
Z

4

35

I have a graph that has a tree as its backbone. So I have, for example a node A with children B, C, and D. Assuming the graph is being drawn top-down, A will be on one level, then B, C, and D. I would like to force graphviz to lay them out in B, C, D order within their rank. Is this possible? If so, how?

If there are only A, B, C, and D, I can get this effect by just putting B, C, and D in that order in the input dot file. But if there are other edges out of B, C, and/or D, sometimes the order gets scrambled. That's what I would like to avoid.

enter image description here

Zn answered 31/5, 2017 at 2:6 Comment(1)
node[ordering=out] works fine: graphviz.org/docs/attrs/orderingPeeples
R
42

This can be achieved with "invisible" edges as shown. Please note well the comments that describe how it works.

digraph test{

// make invisible ranks
rank1 [style=invisible];
rank2 [style=invisible];

// make "invisible" (white) link between them
rank1 -> rank2 [color=white];

// declare nodes all out of desired order
A -> D;
A -> B;
A -> C;
A -> E;

// even these new connection don't mess up the order
B -> F -> G;
C -> F -> G;

{
rank = same;
// Here you enforce the desired order with "invisible" edges and arrowheads
rank2 -> B -> C -> D -> E [ style=invis ];
rankdir = LR;
}
}

enter image description here

Ratal answered 31/5, 2017 at 2:18 Comment(1)
There is no need for rank1 and rank2, see below.Tartan
V
45

To help fill-out @TomServo's answer (for people struggling with "rank"), I've made the invisible edges visible:

After adding <code>rank1</code> and <code>rank2</code>.

Vatic answered 9/4, 2018 at 15:14 Comment(1)
Thanks, that helps understand the ranking better.Geehan
R
42

This can be achieved with "invisible" edges as shown. Please note well the comments that describe how it works.

digraph test{

// make invisible ranks
rank1 [style=invisible];
rank2 [style=invisible];

// make "invisible" (white) link between them
rank1 -> rank2 [color=white];

// declare nodes all out of desired order
A -> D;
A -> B;
A -> C;
A -> E;

// even these new connection don't mess up the order
B -> F -> G;
C -> F -> G;

{
rank = same;
// Here you enforce the desired order with "invisible" edges and arrowheads
rank2 -> B -> C -> D -> E [ style=invis ];
rankdir = LR;
}
}

enter image description here

Ratal answered 31/5, 2017 at 2:18 Comment(1)
There is no need for rank1 and rank2, see below.Tartan
T
20

You don't need those magic rank1 and rank2.

Just:

  1. Make the graph as usual.
  2. Add nodes one again in a subgraph.
digraph test{

// declare nodes all out of desired order
A -> D;
A -> B;
A -> C;
A -> E;

B;C;D;E;

// even these new connection don't mess up the order
B -> F -> G;
C -> F -> G;

{
rank = same;
// Here you enforce the desired order with "invisible" edges and arrowheads
edge[ style=invis];
B -> C -> D -> E ;
rankdir = LR;
}
}

Tartan answered 22/9, 2020 at 9:55 Comment(3)
Is there a way to do this to enforce order within a cluster? Simply making the subgraph here a cluster arranges the nodes within it vertically instead: i.imgur.com/sAb0AnE.png.Biafra
I dunno, just added another set of { } inside the subgraph, and it became horizontal.Tartan
I'm finding that this doesn't enforce the order: i.imgur.com/CJHtNGi.png. (Code: pastebin.com/ZaT6qSYe). Plain subgraphs do seem to enforce the order: i.imgur.com/JZvZ5V9.png.Biafra
V
15

I hit the same snag, and discovered the magic incantation is ordering=out

My full example looks like this:

digraph game_tree {
node [shape = circle, ordering=out];
f, h [shape=doublecircle, color=red];
k, n [shape=doublecircle, color=blue];
l, m [shape=doublecircle];
a -> b [label=1];
a -> c [label=2];
a -> d [label=3];
b -> e [label=4];
b -> f [label=5];
c -> g [label=4];
c -> h [label=5];
d -> i [label=4];
d -> j [label=5];
e -> k [label=6];
g -> l [label=6];
i -> m [label=7];
j -> n [label=8];
}

graphviz tree

Voccola answered 13/1, 2021 at 10:50 Comment(2)
This is much cleaner than other answers proposed above imho. Using fontcolor="transparent" makes the labelsdisapear for a cleaner result.Entitle
If you don't want labels, just do a -> b; etc instead of a -> b [label=1];Voccola

© 2022 - 2024 — McMap. All rights reserved.