Graphviz 排版思路 Graphviz 如何控制节点位置

有个画图需求是需要生成特定排版的关系图。

graphviz 对于一般情况都是自动排的,有时候会抽风,比如这种情况:

Graphviz 排版思路 Graphviz 如何控制节点位置_第1张图片

而我们想要这样:

Graphviz 排版思路 Graphviz 如何控制节点位置_第2张图片

对初学者提一下 ,如何实现 3  2 5 ,1467 从左到右排列呢?待会会顺便讲解这个的实现方法。

可以看到 3 就是不能在 2 的左边 。而代码中加入了限制:

    subgraph {
        rankdir = LR;
        rank = same;
        
        s3 -> s2 [style = invis;];
        s2 -> s5 [style = invis;];
    }
    

这里 invis 边就是用来控制位置用的。因此我们继续加入一些限制来吧这个 3 移动回到 2 的左边。

    subgraph {
        s1 -> s4 [style = invis;];
        s4 -> s6 [style = invis;];
        s6 -> s7 [style = invis;];
        s1 -> start [style = invis;];
    }
    subgraph {
        rankdir = LR;
        rank = same;
        
        start [style = invis;];
        start -> s3 [style = invis;];
        s3 -> s2 [style = invis;];
        s3 -> s5 [style = invis;];
    }

原理是通过添加额外的节点和边(仅用于排版,输出时隐藏)以及 rank 限制条件,来控制生成节点尽量满足需要的排版。不过这个实际和算法执行起来算出来的效果有关。

Graphviz 排版思路 Graphviz 如何控制节点位置_第3张图片

上图中框起来的是  invis 边。

下面进行讲解:

红色橙色:为了限制节点的顺序是水平的 3 2 5 排序摆放。1 4 6 7 水平顺序摆放,否则会错乱,graphviz 会自己想怎么排就怎么拍(设置 rankdir = LR 能生效的前提是他们节点之间有有向边!

绿色:为了把 3 从 graphviz 糟糕算法生成的右边拉回到左边,至于为什么会这样,其实和 graphviz 用的算法和选择策略有关,可以参照Graphviz中的资料,实际就是算法因为是比较通用的,在这个 case 下,算法恰好生成的时候认为 3 再右边更加的均匀。

实际效率需求的生产中,我们还是用 GUI 工具吧,这种除了要通过代码生成的情景或者大量的数据下之外,比如这种需要对特定节点特定边的位置进行控制的,没有太大必要去用脚本工具画图。。

附录,完整代码:

digraph b {
    overlap = false;
    splines = true;
    
    s8 [label = 8;group = g1;];
    
    s2 [label = 3;group = g2;];
    s3 [label = 2;group = g2;];
    s5 [label = 5;group = g2;];
    
    s1 [label = 1;group = g3;];
    s4 [label = 4;group = g3;];
    s6 [label = 6;group = g3;];
    s7 [label = 7;group = g3;];
    
    
    
    s8 -> s3 [dir = back;];
    s1 -> s3;
    s3 -> s6 [dir = back;];
    s4 -> s3;
    s7 -> s3;
    
    s2 -> s3;
    s3 -> s2;
    s3 -> s5;
    s5 -> s3;
    
    
    subgraph a {
        rankdir = TB;
        rank = same;
        s2;
        s3;
        s5;
    }
    
    subgraph {
        s1 -> s4 [style = invis;];
        s4 -> s6 [style = invis;];
        s6 -> s7 [style = invis;];
        s1 -> start [style = invis;];
    }
    subgraph {
        rankdir = LR;
        rank = same;
        
        start [style = invis;];
        start -> s2 [style = invis;];
        s2 -> s3 [style = invis;];
        s3 -> s5 [style = invis;];
    }
    
    
    subgraph c {
        rankdir = TB;
        rank = same;
        s1;
        s4;
        s6;
        s7;
    }
    subgraph d {
        rank = same;
        s8;
    }
    rank = same;
}

你可能感兴趣的:(摘要性笔记,流程图)