Vertically aligning a node joining subgraphs in Graphviz

alignmentdotgraphviz

I give the following input to Dot:

digraph G {
  subgraph cluster1 {
    fontsize = 20;
    label = "Group 1";
    A -> B -> C -> D;
    style = "dashed";
  }

  subgraph {
    O [shape=box];
  }

  subgraph cluster2 {
    fontsize = 20;
    label = "Group 2";
    Z -> Y -> X -> W [dir=back];
    style = "dashed";
  }

  D -> O [constraint=false];
  W -> O [constraint=false, dir=back];
}

And it produces:

picture with node O aligned with A and Z

How can I align node O so that it has the same rank as D and W? That is, a graph that looks like:

A   Z
|   |
B   Y
|   |
C   X
|   |
D-O-W

Adding

 { rank=same; D; O; W; }

yields the error

Warning: D was already in a rankset, ignored in cluster G
Warning: W was already in a rankset, ignored in cluster G

I'm thinking I can hack it by adding invisible nodes and edges to the subgraph of O, but I was wondering if I was missing some Dot magic.

Best Solution

You could use an approach with rankdir=LR and use constraint=false for the edges inside the clusters:

digraph G {
  rankdir=LR;

  subgraph cluster1 {
    fontsize = 20;
    label = "Group 1";
    rank=same;
    A -> B -> C -> D [constraint=false];
    style = "dashed";
  }

  subgraph cluster2 {
    fontsize = 20;
    label = "Group 2";
    rank=same;
    Z -> Y -> X -> W [dir=back, constraint=false];
    style = "dashed";
  }

  O [shape=box];
  D -> O -> W;
}

It's not dot magic :-), but it achieves this:

graphviz output with rankdir LR

Hacking with invisible nodes does also work:

digraph G {
  subgraph cluster1 {
    fontsize = 20;
    label = "Group 1";
    A -> B -> C -> D;
    style = "dashed";
  }

  subgraph {
    O1[style=invis];
    O2[style=invis];
    O3[style=invis];
    O [shape=box];

    O1 -> O2 -> O3 -> O [style=invis];
  }

  subgraph cluster2 {
    fontsize = 20;
    label = "Group 2";
    Z -> Y -> X -> W [dir=back];
    style = "dashed";
  }

  edge[constraint=false];
  D -> O -> W;
}

The result is almost identical:

graphviz output with invisible nodes