Top-left to bottom-right tree in Graphviz - graphviz

Say I start with this:
graph {
graph [splines=ortho]
node [fontname="Sans-Serif" shape=record]
rankdir=LR
"Parent" -- "Child 1"
"Parent" -- "Child 2"
"Parent" -- "Child 3"
"Parent" -- "Child 4 and then some"
}
This yields:
What do I need to change to get this instead (and so on for subequent levels)?
Thanks!

Surprisingly difficult. Ortho replaced by DIY ortho-like edges, using pseudo-invisible nodes.
graph {
// note: renaming the nodes was optional
graph [splines=false ] // was ortho
node [fontname="Sans-Serif" shape=rect ] // record features unused
rankdir=LR // ranks are now vertical!
{ // non-visible nodes (i1 i2 i3 i4) used to connect edges
rank=same
node [label="" peripheries=0] // keep same size as other nodes,
// but do not draw (peripheries)
edge [headclip=false tailclip=false] // draw center-to-center
i1:c -- i2:c -- i3:c -- i4:c
}
{node [group=T] P C1} //group used to place "child 1" w/ parent
P [label="Parent"]
{
rank=same
C1 [label="Child 1"]
C2 [label="Child 2"]
C3 [label="Child 3"]
C4 [label="Child 4 and then some"]
}
P -- i1 [headclip=false]
edge [tailclip=false]
i1 -- C1
i2 -- C2
i3 -- C3
i4 -- C4
}
Giving:

Related

Graphviz: drawing nodes in given order to correctly draw tree

I'm trying to draw a tree but have a problem with the following approach:
Use of 'invisible' nodes to connect levels of tree,
Use 'rank same' to draw nodes on the same level
Using this code I get following result
graph G{
edge [arrowhead = none];
splines = ortho;
rankdir = LR;
node [ shape="box" fixedsize = true width = 4 height = 1];
{ rank = same; "C" }
{ rank = same;
"B"
"A"
}
{ rank = same;
"F"
"D"
"E"
}
node [ shape="cricle" width = 0 height = 0 style=invis];
{ rank = same;
"B_Inv_Parent_1"
"C_Inv_Even_Children_0"
"A_Inv_Parent_1"
}
{ rank = same;
"F_Inv_Parent_2"
"D_Inv_Parent_2"
"A_Inv_Even_Children_1"
"E_Inv_Parent_2"
}
"C" -- "C_Inv_Even_Children_0";
"B_Inv_Parent_1" -- "C_Inv_Even_Children_0" -- "A_Inv_Parent_1";
"B_Inv_Parent_1" -- "B";
"A_Inv_Parent_1" -- "A";
"B" -- "F_Inv_Parent_2";
"F_Inv_Parent_2" -- "F";
"A" -- "A_Inv_Even_Children_1";
"D_Inv_Parent_2" -- "A_Inv_Even_Children_1" -- "E_Inv_Parent_2";
"D_Inv_Parent_2" -- "D";
"E_Inv_Parent_2" -- "E";
}
I have a problem in the 3rd level: D is drawn on top of the picture thus making a connection with E not ideal.
I would like to have the same results as with C, B and A.
I think the problem is with the order of nodes definition however, I can't manage to get it working whatever order I define them in.
Can anyone spot another problem with my code and suggest a fix?
I have cleaned up your code and re-arranged a few lines - after all, I think that introducing
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
has been the key. You don't need to define edge arrows since you don't have a directed graph, and there is a typo in shape="cricle".
Here my edited version
graph G
{
splines = ortho;
rankdir = LR;
// node definitions
node [ shape="box" fixedsize = true width = 4 height = 1];
C
{ rank = same; B A }
{ rank = same; F D E }
node [ shape="point" width = 0 height = 0 ];
{ rank = same;
B_Inv_Parent_1
C_Inv_Even_Children_0
A_Inv_Parent_1 }
{ rank = same;
F_Inv_Parent_2
D_Inv_Parent_2
A_Inv_Even_Children_1
E_Inv_Parent_2 }
// edges
C -- C_Inv_Even_Children_0;
B_Inv_Parent_1 -- C_Inv_Even_Children_0 -- A_Inv_Parent_1;
B_Inv_Parent_1 -- B -- F_Inv_Parent_2;
A_Inv_Parent_1 -- A -- A_Inv_Even_Children_1;
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
F_Inv_Parent_2 -- F;
D_Inv_Parent_2 -- D;
E_Inv_Parent_2 -- E;
}
and the result:
EDIT: I may have misunderstood your intention how you want to connect the third level - if so, replace
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
with
F_Inv_Parent_2 -- D_Inv_Parent_2[ style = invis ];
D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
which gives you
EDIT No. 2, in response to yr comment:
Adding weight to the edge helps straightening it - I give the full code even though only two lines have changed (plus comments), for easier copy & paste:
graph G
{
splines = ortho;
rankdir = LR;
// node definitions
node [ shape="box" fixedsize = true width = 4 height = 1];
C
{ rank = same; B A }
{ rank = same; F D E }
node [ shape="point" width = 0 height = 0 ];
{ rank = same;
B_Inv_Parent_1
C_Inv_Even_Children_0
A_Inv_Parent_1 }
{ rank = same;
F_Inv_Parent_2
D_Inv_Parent_2
A_Inv_Even_Children_1
E_Inv_Parent_2 }
// edges
C -- C_Inv_Even_Children_0;
B_Inv_Parent_1 -- C_Inv_Even_Children_0 -- A_Inv_Parent_1;
// add extra weight to the continouous connection between four levels:
B_Inv_Parent_1 -- B -- F_Inv_Parent_2 -- F[ weight = 10 ];
// no weight here:
A_Inv_Parent_1 -- A -- A_Inv_Even_Children_1;
F_Inv_Parent_2 -- D_Inv_Parent_2[ style = invis ];
D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
// F_Inv_Parent_2 -- F; ### moved
D_Inv_Parent_2 -- D;
E_Inv_Parent_2 -- E;
}
Which gives you the disired straight line from B via F_Inv_Parent_2 to F which is actually the grandchild:

