How to make an edge with both direction in GraphViz?
I am trying to make an curved edge with both direction.
But the only plot I can make is:
I want to make the edge between x1 and x2 curved with both direction.
The code I used:
digraph {
rankdir=LR
node [shape=box ]
x1;x2
node [shape=oval ]
y
x1->y[dir=back label=0.77]
x2->y[dir=back label=0.42]
x1:w -> x2:w[dir=both constraint=false]
}
I would appreciate any help.
I think there should be a better solution but the following did work for me:
digraph {
rankdir=LR
node [shape=box ]
x1;x2
node [shape=oval ]
y
x1->y[dir=back label=0.77]
x2->y[dir=back label=0.42]
x1:w -> x2:w[dir=both constraint=false]
x2:w -> x1:w[dir=both constraint=false]
}
based on the answer from Changing edge direction in dot:
digraph g {
rankdir=LR
node [shape=box ]
{rank=same x1;x2}
node [shape=oval ]
y
x1 -> y[dir=back label=0.77]
x2 -> y[dir=back label=0.42]
x1:w -> x2:w[dir=both label=0.34]
}
Related
Is there a way to control the spacing between edges in dot, similar to the nodesep attribute in the other graphviz layout engines? I would like to keep using dot as the layout engine.
By edges I mean either multi-edges or multi-coloured edges, like in the following example. I would like to decrease the space between the a->b edges or increase the space between the c->d edges.
digraph G {
nodesep = "0.15"
a -> b [dir=none color="red"]
a -> b [dir=none color="blue"]
a -> b [dir=none color="green"]
c -> d [dir=none color="green:red:blue"]
}
In dot, the nodesep attribute does not have the desired effect.
Assuming a white background, add white (invisible) lines to change the apparent spacing:
digraph G {
nodesep = "0.15"
c -> d [dir=none color="green:white:white:white:red:white:white:white:blue"]
}
Giving:
There seems to be a bug in that code, only one leg is thicker (penwidth).
So, this solution used ports:
digraph G {
// nodesep = "0.15"
splines=false
edge[penwidth=7]
a:sw -> b:nw [dir=none color="red"]
a -> b [dir=none color="blue"]
a:se -> b:ne [dir=none color="green"]
c -> d [dir=none color="green:white:white:white:red:white:white:white:blue"]
}
Giving:
The best solution I've found is to add transparent edges. That way, this solution works regardless of background colour. Since the edges are transparent, overlap is not a problem and all the coloured edges have the same width.
digraph G {
c -> d [
dir=none
penwidth=5
color="red:transparent:transparent:green:transparent:transparent:blue"
]
}
Produces:
This works for an arbitrary number of edges, and the spacing can be controlled by changing the number of transparent edges between each coloured edge.
I have some digraph, which I have to use the [style=invis] to define the node order; but I found the original vertical edge is impacted by [style=invis], below is the digraph:
digraph G {
edge [dir=none];
R_35->p92;
R_35->p93;
c_p92 [shape=diamond];
{rank=same; p92 -> c_p92};
R_38 [shape=box];
c_p92->R_38;
R_38->p21;
c_p93 [shape=diamond];
{rank=same; p93 -> c_p93};
R_36_0 [shape=box];
R_36_0->p96;
R_36_1 [shape=box];
R_36_1->p97;
R_36_0->R_36_1
c_p93->R_36_1;
c_p92->p93[style=invis];
R_38->R_36_0[style=invis];
p21->p96->p97[style=invis];
{rank=same; p92; c_p92; p93;c_p93;};
{rank=same; R_38; R_36_0; R_36_1};
{rank=same; p21; p96; p97;};
}
I hope the edges from node "c_p92" to "R_38", from node "R_36_1" to "p97" are vertical, but they are impacted by the [style=invis] that, it seems they are attracted by each other and the edge is tilt. Can any one help me to figure out how to make these edges vertical?
You could assign the same group to all nodes of a 'string' of nodes should be aligned vertically - for example group=a for nodesc_p29, R38, p21 and group=b for nodes c_p93, R_36_1, p97:
digraph G {
edge [dir=none];
R_35->p92;
R_35->p93;
c_p92 [shape=diamond, group=a];
{rank=same; p92 -> c_p92};
R_38 [shape=box, group=a];
c_p92->R_38;
p21[group=a];
R_38->p21;
c_p93 [shape=diamond, group=b];
{rank=same; p93 -> c_p93};
R_36_0 [shape=box];
R_36_0->p96;
R_36_1 [shape=box, group=b];
p97[group=b];
R_36_1->p97;
R_36_0->R_36_1
c_p93->R_36_1;
c_p92->p93[style=dotted];
R_38->R_36_0[style=dotted];
p21->p96->p97[style=dotted];
{rank=same; p92; c_p92; p93;c_p93;};
{rank=same; R_38; R_36_0; R_36_1};
{rank=same; p21; p96; p97;};
}
Graphivz tries to align nodes of the same group.
(changed invis edges to dotted to see what's what)
A good way to get vertical edges (assuming rankdir=TB) is to use the group attribute (https://graphviz.org/docs/attrs/group/ and https://forum.graphviz.org/t/a-question-about-the-group-attribute-what-does-straight-mean/548/2). Like so:
digraph G {
edge [dir=none];
R_35->p92;
R_35->p93;
c_p92 [shape=diamond group=V1];
{rank=same; p92 -> c_p92};
R_38 [shape=box group=V1];
c_p92->R_38 [color=red];
R_38->p21;
c_p93 [shape=diamond];
{rank=same; p93 -> c_p93};
R_36_0 [shape=box];
R_36_0->p96;
R_36_1 [shape=box group=YY];
R_36_1->p97 [color=red];
R_36_0->R_36_1
c_p93->R_36_1;
c_p92->p93[style=invis];
R_38->R_36_0[style=invis];
p21->p96->p97[style=invis];
{rank=same; p92; c_p92; p93;c_p93};
{rank=same; R_38; R_36_0; R_36_1};
{rank=same; p21; p96; p97 [group=YY]}
}
Giving:
I've got two cluster subgraphs in GraphViz, with edges between the nodes in each subgraph. I'd like to be able to influence the top-to-bottom ordering of the nodes within the second subgraph so as to achieve symmetry across the horizontal axis, and have the nodes in the second subgraph ordered top-to-bottom as a, b, c, d.
digraph {
rankdir=LR
subgraph cluster_1 {
bx -> cx
by -> cy
}
subgraph cluster_2 {
a; b; c; d
}
bx -> a
cx -> b
cy -> c
by -> d
}
Right now, I get this:
Changing the ordering of node appearance within the cluster_2 subgraph doesn't seem to matter, nor does changing the ordering of the cross-cluster edges at the bottom.
Is there any way to get GraphViz to produce what I want here?
You can add some scaffolding edges and/or nodes i.e. invisible edges/nodes but it can be a bit triggy especially when clusters are involved
e.g.:
digraph {
rankdir=LR
subgraph cluster_1 {
bx -> cx
by -> _d [dir=none]
by -> cy
_a[shape=point height=0]
_d[shape=point height=0]
bx -> _a [dir=none]
}
subgraph cluster_2 {
a; b; c; d
}
//bx -> a
cx -> b
cy -> c
//by -> d
_a->a
_d->d
}
I'm trying to draw bigraphs in GraphViz (something like this)
Is it possible to nest nodes directly in GraphViz?
If not is it possible to change the shape of a subgraph/cluster?
I have found a post about how to import images of graphs into nodes but that seems like more effort than drawing them in powerpoint.
I can also make clusters visible, but they will include nodes from outside the cluster and as far as I can tell have a fixed shape.
Thanks for your help.
Nest nodes is impossible, but nest clusters is possible.
Subgraph/cluster has some predefined styles. Also nodes has predefines shapes. I don't know about manual editing path of border shapes for nodes in graphviz in different layouts (or alternatives like representing the border as a chain of nodes), maybe someone else can tell us.
You can get nested nodes in neato layout engine, but in fact they will be nested only visually, because you just set their coordinates with pos attribute, which means they overlap each other.
Example image:
and script:
graph {
layout=neato
node [shape=circle pin=true ]
foo [height=0.6 pos="0.7,1.5" ]
bar [height=2 pos="1,2" ]
baz [height=1 pos="2,2" ]
}
You can import images as backgrounds into nodes as described in this answer. For example for Windows you can use this official archive, it comes with a cairo.dll, which will avoid errors like Warning: No loadimage plugin for "jpeg:cairo" when you run the command $ dot -Tpng input.dot -o output.png.
The image from your question can be drawn like this:
Script:
digraph {
graph [
layout=dot,
ranksep=1,
overlap=false,
compound=true, // to enable `lhead`, `ltail` features
newrank=true, // to enable ranking between nodes in clusters
splines=true,
splines=curved]
edge[color=lime arrowhead=none]
node[shape=plaintext]
y0 [label=<<FONT><I>y</I><SUB>0</SUB></FONT>>]
y1 [label=<<FONT><I>y</I><SUB>1</SUB></FONT>>]
y2 [label=<<FONT><I>y</I><SUB>2</SUB></FONT>>]
x0 [label=<<FONT><I>x</I><SUB>0</SUB></FONT>>]
x1 [label=<<FONT><I>x</I><SUB>1</SUB></FONT>>]
subgraph cluster_r0{
style="rounded, dashed"
margin=20
label=<<FONT><I>r</I><SUB>0</SUB></FONT>>
v2 [shape=circle]
noname_dot[shape=point height=0]
subgraph cluster_v0{
style="rounded"
label=<<FONT><I>v</I><SUB>0</SUB></FONT>>
invis_dot_1 [style=invis shape=point]
subgraph cluster_v1{
style="rounded";
label=<<FONT><I>v</I><SUB>1</SUB></FONT>>
subgraph cluster_s0{
label=<<FONT><I>s</I><SUB>0</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_2 [style=invis shape=point]
}
}
}
}
y0 -> noname_dot
noname_dot -> invis_dot_2 [lhead="cluster_v1"]
noname_dot -> invis_dot_1 [lhead="cluster_v0"]
noname_dot -> v2 [constraint=false]
y1 -> v2
subgraph cluster_r1{
style="rounded, dashed"
margin=20
label=<<FONT><I>r</I><SUB>1</SUB></FONT>>
noname_dot_2 [shape=point height=0]
subgraph cluster_s3{
label=<<FONT><I>s</I><SUB>3</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_s3 [style=invis shape=point]
}
subgraph cluster_v3{
style="rounded"
label=<<FONT><I>v</I><SUB>3</SUB></FONT>>
subgraph cluster_s2{
label=<<FONT><I>s</I><SUB>2</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_s2 [style=invis shape=point]
}
}
}
y2 -> noname_dot_2
noname_dot_2 -> x0
v2 -> noname_dot_2 [weight=0]
noname_dot_2 -> invis_dot_s2 [lhead="cluster_v3"]
invis_dot_s2 -> x1 [ltail="cluster_v3"]
// Vertical alignment (`rank`) of the desired nodes:
{rank=same; noname_dot; noname_dot_2; v2 }
{rank=same; invis_dot_s3; invis_dot_s2 }
{rank=same; x0; x1;}
{rank=same; y0; y1; y2;}
}
For example:
digraph G {
rankdir = TB;
subgraph A {
a -> {a0, a1};
};
subgraph B {
b -> {b0, b1, b2};
};
};
I want to put B at the bottom of A, how to do it?
You'll have to tell graphviz that the subgraphs are not equal. One way to do it is simply to add invisible edges between the graphs:
digraph G {
rankdir = TB;
subgraph A {
a -> {a0, a1};
};
subgraph B {
b -> {b0, b1, b2};
};
a0 -> b [style=invis];
a1 -> b [style=invis];
};
By adding two invisible edges the subgraphs are neatly aligned.