使用Graphviz下的dot工具绘制图像
北风其凉 发表于2年前
使用Graphviz下的dot工具绘制图像
  • 发表于 2年前
  • 阅读 890
  • 收藏 6
  • 点赞 2
  • 评论 0

1小时搭建人工智能应用 让技术更容易入门>>>   

摘要: 使用Graphviz下的dot工具绘制图像

一、关于Graphviz下的dot工具

Graphviz是一个画图软件,其中的dot工具可以用于绘制流程图。dot工具可以根据dot语言代码生成GIF、PNG、SVG、PDF、PostScript格式的图片文件。

通过dot工具,可以绘制出如下面这样复杂的流程图(摘自dot工具官方帮助手册):

dot工具画图通过以下四个步骤来完成:

第一步:通过翻转一些循环边的内部方向,打破在输入图中出现的环路。

第二步:将节点分配给不同的等级(rank)和层次(level),自顶向下绘图,等级决定了纵轴的位置。跨越了多个等级的边,会被拆分成有多个虚拟节点相连接的链条。

第三步:根据节点等级(rank)为节点排序以避免节点的交叉。

第四步:在保持边长尽量短的情况下,设置节点的横坐标,同时绘出边的样条曲线。

dot工具的绘图方法,其官网 www.graphviz.org 上面有着详细的介绍,这里不再做更深层次的说明。本文中我使用的Graphviz版本为2.38

二、使用dot工具生成图片

安装Graphviz后,新建一个文件夹,建立一个bat文件取名【GenerateJpgsBatch.bat】,代码如下:

:: 在这里设置调用文件路径
set dotPath=D:\Graphviz2.38
set sourcePath=C:\Users\Tsybius\Desktop\graphviz_study

rem 测试文件XXX
%dotPath%\bin\dot.exe -Tjpg %sourcePath%\XXX.dot -o %sourcePath%\XXX.jpg

pause

其中dotPath为dot代码文件地址,sourcePath为生成后文件的地址。

上面的代码就是用dot.exe,将一个名为XXX.dot的文件,生成为图片XXX.jpg。

使用dot程序生成带有汉字信息的图片,需要注意两点,否则生成的图片中汉字会被显示为乱码:

1、文件应使用UTF-8编码保存,而不是Windows默认的ANSI编码

2、字体应指定为支持汉字的字体,如宋体为SimSun

三、实例一:最简单的dot图-高速公路节点图

下图是一张高速公路重要节点图。这张图是一张较为简单dot图,只有节点之间的简单指向关系。

文件【expressway.dot】内代码如下:

digraph {

    edge[fontname="SimSun",fontcolor=red];
    node[fontname="SimSun",size="20,20"];

    北京[shape=doublecircle];
    湘潭[shape=plaintext]

    //高速公路节点关系
    北京->石家庄->郑州->武汉->长沙->广州[label=京港澳高速,color=red];
    北京->天津->沈阳->长春->哈尔滨[label=京哈高速,color=lawngreen];
    北京->呼和浩特->银川->兰州->西宁->拉萨[label=京藏高速,color=purple];
    郑州->西安->兰州->乌鲁木齐[label=连霍高速,color=blue]
    上海->杭州->南昌->湘潭->贵阳->昆明[label=沪昆高速,color=orange];
    福州->南昌->武汉->西安->银川[label=福银高速,color=brown];
    湘潭->长沙[style=dotted];
}

生成图片如下:

四、实例二:类HTML语言编写复杂的节点-华容道

dot也支持解释一些类HTML的代码绘制近似于复杂表格的数据。

下图是由一个单一节点组成的,这个节点被划分成很多区域,被绘制成华容道最经典的图形-横刀立马

文件【huarongpass.dot】内代码如下:

digraph {
    huarongpass [shape=none, margin=0, fontname="SimSun" label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
            <TR><TD>张<BR/>飞</TD><TD COLSPAN="2">曹操</TD><TD>马<BR/>超</TD></TR>
            <TR>
                <TD ROWSPAN="2">赵<BR/>云</TD>
                <TD COLSPAN="2">关羽</TD>
                <TD ROWSPAN="2">黄<BR/>忠</TD>
            </TR>
            <TR><TD>卒</TD><TD>卒</TD></TR>
            <TR><TD>卒</TD><TD COLSPAN="2"></TD><TD>卒</TD></TR>
        </TABLE>
    >];
}

生成图片如下:

五、实例三:为图片添加层次关系-世系树

世系树要求将同一个辈分的人放在同一个层次,下面这个例子描绘了汉宣帝从高祖到其自身的世系树,它设置了5个rank。

文件【familytree.dot】内代码如下:

digraph {
    
    ranksep=2.75; size="15,15";
    {
        edge [fontname="SimSun", fontcolor=red];
        //时间线
        node [shape=plaintext, fontname="SimSun", fontsize=60];
        "高祖辈"->"曾祖辈"->"祖父辈"->"父辈"->"本人";
    }

    {
        rank = same;
    };

    node [shape=box, fontname="SimSun", fontsize=60];
    { rank = same; "高祖辈"; "孝景皇帝刘启"; "孝景皇后王氏"; "外高祖父卫父"; "外高祖母卫媪"; }
    { rank = same; "曾祖辈"; "曾祖父世宗武皇帝刘彻"; "曾祖母思皇后卫子夫"; "外曾祖母贞君"; }
    { rank = same; "祖父辈"; "祖父戾太子刘据"; "祖母戾后史氏"; "外祖父思成侯王乃始"; "外祖母博平君思成夫人王媪"; }
    { rank = same; "父辈"; "父悼皇考刘进"; "母悼后王翁须" }
    { rank = same; "本人"; "中宗孝宣皇帝刘询" }

    {"孝景皇帝刘启", "孝景皇后王氏"}->"曾祖父世宗武皇帝刘彻";
    {"外高祖父卫父", "外高祖母卫媪"}->"曾祖母思皇后卫子夫";
    {"曾祖父世宗武皇帝刘彻", "曾祖母思皇后卫子夫"}->"祖父戾太子刘据";
    "外曾祖母贞君"->"祖母戾后史氏"
    {"祖父戾太子刘据", "祖母戾后史氏"}->"父悼皇考刘进";
    {"外祖父思成侯王乃始", "外祖母博平君思成夫人王媪"}->"母悼后王翁须";
    {"父悼皇考刘进", "母悼后王翁须"}->"中宗孝宣皇帝刘询";
}

生成图片如下:

六、实例四:通过创建子图对大图中的节点进行分组-三国君主传承顺序

dot支持可以通过创建子图(subgraph)对节点进行分区,如下图总结三国时代魏蜀吴三国君主传承顺序,将魏、蜀、吴三国的君主分到了各自的区域内。

文件【threekingdoms.dot】内代码如下:

digraph {
    
    edge[fontname="SimSun",fontcolor=red];
    node[fontname="SimSun",size="20,20"];

    subgraph cluster0 {
        color=red;
        "曹操(0)","曹丕(1)","曹叡(2)","曹髦(3)","曹芳(4)","曹奂(5)"[shape=box];
        fontname="SimSun"
        label="#1 魏国";
        "曹操(0)"->{"曹丕(1)", "曹彰", "曹宇"};
        "曹丕(1)"->{"曹叡(2)", "曹霖"};
        "曹霖"->"曹髦(3)"
        "曹彰"->"曹楷"->"曹芳(4)"
        "曹宇"->"曹奂(5)"
    }
    
    subgraph cluster1 {
        color=blue;
        "刘备(0)","刘禅(1)"[shape=box];
        fontname="SimSun"
        label="#2 蜀国";
        "刘备(0)"->"刘禅(1)"
    }

    subgraph cluster2 {
        color=purple;
        "孙坚(0)","孙策(1)","孙权(2)","孙亮(3)","孙休(4)","孙和(5)","孙皓(6)"[shape=box];
        fontname="SimSun"
        label="#3 吴国";
        "孙坚(0)"->{"孙策(1)","孙权(2)"};
        "孙权(2)"->{"孙和(5)","孙休(4)","孙亮(3)"};
        "孙和(5)"->"孙皓(6)";
    }

    "初代君主"->{"曹操(0)","刘备(0)","孙坚(0)"}[style=dotted];
    {"曹奂(5)","刘禅(1)","孙皓(6)"}->"末代君主"[style=dotted];
}

生成图片如下:

END

共有 人打赏支持
北风其凉
粉丝 111
博文 478
码字总数 454824
作品 4
×
北风其凉
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: