Search code examples
graphviz

How to combine both vertical and horizontal layout of clusters and nodes using graphviz?


I am experimenting with graphviz to visualize the requirements traceability documentation.

This is what I would like to achieve:

  • One document to the left side, another to the right side.
  • Within each document, the chapters are laid out vertically.
  • Within each chapter, the nodes are laid out vertically.

I tried to replace LR with TB and experimented with rankdir=same and assigning rank to the nodes, but could not get it to work.

My goals:

  • Achieve the desired layout.
  • Make sure that the nodes within the clusters are also sorted correctly. I figured out that for these nodes, I can fix the order using invisible links, but maybe there is a better approach.
  • Eventually, I am going to generate this code automatically for rather large documents, so no preference to the hard-coded solutions.

This is my code.

digraph {
  rankdir=LR;
  subgraph cluster_document_1 {
    subgraph cluster_document_1_chapter_1 {
      {
        D1_C1_E1[label="Chapter 1.1"]
        D1_C1_E2[label="Chapter 1.2"]
      }
    }
    subgraph cluster_document_1_chapter_2 {
      {
        D1_C2_E1[label="Chapter 2.1"];
        D1_C2_E2[label="Chapter 2.2"];
      }
    }
  }
  subgraph cluster_document_2 {
    subgraph cluster_document_2_chapter_1 {
      {
        D2_C1_E1[label="Chapter 1.1"];
        D2_C1_E2[label="Chapter 1.2"];
      }
    }
    subgraph cluster_document_2_chapter_2 {
      {
        D2_C2_E1[label="Chapter 2.1"];
        D2_C2_E2[label="Chapter 2.2"];
      }
    }
  }
}

This is what I DON'T want:

enter image description here

enter image description here

This is how I want it to look like:

enter image description here


Solution

  • As already stated in the question, I don't think there is a way around invisible edges for your use case.

    Fortunately, it's quite easy to generate those edges automatically - simply create a chain of edges from the first to the last chapter.

    Example:

    digraph {
      edge[style=invis]
      subgraph cluster_document_1 {
        subgraph cluster_document_1_chapter_1 {
          {
            D1_C1_E1[label="Chapter 1.1"]
            D1_C1_E2[label="Chapter 1.2"]
          }
        }
        subgraph cluster_document_1_chapter_2 {
          {
            D1_C2_E1[label="Chapter 2.1"];
            D1_C2_E2[label="Chapter 2.2"];
          }
        }
        
        D1_C1_E1 -> D1_C1_E2 -> D1_C2_E1 -> D1_C2_E2
      }
      subgraph cluster_document_2 {
        subgraph cluster_document_2_chapter_1 {
          {
            D2_C1_E1[label="Chapter 1.1"];
            D2_C1_E2[label="Chapter 1.2"];
            D2_C1_E3[label="Chapter 1.3"];
          }
        }
        subgraph cluster_document_2_chapter_2 {
          {
            D2_C2_E1[label="Chapter 2.1"];
            D2_C2_E2[label="Chapter 2.2"];
          }
        }
        D2_C1_E1 -> D2_C1_E2 -> D2_C1_E3 -> D2_C2_E1 -> D2_C2_E2
      }
    }
    

    graphviz output