Graphviz Dot placing node inside subgraph even though it was defined elsewhere - dot

I am trying to make a dot script generator for a homework problem, it's going well except I have this issue where some nodes that are not defined in subgraphs are being placed in them. For example the following dot script:
digraph dg {
compound=true;
labelloc="t";
label="test.cpp";
Vehicle;
Make;
subgraph clusterFord {
label="Ford"
Ford[shape="none"][style="invis"][label=""];
Mustang -> Vehicle [label="private"];
Thunderbird -> Vehicle [label="private"];
}
Ford -> Make [label="public"][ltail ="clusterFord"];
subgraph clusterChevrolet {
label="Chevrolet"
Chevrolet[shape="none"][style="invis"][label=""];
Camero -> Vehicle [label="private"];
}
Chevrolet -> Make [label="public"][ltail ="clusterChevrolet"];
}
Generates this image:
The "Vehicle" node is supposed to be outside of the "Ford" subrgraph. What am I missing here?

This will give what you want:
digraph dg {
compound=true;
labelloc="t";
label="test.cpp";
subgraph clusterFord {
label="Ford"
Ford[shape="none"][style="invis"][label=""];
Mustang
Thunderbird
}
subgraph clusterChevrolet {
label="Chevrolet"
Chevrolet[shape="none"][style="invis"][label=""];
Camero
}
Ford -> Make [label="public"][ltail ="clusterFord"];
Chevrolet -> Make [label="public"][ltail ="clusterChevrolet"];
Mustang -> Vehicle [label="private"];
Thunderbird -> Vehicle [label="private"];
Camero -> Vehicle [label="private"];
}

Related

graphviz no line break (.dot)

I'm working with graphviz on LinuxArch. If I print my .svg I use the command dot -Tsvg example.dot -o exampale.svg. My graph is printed and that works fine. I read some other questions on that topic Link 1, Link 2, also the documentation on graphviz.org didn't give me a clue.
Question: I want to line break in a node. How I can do it?
The following code is working, but not always. Full Code:
digraph G {
//general settings
graph [fontname="Arial"];
node [fontname="Arial"];
edge [fontname="Arial"];
//data of graph
subgraph cluster_1
{
label = "Cluster 1";
style=filled;
color="#E0E0E0";
margin=20;
node [style=filled,color=white];
"I'm text" -> "I want a donat.";
"I want a donat." -> a1[label="Love food,\nlove it so much!"];
}
subgraph cluster_2
{
label = "Cluster 2";
style=filled;
color="#E0E0E0";
margin=20;
node [style=filled,color=white];
Start -> a2[label="sit amet,\nconsetetur"];
a2 ->
{
b2[label="Lorem Impsum\ndollar sit amet."];
}
}
}
Result: (Green marked is working and the problem is Red marked.)
It seems to me you are confusing node and edge declarations.
Try changing the lines
"I'm text" -> "I want a donat.";
"I want a donat." -> a1[label="Love food,\nlove it so much!"];
into
a1[label="Love food,\nlove it so much!"];
"I'm text" -> "I want a donat.";
"I want a donat." -> a1;
What this actually does is that a1 is defined as a node with a label. The node id a1 can then be used to declare edges between nodes.
Here is an other example, with explicit node declarations for all nodes, and then the edge declarations using the node identifiers:
imtext[label="I'm text"];
donat[label="I want a donat."];
a1[label="Love food,\nlove it so much!"];
imtext -> donat -> a1;

Edge pointing at edge with Graphviz and Dot

I would like to point an edge towards another edge in graphviz using the dot format.
What I got so far:
digraph G {
Hello->dummy;
dummy->World;
dummy[shape=point width=0];
Test->dummy;
}
which produces
what I would like to get is something more similar to this:
Any ideas how to do so?
Maybe rank = same does the trick?
digraph G
{
{ rank = same; Test; dummy } // dummy and Test on the same level
dummy[ shape = point, width = 0 ]; // connector
Hello -> dummy[ arrowhead = none ]; // remove arrowhead to connector
dummy -> Test[ dir = back ]; // you want Test on the right side
dummy -> World;
}
yields
[arrowhead=none] with you dummy middleman does the job for me.
digraph G {
Hello->dummy[arrowhead=none];
dummy->World;
dummy[shape=point width=0];
Test->dummy;
}
I've added feature request for it in Graphviz's issue tracker.