Maintain horizontal ordering of nodes in Graphviz

I have the following the dot file contents:
digraph G {
start -> {a0, b0} -> end;
start -> c0 -> c1 -> c2 -> end;
start -> d0 -> d1 -> d2 -> end;
start -> {e0, f0} -> end;
subgraph cluster_test {
{
rank = same;
a0; b0; c0; d0; e0; f0;
}
{
rank = same;
c1; d1;
}
{
rank = same;
c2; d2;
}
}
}
The resulting graph is as follows:
What I want is for the ordering of level 0 nodes to be maintained, i.e, I want a0, b0 to come before c0, d0 in the horizontal direction.
How do I achieve this?
Empty nodes, edges with weight and explicit ordering of the top row in the cluster helps. See code below with annotations:
digraph so
{
// we define all nodes in the beginning, before edges and clusters
// may not be essential but I think it's good practice
start
a0 b0 c0 d0 e0 f0
c1 d1
c2 d2
end
// we define "empty" nodes that can be used to route the edges
node[ shape = point, height = 0 ];
ax bx ex fx
subgraph cluster_test
{
// we need to keep explicit order of the top nodes in the cluster
{ rank = same; a0 -> b0 -> c0 -> d0 -> e0 -> f0[ style = invis ] }
// the original layout in the cluster, empty nodes added at the bottom
{ rank = same; c1 d1 }
{ rank = same; ax bx c2 d2 ex fx }
c0 -> c1 -> c2;
d0 -> d1 -> d2;
// routing through invisible nodes keeps the position of all other nodes
// edges with no arrowheads, strong weight to keep it vertical
edge[ dir = none, weight = 10 ]
a0 -> ax;
b0 -> bx;
e0 -> ex;
f0 -> fx;
}
// connecting to the start and end node, normal edges again
edge[ weight = 1, dir = forw ];
start -> { a0 b0 c0 d0 e0 f0 }
{ ax bx c2 d2 ex fx } -> end;
}
which gives you

Alignment issue with two clusters using Graphviz and Dot

I'm trying to get the following dot file to output two subgraphs. I want the bLoop node in cluster0 to align with the ISR struct in cluster 2. I'm using an invisible node to do this now, but with the unintended consequence of lot of gray space left in cluster0.
Is there a way to do what I want without the invisible node?
I can't post images yet, so here's the link.
digraph G {
ranksep=.75;
nodesep = 1.5;
node [shape = none]
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
ratio=fill;
splines=false;
compound=true;
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
e0[shape=rectangle, style=invis, fixedsize=true, width=.01];
a0 -> a1 -> a2 -> bgLoop;
bgLoop ->e0[style=invis]
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
subgraph cluster2 {
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
concentrate = true;
struct1 -> bgLoop[lhead=cluster0, ltail=cluster4, constraint=true];
bgLoop -> struct1[lhead=cluster4, ltail=cluster0, constraint=true];
struct1 -> e0[style=invis, constraint=true];
start -> a0[lhead=cluster0];
}
you need helper nodes to get the correct rank for struct1.
digraph G {
ranksep=.75;
nodesep = 1.5;
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
compound=true
subgraph cluster2 { rank="max"
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
a0 -> a1 -> a2 -> bgLoop;
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
{node [style=invis]; 0; 1; 2; 3; }
{edge [style=invis]; 0->1->2->3->struct1; }
struct1 -> bgLoop[lhead=cluster0, ltail=cluster2, constraint=false];
bgLoop -> struct1[lhead=cluster2, ltail=cluster0, constraint=false];
start -> a0[lhead=cluster0];
}

Graphviz: how to set 'default' arrow style?

Consider this dot language code:
digraph graphname {
subgraph clusterA {
node [shape=plaintext,style=filled];
1 -> 2 [arrowhead=normal,arrowtail=dot];
2 -> 3 -> X2 -> 5;
6;
7;
label = "A";
color=blue
}
}
In the above example, only the 1 -> 2 connection will have the arrowhead=normal,arrowtail=dot style applied; all the other arrows will be of the "default" style.
My question is - how do I set the arrow style (for the entire subgraph - or for the entire graph), without having to copy paste "[arrowhead=normal,arrowtail=dot];" next to each edge connection?
EDIT: Just for reference - the answer from Jesse didn't contain any code; I wrote that snippet and had it in this space here - for unknown reasons, a moderator cut it off from here and pasted it into Jesse's answer.
Use the edge attribute statement, as stated in the DOT Language documentation.
digraph graphname {
subgraph clusterA {
node [shape=plaintext,style=filled];
edge [arrowhead=normal,arrowtail=dot];
1 -> 2 ;
2 -> 3 -> X2 -> 5;
6;
7;
label = "A";
color=blue
}
}
Just like you did for nodes, but using edge, e.g. edge[style=dashed]

subgraph cluster ranking in dot

I'm trying to use graphviz on media wiki as a documentation tool for software.
First, I documented some class relationships which worked well. Everything was ranked vertically as expected.
But, then, some of our modules are dlls, which I wanted to seperate into a box. When I added the nodes to a cluster, they got edged, but clusters seem to have a LR ranking rule. Or being added to a cluster broke the TB ranking of the nodes as the cluster now appears on the side of the graph.
This graph represents what I am trying to do: at the moment, cluster1 and cluster2 appear to the right of cluster0.
I want/need them to appear below.
<graphviz>
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
</graphviz>
The layout is an attempt by Dot to minimise the overall height.
One reason for the more compact than required layout is the use of the edge that goes in the reverse direction from dll1_a to B1. It tries to pull the cluster as close back to the destination node as possible. To avoid this edge affecting the graph, either relax the constraint on the upwards edges as shown, or draw the edge in the forward direction and use the dir attribute to reverse the arrow.
This will help with many layouts but it alone is not sufficient to fix the example given. To prevent Dot from maintaining the compact layout it prefers you can add a minlen attribute to edges that should remain (near) vertical. This may be difficult to calculate in general but is practical for manually tuned layouts.
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [constraint = false];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
My experience shows that constraint=false commonly gives unnecessarily convoluted edges. It seems that weight=0 gives better results:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [weight = 0];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
This will produce the graph you are looking for:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph {
rankdir="TB"
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
}
dll1_A -> dll2_A;
}
What this does is creat a subgraph that is used only for layout purposes to provide the top to bottom ordering that you desire.

Resources