Edges between clusters

My goal is to create an edge between clusters but align them so that the edge started in the middle of the cluster A and connected to the middle of the cluster B.

How can I:

  1. make the edge looks like an edge, not like a triangle?
  2. how to remove empty space in place of invisible nodes?
  3. how to align clusters in the center to each other?
  4. maybe you know better way to make edges between clusters without using invisible nodes? I create them only for the edge.

Here is my solution:

digraph {
  compound=true;

  subgraph cluster_a {
    label="Cluster A";
    1; 3; 5; a [style=invis]; 7; 9; 11; 13; 
  }
  subgraph cluster_b {
    label="Cluster B";
    2; 4; b[style=invis]; 6; 8; 
  }

  a -> b [ltail="cluster_a" lhead="cluster_b"];
}

It will help a little to set ranksep=1 (or at least increase it). You can decrease the width of the invisible nodes, too.

1 Like
  1. ranksep (ranksep | Graphviz) takes care of problem #1.
  2. Invisible nodes do occupy some space, but you can reduce that space by setting shape=point (or plain) (Node Shapes | Graphviz) and reducing nodesep (nodesep | Graphviz).
  3. aligning clusters is a challenge. In recent versions of Graphviz (last 6 months?), you can use packmode (the array option) to force node order and cluster positioning (packMode | Graphviz)
  4. fdp (fdp | Graphviz) allows cluster-cluster edges, no invisible nodes needed. (I can’t find documentation about this). But fdp does node layout entirely differently
  5. If you want a gap-less result, I have a program that will produce it. All automated, but you need to make some odd changes to the input (move all cluster-cluster edges to a second graph) and then run a series of programs. Let me know if this sounds fun. See “gapless”, below.

This gets fairly close. Note it only uses one invisible node, to “fix” the problem of even number of nodes in one cluster.

digraph {
  compound=true;
  ranksep=1
  nodesep=.1

  subgraph cluster_a {
    label="Cluster A";
    1; 3; 5; 7; 9; 11; 13; 
  }
  subgraph cluster_b {
    label="Cluster B";
    2; 4;
    mid [shape=point style=invis]
    6; 8; 
  }
  7 -> mid  [ltail="cluster_a" lhead="cluster_b"];
}

Giving:

Gapless:

1 Like

This is the best approximation I could achieve. While the nodes in Cluster B are not evenly spaced, they exhibit a degree of symmetry.

Here is what I changed:

  1. Added ranksep=1 to move the clusters apart, as @scnorth suggested.
  2. Removed node a from Cluster A.
  3. Changed node b to have no width by adding the attributes width=0 fixedsize=true.
  4. Changed the edge to connect center node 7 in Cluster A to invisible node b in Cluster B.
digraph "gvforum"
{
    compound=true;
    ranksep=1
    subgraph "cluster_a" {  label="Cluster A"
        1; 3; 5; 7; 9; 11; 13;
    }
    subgraph "cluster_b" {  label="Cluster B"
        2; 4; b; 6; 8;
        b [ width=0  fixedsize=true style=invis ];
    }
    7 -> b[ ltail="cluster_a" lhead="cluster_b" ];
}

You can add additional 0 width nodes in Cluster B to achieve even spacing, however the gaps will be wider than what occurs in Cluster A

digraph "gvforum"
{
    compound=true;
    ranksep=1
    subgraph "cluster_a" {  label="Cluster A"
        1; 3; 5; 7; 9; 11; 13;
    }
    subgraph "cluster_b" {  label="Cluster B"
        2; a; 4; b; 6; c; 8;
        a [ width=0  fixedsize=true style=invis ];
        b [ width=0  fixedsize=true style=invis ];
        c [ width=0  fixedsize=true style=invis ];
    }
    7 -> b[ ltail="cluster_a" lhead="cluster_b" ];
}

2 Likes