subgraph cluster ranking in dot

2019-02-04 19:56发布

问题:

I'm trying to use graphviz on media wiki as a documentation tool for software.

First, I documented some class relationships which worked well. Everything was ranked vertically as expected.

But, then, some of our modules are dlls, which I wanted to seperate into a box. When I added the nodes to a cluster, they got edged, but clusters seem to have a LR ranking rule. Or being added to a cluster broke the TB ranking of the nodes as the cluster now appears on the side of the graph.

This graph represents what I am trying to do: at the moment, cluster1 and cluster2 appear to the right of cluster0.

I want/need them to appear below.

<graphviz>
digraph d {
    subgraph cluster0 {
      A -> {B1 B2}
      B2 -> {C1 C2 C3}
      C1 -> D;
    }
    subgraph cluster1 {
      C2 -> dll1_A;
      dll1_A -> B1;
    }
    subgraph cluster2 { 
      C3 -> dll2_A;
    }
    dll1_A -> dll2_A;
}
</graphviz>

回答1:

The layout is an attempt by Dot to minimise the overall height.

One reason for the more compact than required layout is the use of the edge that goes in the reverse direction from dll1_a to B1. It tries to pull the cluster as close back to the destination node as possible. To avoid this edge affecting the graph, either relax the constraint on the upwards edges as shown, or draw the edge in the forward direction and use the dir attribute to reverse the arrow.

This will help with many layouts but it alone is not sufficient to fix the example given. To prevent Dot from maintaining the compact layout it prefers you can add a minlen attribute to edges that should remain (near) vertical. This may be difficult to calculate in general but is practical for manually tuned layouts.

digraph d {
    subgraph cluster0 {
        A -> {B1 B2}    
        B2 -> {C1 C2 C3}
        C1 -> D;
    }
    subgraph cluster1 {
        C2 -> dll1_A [minlen = 2];
        dll1_A -> B1 [constraint = false];
        /* B1 -> dll1_A [dir = back]; */
    }
    subgraph cluster2 {
        C3 -> dll2_A;
    }
    dll1_A -> dll2_A;
}



回答2:

My experience shows that constraint=false commonly gives unnecessarily convoluted edges. It seems that weight=0 gives better results:

digraph d {
    subgraph cluster0 {
        A -> {B1 B2}    
        B2 -> {C1 C2 C3}
        C1 -> D;
    }
    subgraph cluster1 {
        C2 -> dll1_A [minlen = 2];
        dll1_A -> B1 [weight = 0];
        /* B1 -> dll1_A [dir = back]; */
    }
    subgraph cluster2 {
        C3 -> dll2_A;
    }
    dll1_A -> dll2_A;
}


回答3:

This will produce the graph you are looking for:

digraph d {
  subgraph cluster0 {
    A -> {B1 B2}
    B2 -> {C1 C2 C3}
    C1 -> D;
  }

  subgraph {
    rankdir="TB"
    subgraph cluster1 {
      C2 -> dll1_A;
      dll1_A -> B1;
    }

    subgraph cluster2 {
      C3 -> dll2_A;
    }
  }
  dll1_A -> dll2_A;
}

What this does is creat a subgraph that is used only for layout purposes to provide the top to bottom ordering that you desire.



标签: graphviz dot