Horizontally placing clusters with node outside

I'm fiddling around in Graphviz trying to make a graph of an architecture, but no matter what I try, dot always seems to want to connect some of the nodes with the longest possible path.
Here's a sketch of how I want it to more or less look:
Here's how it actually looks:
And here's the code in question:
digraph ngsys {
graph [dpi = 300];
rankdir="LR";
subgraph cluster_client {
style=filled;
color=lightgrey;
node [style=filled, color=white];
ngcontroller -> ngmodel;
ngmodel -> ngview;
label="Client";
}
ngview -> user [style=dashed];
user -> ngcontroller [style=dashed];
subgraph cluster_server {
style=filled;
color=lightgrey;
node [style=filled, color=white];
apicontroller -> apimodel;
label="Server";
}
ngcontroller -> apicontroller [label="REST", dir=both, style=dashed];
ngmodel [label="NG-Model" shape=box];
user [label="User"];
ngview [label="NG-View", shape=box];
ngcontroller [label="NG-Controler", shape=box];
apicontroller [label="API-Controller", shape=box];
apimodel [label="API-Model", shape=box];
}
Is there anything I can do to make the output look a little more akin to the sketch?
a little change fixes the order:
ngview -> ngmodel [dir=back];
ngmodel -> ngcontroller [dir=back];
another little change improves the look:
nodesep=1;
...
ngview:s -> user [style=dashed];
user -> ngcontroller:s [style=dashed];

edge connections overlap and don't space out

I'm trying too see whether I can use the Dot programming language to apply it to an old project of mine.
The task is simple: create a high quality graph with ease.
Unfortunately, while it has been fairly easy to implement the details of my graph, I wound up having to take loads of time just for adjusting the layout.
Furthermore, it is quite unclear to me how the order of my instructions impact my graph, but it actually looks like putting the last instruction of my code at the beginning produces a completely different output!
Here is the code:
digraph {
TOP [shape=doublecircle]
TOP->TOP->{rank=same a->b->c->b->a}
a:s->c:s
a:nw->a:sw
c:ne->c:se
b:s->b:s
}
so. firstly, i finally mastered the 'get nodes to be on the same horizontal/vertical line' through ranking...
I also kinda fixed the problem of edges doing stupid interconnections (all free space below the graph for connections, and the edge winds up zig-zagging through the whole graph in an awkward way and overlapping everything?) using the direction indicators ":e" and the such (i believe they are called routes...), but it looks like graphviz isn't using them in a smart way, because the result looks funny to me.
Here is the output, how do I get it to avoid edge overlappings and make enough space for future (long) labels?
(made with dot -Tpng test.dot -o test.png)
(also, I would need to add a c->a edge at the bottom too, but adding one the "normal" way ruined everything)
You can use invisible nodes to "re-route" your edges as desired (edited as per comments below):
digraph
{
/* layout */
// node width to create space for longer labels
node [ width = 1.75 ];
{ rank=same; a; b; c }
/* nodes */
t [ label = "TOP", shape = doublecircle, width = 1];
a [ label = "short" ];
b [ label = "medium" ];
c [ label = "rather l o n g"]
// invisible nodes to 're-route' the edges
x [ style = invis, shape = point, width = 0 ];
y [ style = invis, shape = point, width = 0 ];
/* edges */
t -> t;
t -> { a b c }
t -> { a b c } [dir = back ]; // added for reverse arrows
a -> b -> c -> b -> a;
a:nw -> a:sw;
c:ne -> c:se;
b:s -> b:s;
// put the invisible nodes at the desired places with invisible edges
b -> x -> y [ style = invis ];
// edges to invisible nodes must not have heads
c:sw -> x [ arrowhead = "none" ];
x -> a:se;
a:s -> y [ arrowhead = "none" ];
y -> c:s;
}
yields

Graphviz subgraph alignment issue

I am trying to force the nodes to have a specified position in the graph. While doing so, the different sub-graphs are not aligned properly. The code to generate this graph is :
digraph {
rankdir=LR;
labeljust="l";
subgraph cluster0{
label="t=0"
n_3_0_0[label="192.168.8.6"
pos="15,12!"
];
n_3_0_1[label="192.168.8.3"
pos="10,10!"
];
n_3_0_0 -> n_3_0_1 ;
n_3_0_1 -> n_3_0_0 ;
};
subgraph cluster1{
label="t=5"
n_3_1_0[label="192.168.8.6"
pos="15,12!"
];
n_3_1_1[label="192.168.8.3"
pos="10,10!"
];
n_3_1_2[label="192.168.8.9"
pos="10,12!"
];
n_3_1_0 -> n_3_1_1 ;
n_3_1_1 -> n_3_1_0 ;
};
subgraph cluster2{
label="t=10"
n_3_2_0[label="192.168.8.6"
pos="14,10!"
];
n_3_2_1[label="192.168.8.3"
pos="10,10!"
];
n_3_2_2[label="192.168.8.9"
pos="15,11!"
];
n_3_2_3[label="192.168.8.8"
pos="18,12!"
];
n_3_2_0 -> n_3_2_1 ;
n_3_2_2 -> n_3_2_3 ;
n_3_2_1 -> n_3_2_0 ;
n_3_2_3 -> n_3_2_2 ;
};
}
I compiled this code by forcing the node position:
dot -Kfdp -n -Tpng -o sample.png test2.dot
The output graph is:
http://imageshack.us/photo/my-images/826/samplebg.png/
The problem with the output I got is:
1. the subgraph are NOT displayed in sequence of t=0, t-5, t=10...
2. the subgraph are NOT aligned to left.
I need to have output graph like this:
http://imageshack.us/photo/my-images/253/needed.png/
Thnak You.
Since you already precalculated the positions of all the nodes, you don't really need fdp - you just nead a layout which respects the pos attribute.
So you could generate the output like this:
neato -Tpng sourcedot.gv -O
But you'd have to adjust node positions before that, in order to have the subgraphs correctly stacked and not super-posed:
digraph {
rankdir=LR;
labeljust="l";
subgraph cluster0{
label="t=0"
n_3_0_0[label="192.168.8.6"
pos="15,4!"
];
n_3_0_1[label="192.168.8.3"
pos="10,2!"
];
n_3_0_0 -> n_3_0_1 ;
n_3_0_1 -> n_3_0_0 ;
};
subgraph cluster1{
label="t=5"
n_3_1_0[label="192.168.8.6"
pos="15,7!"
];
n_3_1_1[label="192.168.8.3"
pos="10,5!"
];
n_3_1_2[label="192.168.8.9"
pos="10,7!"
];
n_3_1_0 -> n_3_1_1 ;
n_3_1_1 -> n_3_1_0 ;
};
subgraph cluster2{
label="t=10"
n_3_2_0[label="192.168.8.6"
pos="14,8!"
];
n_3_2_1[label="192.168.8.3"
pos="10,8!"
];
n_3_2_2[label="192.168.8.9"
pos="15,9!"
];
n_3_2_3[label="192.168.8.8"
pos="18,10!"
];
n_3_2_0 -> n_3_2_1 ;
n_3_2_2 -> n_3_2_3 ;
n_3_2_1 -> n_3_2_0 ;
n_3_2_3 -> n_3_2_2 ;
};
}
Resulting in
(Some minor adjustments still needed for the label of the middle subgraph)
Or just use dot and let it align the nodes, too:

Resources