Search code examples
graphvizdot

Graphviz - Vertical order of leaf nodes


I'm trying to generate a Tree graph (left to right one), to illustrate an object reference tree. Beside this, I want the leafs to appear vertically consequent, because this indicates some order of execution.

The dot code is as follows:

digraph G {

    rankdir=LR
    subgraph cluster_0 {

        L1   L2   L3   L4  L5  L6 
        L10  L20  L30   L40  L50  L60

        { rank=same;
            L1 -> L2 -> L3 ->  L4 -> L5 -> L6 ->
            L10 -> L20 -> L30 ->  L40 -> L50 -> L60 
        }
    }

    subgraph cluster_1 {
        R

        D10 D11

        D20 D21 D22 D23

        D30 D31 D32 D33 D34 D35 D36 D37
    }

    R->D10
    R->D11

    D10 -> D20
    D10 -> D21
    D11 -> D22
    D11 -> D23

    D20 -> D30
    D20 -> D31
    D21 -> D32
    D21 -> D33
    D22 -> D34
    D22 -> D35
    D23 -> D36
    D23 -> D37

    D30 -> L1
    D20 -> L2
    D31 -> L3

    D32 -> L4
    D21 -> L5
    D33 -> L6

    D34 -> L10
    D22 -> L20
    D35 -> L30

    D36 -> L40
    D23 -> L50
    D37 -> L60
}

What I've got far (using https://dreampuf.github.io/GraphvizOnline/ to render SVG): Tree

The problem is, I want the leafs to show up in the order of declaration. Following some posts on SO, I've been playing around with constraint / invisible edges / ranking system but couldn't quite get my hands on it.

It'd be nice if some graphvizard could extend their hand over here. note that this procedure will be later automated with python, so some robust idea will be more than appreciated.

note 2, the tree could have up to hundreds of leafs.

note 3, if you know some good python lib to generate Graphs which is more intuitive (for you at least) than Graphviz, please comment. I'm currently using pydot & graphviz (py3)


Solution

  • By moving the leaf nodes out and adding weights to them I have the following:

    enter image description here

    I changed the dot input to:

    digraph G {
        rankdir=LR
        subgraph cluster_0 {
            L1   L2   L3   L4  L5  L6 
            L10  L20  L30   L40  L50  L60
        }
    
        subgraph cluster_1 {
            R
            D10 D11
            D20 D21 D22 D23
            D30 D31 D32 D33 D34 D35 D36 D37
        }
    
        R->D10 
        R->D11 
    
        D10 -> D20 
        D10 -> D21 
        D11 -> D22 
        D11 -> D23 
    
        D20 -> D30 
        D20 -> D31 
        D21 -> D32 
        D21 -> D33 
        D22 -> D34 
        D22 -> D35 
        D23 -> D36 
        D23 -> D37 
    
        D30 -> L1 
        D20 -> L2 
        D31 -> L3 
    
        D32 -> L4 
        D21 -> L5 
        D33 -> L6 
    
        D34 -> L10 
        D22 -> L20 
        D35 -> L30 
    
        D36 -> L40 
        D23 -> L50 
        D37 -> L60 
    
        { rank=same;
          L1-> L2 [style=invis, weight=1000]
          L2-> L3 [style=invis, weight=1100]
          L3-> L4 [style=invis, weight=1200]
          L4-> L5 [style=invis, weight=1300]
          L5-> L6 [style=invis, weight=1400]
          L6-> L10 [style=invis, weight=1500]
          L10-> L20 [style=invis, weight=1600]
          L20-> L30 [style=invis, weight=1700]
          L30-> L40 [style=invis, weight=1800]
          L40-> L50 [style=invis, weight=1900]
          L50-> L60 [style=invis, weight=2000]
        }
    }