7

Drawing graphs with dot 精要笔记

 3 years ago
source link: https://hsingko.github.io/post/2021/05/24/note-about-drawing-graphs-with-dot/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这个文档是官网上提供的,链接: http://www.graphviz.org/pdf/dotguide.pdf

读完了之后的第一感觉是并不适合新手入门,因为很多基础性的东西并没有讲到,更适合用来提高,因此建议没接触过 graphviz 的读者先熟悉一下基本操作,至少能用它完成一个简单的人物关系图之后,再来阅读该文档。

以下是我读完文档之后做的笔记,比较简略,唯一的优点是提供了原创的例子,帮助读者形象地认识各种参数的功能,希望这篇文章能给读者些许裨益。

Basic Graph Drawing 基本使用#

digraph{
    hello -> world;
}
hello-world.svg

Drawing Attributes 常用属性#

Node Shapes 节点形状#

分为两类。

polygon-based 多边形节点#

digraph {
    box[shape=box];
    circle[shape=circle];
    point[shape=point];
    triangle[shape=triangle];
    plain[shape=plain];
}
node-shapes.svg

record-based 条目节点#

label 里面用竖线分割,默认横排,用花括号表示竖排。

digraph{
    struct1 [shape=record, label= "left|mid|right"];
    struct2 [shape=record, label= "{1|2|3}"]
    struct3 [shape=record, label= "a|{c|d|e}|b"];
}
node-record.svg

Labels 标签#

若不显式指定 label 那么节点的标签默认就是节点名。

跨行标签#

digraph {
    a [label= "hello\nworld!"]
    b [label= "hello\lworld!"]
    c [label= "hello\rworld!"]
}
labels-mulit-line.svg

graph 的标签#

  • labelloc 控制上下
  • labeljust 控制左右
digraph{
    subgraph cluster_top_label {
        labelloc = t;
        label = "top";
        a;
    }
    subgraph cluster_bottom_label {
        labelloc = b;
        label = "bottom";
        b;
    }
    subgraph cluster_left_label {
        labeljust = l;
        label = "left";
        c;
    }
    subgraph cluster_right_label {
        labeljust = r;
        label = "right";
        d;
    }
}
graph-label.svg

标签样式#

  • 默认字体是 Times-Roman, 14pt
  • 通过 fontname, fontsize, fontcolor 控制字体的样式
digraph{
    a [label= "hello,world!", fontsize=20, fontcolor=red];
}
label-font.svg

edge label 边的标签#

digraph{
    a -> b [label= "here"];
    c -> d [label= "here", decorate= true];
    e -> f [label= "here", labelfloat=true];
    g -> h [headlabel= "head", taillabel="tail", label= "normal"]
}
edge-labels.svg

HTML 标签#

可以在 label 中内嵌 html 代码。

文档上使用 html 表格的例子:

digraph html {
    abc [shape=none, margin=0, label=<
         <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
         <TR><TD ROWSPAN="3"><FONT COLOR="red">hello</FONT><BR/>world</TD>
         <TD COLSPAN="3">b</TD>
         <TD ROWSPAN="3" BGCOLOR="lightgrey">g</TD>
         <TD ROWSPAN="3">h</TD>
         </TR>
         <TR><TD>c</TD>
         <TD PORT="here">d</TD>
         <TD>e</TD>
         </TR>
         <TR><TD COLSPAN="3">f</TD>
         </TR>
         </TABLE>>];
     }
html-label.svg

Graphics Styles 各种样式:颜色、线条、箭头#

  • 边的样式:
    • color: 指定边的颜色
    • style: 边的样式,有 solid, dashed, dotted, bold, invis 可供选择,具体外观见附图
    • dir: 箭头的方向。有 back, forward, both, none 就是字面上的功能
    • arrowhead, arrowtail: 箭头的样式。
  • 节点的样式:
    • color 同上
    • style 节点的样式, filled, diagonals, rounded
