Top Rank Node is not center aligned over some subgraphs

I’d like to suggest an alternate approach. When creating these types of diagrams, or domain maps, taxonomies, etc. I feel the osage layout is superior to dot for this use case. Osage will allow you to nest clusters, control top/bottom/left/right alignment, and control the order of the node placement.

Unfortunately most people don’t know how to use osage. osage draws the graph recursively. At each level, there will be a collection of nodes and a collection of cluster subgraphs. The internals of each cluster subgraph are laid out, then the cluster subgraphs and nodes at the current level are positioned relative to each other, treating each cluster subgraph as a node.

The secret is to use packmode attributes to describe how the clusters should be nested, and sortv attributes to specify the order in which clusters and nodes should be emitted.

I’m assuming you are trying to create a diagram similar to this one I found through a Google image search:

Source: https://images.app.goo.gl/8Tsu7q3TVb1Qgta88

Using the osage layout instead of dot allowed me to create a very similar diagram, with full-width headings which you desire:

The source for the diagram is as follows:

strict digraph "main"
{
    layout=osage;
    splines=ortho;
    pad="0.5,0.5"
    node[ shape=rect height=0.75 width=1.25 fixedsize=True fillcolor=White fontname=Arial fontsize=10 style="filled,rounded" penwidth=0.5 label="" ];
    edge[ fontname=Arial fontsize=10 arrowsize=0.5 ];
    subgraph cluster_1 {  packmode=array_rtu4 color=transparent label=""
        subgraph cluster_2 {  sortv=1000 packmode=array_tu1 label=""
            subgraph cluster_3 {  sortv=1100 packmode=array_tu1 label=""
                plan [ shape=rect height=0.1875 width=5.5 fillcolor=LightYellow penwidth=0.5 fontname=Arial fontsize=10 style="filled" labelloc=top label=<<b>PLAN</b>> ];
            }
            subgraph cluster_4 {  sortv=1200 packmode=array_rtu3 label=""
                subgraph cluster_5 {  sortv=1210 packmode=array_rtru1 label=""
                    4 [ shape=rect height=0.75 width=1.75 fillcolor=LightYellow penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 4</b></u><br/><br/>Context of the <br/>organization> ];
                    4.1 [ sortv=1 label="4.1 Understanding\nthe organization\nand its context" ];
                    4.2 [ sortv=2 label="4.2 Understanding\nthe needs and\nexpectations\nof interested parties" ];
                    4.3 [ sortv=3 label="4.3 Determining the\nscope of the QMS" ];
                    4.4 [ sortv=4 label="4.4 Quality\nmanagement\nsystem & its\nprocesses" ];
                }
                subgraph cluster_6 {  sortv=1220 packmode=array_rtu1 label=""
                    5 [ shape=rect height=0.75 width=1.75 fillcolor=LightYellow penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 5</b></u><br/><br/>Leadership> ];
                    5.1 [ sortv=1 label="5.1 Leadership and\ncommitment" ];
                    5.2 [ sortv=2 label="5.2 Quality Policy" ];
                    5.3 [ sortv=3 label="5.3 Organizational\nroles,\nresponsibilities and\nauthorities" ];
                }
                subgraph cluster_7 {  sortv=1230 packmode=array_rtu1 label=""
                    6 [ shape=rect height=0.75 width=1.75 fillcolor=LightYellow penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 6</b></u><br/><br/>Planning> ];
                    6.1 [ sortv=1 label="6.1 Actions to\naddress risks and\nopportunities" ];
                    6.2 [ sortv=2 label="6.2 Quality\nobjectives and\nplanning to achieve\nthem" ];
                    6.3 [ sortv=3 label="6.3 Planning of\nchanges" ];
                }
            }
        }
        subgraph cluster_8 {  sortv=2000 packmode=array_tu1 label=""
            subgraph cluster_9 {  sortv=2100 packmode=array_tu1 label=""
                do [ shape=rect height=0.1875 width=3.55 fillcolor=LightGreen penwidth=0.5 fontname=Arial fontsize=10 style="filled" labelloc=top label=<<b>DO</b>> ];
            }
            subgraph cluster_10 {  sortv=2200 packmode=array_rtu2 label=""
                subgraph cluster_11 {  sortv=2210 packmode=array_rtu1 label=""
                    7 [ shape=rect height=0.75 width=1.75 fillcolor=LightGreen penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 7</b></u><br/><br/>Support> ];
                    7.1 [ sortv=1 label="7.1 Resources" ];
                    7.2 [ sortv=2 label="7.2 Competence" ];
                    7.3 [ sortv=3 label="7.3 Awareness" ];
                    7.4 [ sortv=4 label="7.4 Communication" ];
                    7.5 [ sortv=5 label="7.5 Documented\nInformation" ];
                }
                subgraph cluster_12 {  sortv=2220 packmode=array_rtu1 label=""
                    8 [ shape=rect height=0.75 width=1.75 fillcolor=LightGreen penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" label=<<u><b>Clause 8</b></u><br/><br/>Operation> ];
                    8.1 [ sortv=1 label="8.1 Operational\nplanning and\ncontrol" ];
                    8.2 [ sortv=2 label="8.2 Requirements\nfor products &\nservices" ];
                    8.3 [ sortv=3 label="8.3 Design & \nDevelopment of\nproducts & services" ];
                    8.4 [ sortv=4 label="8.4 Control of\nexternally provided\nprocesses, products\nand services" ];
                    8.5 [ sortv=5 label="8.5 Production and\nservice provision" ];
                    8.6 [ sortv=6 label="8.6 Release of\nproducts and\nservices" ];
                    8.7 [ sortv=7 label="8.7 Control of\nnonconformity\nproducts" ];
                }
            }
        }
        subgraph cluster_13 {  sortv=3000 packmode=array_rtu1 label=""
            subgraph cluster_14 {  sortv=3100 packmode=array_rtu1 label=""
                check [ shape=rect height=0.1875 width=1.75 fillcolor=LightBlue penwidth=0.5 fontname=Arial fontsize=10 style="filled" labelloc=top label=<<b>CHECK</b>> ];
            }
            subgraph cluster_15 {  sortv=3200 packmode=array_rtu1 label=""
                subgraph cluster_16 {  sortv=3210 packmode=array_rtu1 label=""
                    9 [ shape=rect height=0.75 width=1.75 fillcolor=LightBlue penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 9</b></u><br/><br/>Performance<br/>Evaluation> ];
                    9.1 [ sortv=1 label="9.1 Monitoring,\nmeasurement,\nanalysis and\nevaluation" ];
                    9.2 [ sortv=2 label="9.2 Internal Audit" ];
                    9.3 [ sortv=3 label="9.3 Management\nReview" ];
                }
            }
        }
        subgraph cluster_17 {  sortv=4000 packmode=array_rtu1 label=""
            subgraph cluster_18 {  sortv=4100 packmode=array_rtu1 label=""
                act [ shape=rect height=0.1875 width=1.75 fillcolor=Mistyrose penwidth=0.5 fontname=Arial fontsize=10 style="filled" labelloc=top label=<<b>ACT</b>> ];
            }
            subgraph cluster_19 {  sortv=4200 packmode=array_rtu1 label=""
                subgraph cluster_20 {  sortv=4210 packmode=array_rtu1 label=""
                    10 [ shape=rect height=0.75 width=1.75 fillcolor=Mistyrose penwidth=0.5 fontname=Arial fontsize=10 style="rounded,filled" labelloc=top pad="0.25,0.25" sortv=0 label=<<u><b>Clause 10</b></u><br/><br/>Improvement> ];
                    10.1 [ sortv=1 label="10.1 General" ];
                    10.2 [ sortv=2 label="10.2 Nonconformity\nand corrective\nactions" ];
                    10.3 [ sortv=3 label="10.3 Continual\nimprovement" ];
                }
            }
        }
    }
    edge[ fontname=Arial fontsize=10 arrowsize=0.5 ];
    4 -> 5;
    5 -> 6;
    6 -> 7;
    7 -> 8;
    8 -> 9;
    9 -> 10;
    10 -> 4;
    edge[ color="CadetBlue" penwidth=0.5 dir=none fontname=Arial fontsize=10 ];
    4 -> 4.1;
    4 -> 4.2;
    4 -> 4.3;
    4 -> 4.4;
    5 -> 5.1;
    5 -> 5.2;
    5 -> 5.3;
    6 -> 6.1;
    6 -> 6.2;
    6 -> 6.3;
    7 -> 7.1;
    7 -> 7.2;
    7 -> 7.3;
    7 -> 7.4;
    7 -> 7.5;
    8 -> 8.1;
    8 -> 8.2;
    8 -> 8.3;
    8 -> 8.4;
    8 -> 8.5;
    8 -> 8.6;
    8 -> 8.7;
    9 -> 9.1;
    9 -> 9.2;
    9 -> 9.3;
    10 -> 10.1;
    10 -> 10.2;
    10 -> 10.3;
}

iso9001.gv (7.3 KB)

Nesting clusters can be a little confusing. Each time you wish to change the number of columns you must create another cluster with a new packmode attribute. Inside that cluster can be more clusters, or just nodes. sortv values always refer the the most recent packmode in scope.

Here is the same diagram altered to show the cluster borders, and the packmode and sortv values used:

packmode=array Tutorial

How do packmode=array values affect the output?

The mode array(_flag)?(%d)? indicates that the components (clusters or nodes) should be packed at the graph level into an array of graphs. By default, the components are in row-major order, with the number of columns roughly the square root of the number of components.

The integer suffix specifies the number of columns for row-major. Thus, the mode array_r4 indicates array packing, with 4 columns per row, starting in the upper left and going across the first row, then to the second row, etc., until all components are used.

If a graph is smaller than the array cell it occupies, it is centered (left, right, top, and bottom) by default. The optional flags may contain t, b, l, or r, indicating that the graphs should be aligned along the top, bottom, left or right, respectively. The flags may also be combined such as tl for top left, tr for top right, bl for bottom left, or br for bottom right.

If the optional flags contains u, the order of elements is determined by user-supplied values. Each component can specify its sort value by a non-negative integer using the sortv attribute. Components are inserted in order, starting with the one with the smallest sort value. If no sort value is specified, zero is used.

Here are some examples:

Example 1: Default Behavior

packmode=array

Notice that the components are packed roughly in the square root of the 5 components.

image

Example 2: Align Right

packmode=array_r is causing right alignment of node 4.4 with the larger node above it.

image

Example 3: Specify Sort Order

packmode=array_ru says to use the sortv attribute to place the nodes in numerical order specified.

image

Example 4: One Column, Sort Order

packmode=array_u1 says to use one column, and insert the components in the order specified by sortv. The components are centered by default.

image

Example 5: One Column, Sort Order Specified, Right-aligned

packmode=array_ru1 says to use one column.

image

Example 6: One Column, Sort Order Specified, Left-aligned

packmode=array_lu1 says to use one column, and left-align the contents of the column.

image

Example 7: Three Columns, Sort Order Specified

packmode=array_ru3 says to have 3 columns. Note that each column is a transparent cluster. By default the clusters are aligned in the center top-to-bottom.

image

Example 8: Three Columns, Sort Order Specified, Top-aligned

packmode=array_rtu3 says to have 3 columns, and align the contents top-to-bottom.

image

Example 9: Three Columns, Sort Order Specified, Bottom-aligned

Likewise, we can align the contents to the bottom of the cluster with packmode=array_rbu3

image

3 Likes