79

I have a graph I've created in graphviz, but the problem is that edges overlap each other (I have 5-7 nodes in each row), so it is hard to tell for each node which are the nodes it connects.

How can I make the edges not to overlap each other? Have them cross each other is OK.

TylerH
  • 20,799
  • 66
  • 75
  • 101
David Rabinowitz
  • 29,904
  • 14
  • 93
  • 125
  • 3
    Read the documentation https://graphviz.gitlab.io/_pages/pdf/neatoguide.pdf section 4. It says it is not possible to prevent edge overlaps. It says it is "area for future work". I have a very large graph, so that overlap=scale produces ridiculously tiny print, and overlap=false is stupidly dense! I wish there was a way to do a little bit voronoi and a little bit scale, instead of either/or. – John Henckel Jan 18 '19 at 17:44
  • 4
    After some experimenting I'm having good luck with `dot -Granksep=2 -Gnodesep=1 -Grankdir=LR -Gsplines=ortho -Nshape=box` You can increase the size of the boxes and the sep and eventually get zero overlap. Unfortunately neato and twopi do not allow nodesep, so you're stuck with dot – John Henckel Jan 18 '19 at 19:39

3 Answers3

54

I'm assuming you have a directed graph which you layout with dot.

I don't think there's a magic switch to prevent overlapping edges. Graphviz tries to do that out of the box.

Some suggestions that may help, depending on the graph:

  • edge concentrators (concentrate=true): Merge multiple edges with a common endpoint into single edges, and have partially parallel edges share parts of their path.
  • ports : Edges can have their origin and endpoint on a specific port (n, ne, e, se, s, sw, w, nw, w, c, _). Depending on the edge ports, the edge changes its form (spline).
  • invisible nodes : There may be cases where introducing invisible nodes to route edges can have the desired effect.
marapet
  • 54,856
  • 12
  • 170
  • 184
  • 6
    How to set the ports attribute? – dnivog Feb 22 '18 at 16:06
  • 5
    @dnivog Simply by adding a `:` followed by the port to the node id (see also https://graphviz.gitlab.io/_pages/doc/info/lang.html ), for example `node1:ne -> node2:nw` – marapet Feb 23 '18 at 22:52
26

Another approach is to add an overlap property to the graph. Allowable properties are scale (which will vastly increase the size of the output) or false (which will not increase the size as much, but will probably cause edges to overlap nodes).

overlap = scale;

If you're using overlap=false, you can get rid of edge overlaps with nodes by adding the attribute splines=true:

overlap = false;
splines = true;

This will slow down generation time noticeably for large graphs.

Stephan Schulze
  • 139
  • 3
  • 11
Joel Rein
  • 3,608
  • 1
  • 26
  • 32
  • 5
    Where do I add these properties to the graph? I insert them into the body of the graph and it results in no change. – Steven Lu Dec 22 '12 at 07:06
  • 8
    Adding `graph [overlap=false, splines=true];` doesn't help with my overlapping edges, either. – Steven Lu Dec 22 '12 at 07:14
  • 11
    `overlap` is not supported by DOT engine. – vertti Oct 31 '13 at 07:36
  • 20
    [overlap](http://www.graphviz.org/doc/info/attrs.html#d:overlap) only deals with node overlaps, it has nothing to do with edge overlaps. – Ingmar Hupp Apr 18 '14 at 07:52
  • 1
    Just noting that these can be specified on the console like so: `neato -Goverlap=false -Gsplines=true -Tpdf inputFile > outputFile` – Anssssss Dec 02 '15 at 23:10
  • Hello. How can I apply it with my diagrammer input? https://stackoverflow.com/questions/52562208/how-to-minimize-edge-crossings-on-diagrammer-minquit-and-maxiter – skan Oct 02 '18 at 21:55
  • Splines = true really kills performance, since that produces basically curves rather than straight lines. – AdamKalisz Apr 08 '20 at 13:08
  • From the docs, "overlap" is for node overlap only, and unrelated to edge overlap (crossing?) or text/label overlap. – Andrew Mackenzie Dec 01 '22 at 14:40
14

Even for quite trivial graph I see graphviz (neato, fdp) to generate overlaps. For example:

graph G {
0;
1;
2;
3;
0--1 ;
1--2 ;
2--3 ;
3--0 ;
}

Produces a cross in my version of the code 2.38.0.

From the documentation they recommend trying with different random seeds in these cases. Eventually for more complex diagrams crossings will be unavoidable, I am not sure how much effort the engine puts in avoiding crossing.

For example, this worked for me:

neato -Gstart=5 file.dot -Tps -o file.ps
alfC
  • 14,261
  • 4
  • 67
  • 118
  • 1
    It seems the link is broken right now (2018-05-31). This one is working: https://graphviz.gitlab.io/faq/#FaqNeatoEdgeCrossings – Ronie May 31 '18 at 13:37
  • How can I set the parameter with my input? https://stackoverflow.com/questions/52562208/how-to-minimize-edge-crossings-on-diagrammer-minquit-and-maxiter – skan Oct 02 '18 at 21:56
  • @alfC please follow the link, I explain the command line and I provide an example. I'm using neato and dot and in both cases some edges are trivially crossed. – skan Oct 02 '18 at 22:09
  • @skan, I did but I didn't find the command line, can you repeat it here? – alfC Oct 02 '18 at 22:11
  • I'm using Diagrammer from R. And I tell it to use internally Graphviz to generate the graph. I First define the nodes and edges, the define some properties, for example neato layout, and store everything on "graph". At the end I use the command render_graph(graph) – skan Oct 02 '18 at 22:14
  • @skan, I am not familiar with R. I guess if you can manage to pass command line arguments (such as `-Gstart=5`) to `render_graph` then you are set. Another option is go inside Diagrammer and hard code command line to something different. – alfC Oct 03 '18 at 01:47
  • @skan, if you are (very) lucky maybe you can hijack the output argument to sneak options to the command line `render_graph(graph, "-Gstart=5 file.eps")`. – alfC Oct 03 '18 at 01:49
  • Thank you but it doesn't seem to do anything. I've done a script to summarise data from a large database and generate graphs from it using different parameters. For example I get this https://i.imgur.com/DvdXhFs.jpg I've deliberatery deleted the labels. As yo can see it fails to optimize the positioning. – skan Oct 03 '18 at 11:39
  • @skan, I saw in one of the examples the command `set.seed(42)` maybe that changes the randomization variable for the graph renderer. – alfC Oct 03 '18 at 15:04