digraph{
    // color
    a [color= red];
    a -> b [color= pink];

    // edge style
    c -> d [style= solid, label= "solid"];
    c -> d [style= dashed, label = "dashed"];
    c -> d [style= dotted, label = "dotted"];
    c -> d [style= bold, label = "bold"];
    c -> d [style= invis, label = "invis"];

    // node style
    filled[style=filled, color=red];
    diagonals[style=diagonals, color=yellow];
    rounded[style=rounded, shape=rectagle];
    filled -> diagonals -> rounded;

    // edge dir
    e -> f [dir=back, label = "back"];
    e -> f [dir=forward, label = "forward"];
    e -> f [dir=both, label = "both"];
    e -> f [dir=none, label = "none"];

    // arrowhead some for arrow tail
    h -> i [arrowhead= odot, label= "odot"];
    h -> i [arrowhead= dot, label = "dot"];
    h -> i [arrowhead= inv, label = "inv"];
    h -> i [arrowhead= invdot, label = "invdot"];
    h -> i [arrowhead= invodot, label = "invodot"];
    h -> i [arrowhead= none, label = "none"];
}

Drawing Orientation, Size and Spacing 间距调整#

这一节讲的非常粗略且抽象。 经过试验, nodesep, ranksep 只能作用于 graph, 同时只能定义一次,先定义的生效 其中 nodesep 定义的是节点(中心)之间的横向间距,而 ranksep 定义的是纵向间距。

digraph{
    label = "nodesep 1.0";
    nodesep = "1.0";
    a -> {b,c,d};
}
digraph{
    label = "nodesep 2.0";
    nodesep = "2.0";
    A -> {B,C,D};
}

Node and Edge Placement 位置调整#

箭头方向#

通过 rankdir 调整箭头的指向,这个设置同样只作用于 graph. 有四种值:

  • TB, Top to Buttom, 默认
  • BT, Buttom to Top
  • LR, Left to Right
  • RL, Right to Left
digraph{
    rankdir = BT;
    a -> b;
}

rank 层级设置#

rank 作用于 subgraph 可以调整节点之间纵向的相对位置:

  • same, 可以让节点保持在同一水平线上
  • min, 让节点尽可能上浮
  • max, 让节点尽可能下沉

默认情形,所有节点依次往下排列:

digraph{
    label = "default rank"
    a -> b -> c -> d;
}

subgraph 的形式强制将 b,c 两个节点放在同一水平位置(/subgraph/ 用花括号表示):

digraph{
    label = "same-rank";
    a->b->c->d;
    {
        rank = same;
        b;c;
    }
}

将本来在最低点的 d, 强制拉到最上方:

digraph{
    label = "min-rank";
    a->b->c->d;
    {
        rank = min;
        d;
    }
}

将最高点的 a, 强制沉到最底部:

digraph{
    label = "max-rank";
    a->b->c->d;
    {
        rank = max;
        a;
    }
}

顺序#

又是含糊的一段。 翻了文档,解释是这样的:

所谓的次序就是在 dot 中定义的顺序, out 根据箭头出发节点顺序排列,=in= 根据箭头指向节点顺序排列。

本来想设计一些情景来实验这个功能的,但是似乎不是那么好弄?所以先放着吧,这个功能感觉也不是很常用。

weight 边的重量#

weight 值越高,相应的边就越短,默认值为 1.

digraph{
    a->b;
    a->c[weight=2];
    a->d[weight=4];
}

Advanced Features 高级特性#

Node Ports 节点端口#

通过 headport, tailport 指定边和节点的连接位置,比较适合处理 record 节点,因为可以用 ID 来标识位置。

digraph{
    a -> b[tailport=se];

    pointer[shape=record, label= "{<1> TopLeft|<2> TopRight}|{<3> BotLeft|<4>BotRight}"];

    area[shape=record, label= "{<1>1|<2>2}|{<3>3|<4>4}"];

    pointer:1 -> area:1;
    pointer:2 -> area:2;
    pointer:3 -> area:3;
    pointer:4 -> area:4;
}

Clusters 节点群#

当子图的名称以 cluster 开头时,就被认为是一个 cluster ,最直观的用途是在节点周围画方框。

值得注意的是,当指定 compoundtrue 时,可以将 cluster 作为节点来连接。 如下图中, a -> A 之间直接穿过方框; a->B 因为指定了 lhead 箭头指向的是 cluster_b 方框。

digraph{
    compound = true;
    subgraph cluster_a{
        label = "a";
        a->b;
    }
    subgraph cluster_b{
        label = "b";
        A->B;
    }
    a->A;
    a->B[lhead=cluster_b];
}

Concentrators


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK