十分钟了解绘图神器——Graphviz学习笔记

DOT语言学习笔记

设置点和线的形状与颜色

digraph是有向图,graph是无向图。要注意,->和–都表示图中的一条边,但是前者用于有向图中,而后者用于无向图中,不能混用。

代码示例

diaGraph G{
    main -> parse -> execute
    main -> init
    main -> cleanup
    execute -> make_string
    execute -> printf
    init -> make_string
    main -> printf
    execute -> compare
}

然后在命令行(cmd)中运行此文件,

dot -T输出格式 程序文件名.dot -o 输出文件名.输出格式

我们可以手动设置图的属性,即设置图中边的属性与图中点的属性。

我们可以在每条边后面添加中括号,在其中设置边的相关属性,也可以使用edge设置边的默认值。点的属性设置方法相同,node表示点的默认值。

diGraph G{
    size = "4, 4"  /*设置图片尺寸为4 * 4(英寸)*/
    main[shape = box] /*设置点main形状为矩形,默认为椭圆形*/
    main -> parse[weight = 8]  /*设置main到parse的边的重要程度,默认为1*/
    parse -> execute
    main -> init[style = dotted] /*设置main到init的边的样式为点,默认为实线*/
    main -> cleanup
    execute -> {make_string printf} /*一次连接两条边,以隔开目标点*/
    init -> make_string
    edge[color = red]  /*将此语句后的边的颜色设置为红色*/
    main -> printf[style = bold, label = "100 times"]
    node[shape = box, style = filled, color = ".7 .3 1.0"] /*设置此语句后的点的默认属性, 其中color的值采用RGB标准*/
    make_string[label = "make a\nstring"]
    execute -> compare
    compare -> return
}

此外,还可以使用dir设置每条边的箭头方向,有forward(default),back,both,nonc,分别表示前向,反向,双向和无。如下所示:

digraph G{
    A -> B[dir = both]
    B -> C[dir = nonc]
    C -> D[dir = back]
    D -> A[dir = forward]
}

点的属性除了record和Mrecord这两种之外,其他的形状都是多边形,而我们可以对多边形进行设置。sides用于设置边数,peripheries用于设置多边形外框的层数,regular = true可以使你的多边形是一个规则的多边形,orientation = * 可以让你的多边形旋转*角度,skew后面跟一个(-1.0~1.0)的小数,能使你的图形斜切一个角度,distortion则可以令你的图形产生透视效果。

digraph G{
    a -> b -> c
    b ->d 
    a[shape = polygon, sides = 5, peripheries = 3, color = lightblue, style = filled]
    c[shape = polygon, sides = 4, skew = 0.4, label = "hello world"]
    d[shape = invtriangle]
    e[shape = polygon, sizes = 4, distortion = .7]
}
digraph G{
    A -> B
    A[orientation = 15, regular = true, shape = polygon, sides = 8, peripheries = 4, color = red, style = filled]
    B[shape = polygon, sides = 4, skew = 0.5, color = blue]
}

record与Mrecord的区别就是Mrecord的角是圆的,而record是由横竖的矩形组成的图形。

digraph G{
   node[shape = record]
   struct1[label = " left |  middle |  right"]
   struct2[label = " one |  two"]
   struct3[label = "hello \nworld | {b | {c |  d | e} | f} | g | h"]
   struct1 -> struct2
   struct1 -> struct3
}

当你的线与线的label较多时,可以设置线的属性decorate=true使得每条线与其属性之间产生连线。你还可以为每条线设置属性headlabel,taillabel,给每条线的起始点和终点设置属性,它们的颜色由labelfontcolor决定,而label的颜色由fontcolor来决定。

graph G{
   label = "我爱你" /*为图设置标签*/
   labelloc = b    /*图标签的位置在底部,也可以设置为r到顶部*/
   labeljust = l   /*图标签的位置在左边,也可以设置为r到右边*/

   edge[decorate = true]
   C -- D[label = "s1"]
   C -- E[label = "s2"]
   C -- F[label = "s3"]
   D -- E[label = "s4"]
   D -- F[label = "s5"]

   edge[decorate = false, labelfontcolor = blue, fontcolor = red]
   C1 -- D1[headlabel = "d1", taillabel = "c1", label = "c1 - d1"]
}

在dot语言中,我们可以使用html语言制作表格。在label后添加<>,而不是""就能添加html语言。

digraph html{
   abc[shape = none, margin = 0, label = <
   
hello
world
b g h
c d e
f
>] }

设置点,线的位置以及子图的概念

图中的线默认是从上往下的,我们可以通过在文件的最上层设置rankdir=LR将其改为从左往右。同理,rankdir可以设置为TB(默认),BT,RL。

当图中时间表之类的东西时,我们可能需要点排列成一行(列),这时我们就需要rank,在花括号中设置rank=same,然后将需要并排的点一次输入。

digraph G{
   rankdir = LR
   {
    node[shape = plaintext]
    1995 -> 1996 -> 1997 -> 1998 -> 1999 -> 2000 -> 2001
   }
   {
    node[shape = box, style = filled]
    WAR3 -> Xhero -> Footman -> DOTA
    WAR3 -> Battleship
   }
   {
    {rank = same 1996 WAR3}
    {rank = same 1998 Xhero Battleship}
    {rank = same 1999 Footman}
    {rank = same 2001 DOTA}
   }
}

设立一条边时,我们可以制定这条边从起点的哪个位置出发,到终点的哪个位置结束。控制符有"n",“ne”,“e”,“se”,“s”,“sw”,“w"和"nw”,具体效果见下:

digraph G{
   node[shape = box]
   c:n -> d[label = n]
   c1:ne -> d1[label = ne]
   c2:e -> d2[label = e]
   c3:se -> d3[label = se]
   c4:s -> d4[label = s]
   c5:sw -> d5[label = sw]
   c6:w -> d6[label = w]
   c7:nw -> d7[label = nw]
}

我们也可以在record中给点定义一些port,以确定record中哪个部分用于连线。

digraph G{
   label = "Binary Search Tree"
   node[shape = record]
   A[label = " |  A | "]
   B[label = " |  B | "]
   C[label = " |  C | "]
   D[label = " |  D | "]
   E[label = " |  E | "]
   A: f0: sw -> B: f1
   A: f2: se -> C: f1
   B: f0: sw -> D: f1
   B: f2: se -> E: f1
}

我们可以借此构建一个Hash表。

digraph G{
    nodesep = .05
    rankdir = LR
    node[shape = record, width = .1, height = .1]
    
    node0[label = " |  |  |  |  |  | ",height = 2.5]
    
    node[width = 1.5]
    
    node1[label = "{ n14 | 719 | 

}"] node2[label = "{ a1 | 805 |

}"] node3[label = "{ i9 | 718 |

}"] node4[label = "{ e5 | 989 |

}"] node5[label = "{ t20 | 959 |

}"] node6[label = "{ o15 | 794 |

}"] node7[label = "{ s19 | 659 |

}"] node0: f0 -> node1: n node0: f1 -> node2: n node0: f2 -> node3: n node0: f5 -> node4: n node0: f6 -> node5: n node2: p -> node6: n node4: p -> node7: n }

画一个子图就是subgraph cluster#,必须有clutser前缀。这里"#“代表任意字符,当然为了便于区分,最好将”#"设置为非英文字母。

digraph G{
    subgraph cluster1{
       node[style = filled, color = white]
       style = filled
       color = lightgrey
       a0 -> a1 -> a2 -> a3
       label = "process1"
    }

    subgraph cluster2{
        node[style = filled]
        color = blue
        b0 -> b1 -> b2 -> b3
        label = "process2"
    }
    start -> a0
    start -> b0
    a1 -> b3
    b2 -> a3
    a3 -> a0
    a3 -> end
    b3 -> end
    start[shape = Mdiamond]
    end[shape = Msquare]
}

如果你想将一条边连到一个子图的边界上,先输入compound=true,然后就能用lhead和ltail设置连接的子图。

附录

  • 点,边和图的属性

    http://www.graphviz.org/doc/info/attrs.html

  • 点的形状

    http://www.graphviz.org/doc/info/shapes.html

  • 颜色设置

    http://www.graphviz.org/doc/info/colors.html

你可能感兴趣的:(编程)