In Graphviz, how to layout subgraphs in different orientations? - graphviz

There is rankdir for the global graph which sets the orientation of the layout. What about subgraph or cluster - is there a way to have one subgraph in TD layout and another subgraph in BT?
How to achieve the graph in the attached image with following (incorrect) code?
digraph G {
subgraph cluster0 {
rankdir="TD";
A; B;
A -> B;
}
subgraph cluster1 {
rankdir="BT"; // this doesn't produce the desired output
C; D;
D -> C;
}
}

You cannot do that, rankdir is only allowed at top level (graph)
but in simple cases you can work around it by
to go in opposite direction:
C->D[dir=back]
to go in to the side:
{rank=same C D}

Related

DOT graph from superstate to substate

I'd like to generate the DOT code to draw the equivalent state machine diagram shown.
I going to be created programmatically, I've got the transitions between states and superstates done. ButI need a bit of help with this:
This gives me an initial transition, but the State1 should be the cluster:
digraph {
compound=true;
node [shape=Mrecord]
rankdir="LR"
subgraph clusterOpen
{
label = "State1"
State2
}
State1 -> State2 [style="solid"];
node [shape = point label="" ] i ->State1
}
Normally Graphviz programs try hard to avoid placing nodes on top of other nodes. But you can place nodes anywhere you like if you explicitly provide a pos attribute for each node (see https://graphviz.org/faq/#FaqDotWithNodeCoords).
The program that creates your input files should calculate a pos attribute for each node. (Remember that pos coordinates are in points, while node sizes are in inches!). You can probably skip calculating the splines for the edges and just let neato do that.
This program:
digraph {
graph [bb="0,0,482.8,337"];
node [label="\N"];
State1 [height=4.0139,
label="{State 1|\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n}",
pos="162,144.5",
shape=Mrecord,
width=4.5];
State2 [height=1.3333,
label="{State 2|\n\n\n\n}",
// pos="403,144.5",
pos="220,88",
shape=Mrecord,
width=1.6944];
xp3 [height=0.05,
label="",
// pos="429,331",
pos="0,194",
shape=point,
// style=dotted,
style=invis,
width=0.05];
r1 [height=0.16667,
label="",
// pos="455,331",
pos="154,194",
shape=square,
width=0.16667];
xp4 [height=0.05,
label="",
// pos="481,331",
pos="0,88",
shape=point,
// style=dotted,
style=invis,
width=0.05];
xp1 [height=0.16,
label="",
pos="162,331",
shape=point,
width=0.16];
xp1 -> State1:n [pos="e,162,288.5 162,325.23 162,319.09 162,308.89 162,298.63",
style=dashed];
xp2 [height=0.16,
label="",
// pos="403,331",
pos="220,194",
shape=point,
width=0.16];
xp2 -> State2:n [pos="e,403,192.5 403,325.19 403,307.39 403,251.8 403,202.57"];
// manually added:
xp3 -> r1 [label="Trigger 1" dir=none ]
xp4 -> State2 [label="Trigger 2" ]
}
Run with this command line:
neato -n -Tpng stateDiagram.dot >stateDiagram.png
Produces this graph:

Graphviz not rendering labels nor encompassing rectangles

I recently started using Graphviz.
I'm working on a graph with labels, but they're not showing up. Neither are my sub-groups being surrounded by an encompassing rectangle.
Here's my code:
digraph system {
subgraph Machine_001 {
label = "Machine_001";
subgraph Machine_001_Service_001 {
label = "Service_001 on Machine_001";
node [shape=record];
Machine_001_PORT_10 [label = "Port 10"];
Machine_001_PORT_11 [label = "Port 11"];
Machine_001_PORT_12 [label = "Port 12"];
Machine_001_PORT_13 [label = "Port 13"];
{rank=same Machine_001_PORT_10 Machine_001_PORT_11 Machine_001_PORT_12 Machine_001_PORT_13}
Machine_001_PORT_10 -> Machine_001_PORT_11;
Machine_001_PORT_12;
Machine_001_PORT_13;
}
}
subgraph Machine_002 {
label = "Machine_002";
subgraph Machine_002_Service_001 {
label = "Service_001 on Machine_002";
node [shape=record];
Machine_002_PORT_50 [label = "Port 50"];
Machine_001_PORT_11 -> Machine_002_PORT_50;
}
}
}
Using http://www.webgraphviz.com/ to render it, I would expect labels, but those are not shown.
On the other hand, an example like this does show labels and an encompassing rectangle:
digraph D {
subgraph cluster_p {
label = "Parent";
subgraph cluster_c1 {
label = "Child one";
a;
subgraph cluster_gc_1 {
label = "Grand-Child one";
b;
}
subgraph cluster_gc_2 {
label = "Grand-Child two";
c;
d;
}
}
subgraph cluster_c2 {
label = "Child two";
e;
}
}
}
Frankly, I don't see what the problem is. I gave it a label, and I nested it. Which is exactly what the working example does.
What am I missing?
Looks like placing "cluster_" in front of the names in the subgraphs solves the problem, so the following is not 100% an answer as I think, my interpretation of the definitions, it should be possible.
In https://www.graphviz.org/doc/info/lang.html some definitions are given (left out some parts by me!):
subgraph : [ subgraph [ ID ] ] '{' stmt_list '}'
An ID is one of the following:
Any string of alphabetic ([a-zA-Z\200-\377]) characters, underscores ('_') or digits ([0-9]), not beginning with a digit;
The third role for subgraphs directly involves how the graph will be laid out by certain layout engines. If the name of the subgraph begins with cluster, Graphviz notes the subgraph as a special cluster subgraph. If supported, the layout engine will do the layout so that the nodes belonging to the cluster are drawn together, with the entire drawing of the cluster contained within a bounding rectangle. Note that, for good and bad, cluster subgraphs are not part of the DOT language, but solely a syntactic convention adhered to by certain of the layout engines.
So it looks like that the names of the subgraphs are a bit limited in this case.
Maybe that and issue at https://gitlab.com/graphviz/graphviz/issues can help

how do I add arbitrary, positioned, text/symbols to a graphviz diagram?

I would like to have an "implies" arrow between the two graphs here
digraph G {
subgraph case {
x;
left [shape=diamond];
right [shape=diamond];
left -> x;
right -> x;
}
subgraph case_ {
x_;
left_ [shape=diamond];
right_ [shape=diamond];
left_ -> x_;
right_ -> x_;
}
}
Trying to GraphViz - How to connect subgraphs? doesn't work because I'm using the dot algorithm. But I don't need anything too fancy since I have a bunch of diagrams like this where there is a "before" and "after" state and I want to put some visual indicator.

Can I have different font style/sizes in the same graphviz record?

I have the following simple graph and I want to have only the text GetArea() in italics. Is this possible?
digraph {
rankdir = BT;
node [shape=record];
cPolygon [label="{cPolygon|GetArea()}"];
{rank=same; cSquare cTriangle}
cSquare -> cPolygon;
cTriangle -> cPolygon;
}
I think you should use HTML like labels:
digraph {
rankdir = BT;
node [shape=record];
cPolygon [label=<<table border="0"><tr><td>cPolygon</td></tr><tr><td><i>GetArea()</i></td></tr></table>>];
{rank=same; cSquare cTriangle}
cSquare -> cPolygon;
cTriangle -> cPolygon;
}
yields
edit
a horizontal row:
...
cPolygon [label=<<table border="0"><tr><td>cPolygon</td></tr><hr/><tr><td><i>GetArea()</i></td></tr></table>>];
...

Graphviz crossing edges

I am trying to avoid the crossing of the lines between 20->40 and 30->70. Does anyone know how to do this? I am using single points to straighten out the edges but I would have expected the rendering engine to avoid these edges to overlap. Here is my dot code:
digraph {
graph [splines="ortho", nodesep = "1", overlap = false];
node [shape=rectangle, color=lightgrey, style=filled ];
10
20
30
40
50
60
70
80
90
node[shape=none, width=0, height=0 label=""];
edge[dir=none];
{rank=same;
p1->10
10->p2
}
p1->20
p2->30
{rank=same;
p3->40
40->p4
}
p3->50
p4->60
{rank=same;
p5->70
70->p6
}
p5->80
p6->90
20->40
30->70
}
I wanted to post an image, but stackoverflow does not allow me to do this... You can see what I mean when you copy the code into: http://stamm-wilbrandt.de/GraphvizFiddle/
I really appreciate your help on this!
You could give graphviz a hint by adding an invisible edge between p4 an dp5:
{
rank=same;
p3 -> 40;
40 -> p4;
p4 -> p5 [style=invis]; // new invisible edge
p5 -> 70;
70 -> p6;
}
If you are not able to add invisible edges (dynamic graph generation), make sure nodes which are part of a subgraph do appear first within the subgraph, and therefore avoid upfront node definitions.
In this example, I removed the node definitions in the beginning of the script and inlined the style of the elbow-joint nodes.
Here's the GraphvizFiddle
digraph {
graph [splines="ortho", nodesep = "1", overlap = false];
node [shape=rectangle, color=lightgrey, style=filled ];
//node[shape=none, width=0, height=0, label=""];
edge[dir=none];
{
rank=same;
p1[shape=none, width=0, height=0, label=""];
p2[shape=none, width=0, height=0, label=""];
p1->10
10->p2
}
p1->20
p2->30
{
rank=same;
p3[shape=none, width=0, height=0, label=""];
p4[shape=none, width=0, height=0, label=""];
p3->40
40->p4
}
p3->50
p4->60
{
rank=same;
p5[shape=none, width=0, height=0, label=""];
p6[shape=none, width=0, height=0, label=""];
p5->70
70->p6
}
p5->80
p6->90
20->40
30->70
}

Resources