graphvizdot

Dot language: can you connect a containing box to another?


Using Dot language and Graphviz to render, I've been able to create two boxes (nodes) labelled "A" and "B", one above the other, with a dashed bounding box around them:

digraph G {
  // Define a subgraph representing the outer box
  subgraph outer_box {
      cluster=true; // Designate this subgraph as a cluster in order to enable the boundary box
      rankdir="TB"; // Arrange boxes from top to bottom

      style=dashed; // Fill the outer box with color
      fillcolor=lightgray; // Set the fill color of the outer box

      // Top box with text "A"
      node [shape=box, style=filled, fillcolor=lightblue];
      A [label="A"];

      // Bottom box with text "B"
      node [shape=box, style=filled, fillcolor=lightyellow];
      B [label="B"];

      // Connect boxes
      A -> B [style=invis]; // Invisible edge to stack boxes vertically
  }
 }

The visualization can be viewed here, and it looks like this:
enter image description here

How can I make the outer, dashed box connect to another box with the label "C"?

I.e. I would like to generate a picture like this:

enter image description here

I'm open to any change in the class/type of outer_box, A, and/or B; their respective classification as cluster-subgraphs and nodes is just from my current state of experimenting with the Dot language.

I've tried creating C as another cluster subgraph, then adding a outer_box -> C statement, but that didn't work. I have also been reading the Graphviz/Dot language documentation at https://graphviz.org/doc/info/lang.html, but I have not yet found an example that aligns with what I'm trying to achieve.


Solution

  • Not as easily as one might like, but you can get the graph you describe. Look at:

    digraph G {
      compound=true  // allow edges to-from clusters (pseudo)
      rankdir="TB";  // only valid if applied to Root graph - Arrange boxes from top to bottom
      ranksep=.25    // snug up the ranks
      newrank=true   // allow rank=same to apply to ALL nodes, not just those in same cluster
    
      // Define a subgraph representing the outer box
      subgraph outer_box {
          cluster=true; // Designate this subgraph as a cluster in order to enable the boundary box
    
          style=dashed; // Fill the outer box with color
          fillcolor=lightgray; // Set the fill color of the outer box
    
          // Top box with text "A"
          node [shape=box, style=filled, fillcolor=lightblue];
          A [label="A"];
    
          // Bottom box with text "B"
          node [shape=box, style=filled, fillcolor=lightyellow];
          B [label="B"];
    
          dummy [shape=point height=0 width=0 label="" style=invis]  // place a node in-between A & B
          // Connect boxes
          A -> dummy ->B [style=invis]; // Invisible edge to stack boxes vertically
      }
    
      C [shape=box]
      {rank=same   dummy C}
      // the empty label pushes C farther to the right of the cluster
      dummy -> C [ltail=outer_box label="            "]
     }
    

    Giving:
    enter image description here