How to control node placement in graphviz (i.e. avoid edge crossings)
Asked Answered
K

5

53

I'm using graphviz (dot) to generate the graph you can see below. The node in the lower left corner (red ellipse) causes annoyance as its edges cross several edges of the adjacent node. Is there a way to restrain node placement to a certain area?

graph with edge crossing several other edges

Kigali answered 19/3, 2010 at 10:48 Comment(0)
E
10

I'm not aware of any means by which to control the placement of individual nodes. It doesn't really make sense, because in order to do that you'd need to know what the final graph will look like, yet placing one node manually would then change how the rest of the graph is rendered.

I solved this problem by changing the order in which my nodes are defined in the .dot file, and tweaking the nodesep and ranksep attributes at the graph level. It's a process of refinement - tweaking a few things at a time until it looks right.

You might also render the graph as SVG, then import it into Visio (or another editor) and manually rearrange the nodes you're not happy with.

Ecumenicism answered 19/3, 2010 at 11:11 Comment(3)
I don't think Visio could edit a generic svg, but Inkscape could.Greywacke
@GringoSuave: Inkscape can indeed, but the edges do not follow if you move a node. This makes it impractical for anything but very few nodes.Cassell
This is incorrect and should not be the accepted answer. There are answers below with 30 and 20 votes respectively each of which would be a fine accepted answer.Abe
L
65

You could create an invisible constraint, to cause the red node to appear to the left of all other nodes.

redNode -> leftmostNode [style=invis];

Before:

before

After:

after

Linnette answered 11/8, 2011 at 16:19 Comment(1)
That solved my problem. I just wanted something to appear on the other side of something else. Thank you.Crespo
A
35

I like @smokris' [style=invis] trick for persuading graphviz to put things where you want them, by adding edges which affect layout but aren't visible.


Another trick is the constraint attribute, which lets you add edges which are visible but don't affect layout.

If adding a new edge messes up your graph, set [constraint=false] on that edge: now graphviz will ignore it when placing nodes. 🙂

If false, the edge is not used in ranking the nodes. For example, in the graph

digraph G {
    a -> c;
    a -> b;
    b -> c [constraint=false];  
}

the edge b -> c does not add a constraint during rank assignment, so the only constraints are that a be above b and c, yielding the graph:

Armandinaarmando answered 10/5, 2017 at 17:43 Comment(0)
D
31

There is actually a way to control individual node placement - you use the "pos" attribute:

http://www.graphviz.org/doc/info/attrs.html#d:pos

As an example of this, you could write:

n [pos="3,5!"];

That would force node n to be at precisely (3,5).

However, this only works with layout engines "fdp" and "neato".

Dibru answered 30/12, 2010 at 23:19 Comment(3)
The pin attribute (!), is "fdp, neato only" (it doesn't work with dot). So using pos is meaningless with dot unless you bypass the dot layout engine.Kerriekerrigan
@nobar: Hmm, looking at the documentation again it seems you're right - my bad, sorry.Dibru
I noticed that ! also does not work with fdp, although it works with neato. Also, the -s argument that should manage the scaling of the coordinates given in "pos" attributes (default 72.0) does not seem to work (it causes segfaults). In summary: dividing all numbers of the pos attribute by 72.0 and using neato works!Tody
E
10

I'm not aware of any means by which to control the placement of individual nodes. It doesn't really make sense, because in order to do that you'd need to know what the final graph will look like, yet placing one node manually would then change how the rest of the graph is rendered.

I solved this problem by changing the order in which my nodes are defined in the .dot file, and tweaking the nodesep and ranksep attributes at the graph level. It's a process of refinement - tweaking a few things at a time until it looks right.

You might also render the graph as SVG, then import it into Visio (or another editor) and manually rearrange the nodes you're not happy with.

Ecumenicism answered 19/3, 2010 at 11:11 Comment(3)
I don't think Visio could edit a generic svg, but Inkscape could.Greywacke
@GringoSuave: Inkscape can indeed, but the edges do not follow if you move a node. This makes it impractical for anything but very few nodes.Cassell
This is incorrect and should not be the accepted answer. There are answers below with 30 and 20 votes respectively each of which would be a fine accepted answer.Abe
D
0

You can place nodes if you use neato with the -n2 parameter:

`dot -T ${format} -n2 -Goverlap-true -Gsplines=false -Kneato -o ${ output } ${ input }`

e.g.

dot -T png -n2 -Goverlap-true -Gsplines=false -Kneato -o monkey.png monkey.dot

neato expects everything positioned from the bottom left corner in points (1/72 of an inch.

The following dot file places everything as specified, with the small annoyance that positions are always the center of the object

digraph G {
    overlap=true
    bgcolor="transparent"
    node [

        shape=box   
        width=1.2
        height=1.2
        fillcolor="#e9e9e9"
        fontcolor="#333333"
        fontsize=18
        style="filled"
        color="#aaaaaa"
    ];

    edge [
        penwidth=2  
        fontsize=18
        margin=0.01
        labelfloat=true
        fontcolor="#333333"
        color="#bbbbbb"
    ];

d [pos="864,2016!" ] [label="D" ]  [width=16  height=16]



subgraph x {

    node [color="#886600" fillcolor="#dd9944"]

    A [pos="1440,1440!" ] 

    c [pos="864,2016!" ] [label="C" ] 

        A -> c 

    monkey [pos="1008,1872!" ] [label="HI MONKEY" ] 

    A -> c  [label="THIS WAY" ]  [ pos="s,1440,1483 e,907,2016 1440,1488 1440,1856 1280,2016 912,2016" ][ lp="1360, 1936 " ] 

}

F [pos="576,1440!" ] 

up_left [pos="72,2808!"][label="" height=1 width=1 penwidth=0 color="red"]  down_right [pos="2808,72!"] [label="" height=1 width=1 fillcolor="red" penwidth=0 color="red"]

}

Dry answered 13/11, 2021 at 4:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.