graphviz - Graphviz 中的图形图

标签 graphviz dot

我有一组用 DOT 语言编码的有向图。我想构建一个图图,使得超图中的每个节点都是这些有向图之一。有没有办法在 GraphViz 框架内做到这一点?

我知道gvpack将允许我将多个图形组合成一个 .dot 文件。但我不知道它是否允许我声明这些图之间的边。

最佳答案

简短的回答是 gvpack不声明子图之间的边。事实上,当子图之间有共同的节点名称时,gvpack重命名它们以避免冲突。但是,这是可以修复的。

例如,给定三个 .dot文件 1.dot :

digraph {
    A -> B
    A -> C
    }
2.dot :
digraph {
    D -> E
    E -> F
    }

...和3.dot :
digraph {
    D -> G
    G -> A
    }

... 运行 gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg给出下图gvp1.jpg :

enter image description here

如您所见,gvpack已重新标记重复的节点名称。但是,我们可以使用 gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg 轻松逆转重新标记。 , 生成下图 gvsub.jpg :

enter image description here

这种方法依赖于具有共同节点名称的子图,因此可能需要在子图中插入额外的节点 .dot文件来实现这一点。

(编辑:上面的解决方案显示了节点合并但不与集群中的子图合并的图。以下解决方案显示了集群中的子图。)

给定 .dot文件 1.dot (这些与上面的文件相同,除了我给每个有向图命名):
digraph g1 {
    A -> B
    A -> C
    }
2.dot :
digraph g2 {
    D -> E
    E -> F
    }

...和3.dot :
digraph g3 {
    D -> G
    G -> A
    }

...连同hdr.dot :
digraph GMaster {
    compound = true;
    g1 [style=invisible, height = 0, width = 0, label=""];
    g2 [style=invisible, height = 0, width = 0, label=""];
    g3 [style=invisible, height = 0, width = 0, label=""];
    g1 -> g2 [lhead=clusterg2, ltail=clusterg1];
    g1 -> g3 [lhead=clusterg3, ltail=clusterg1]

...和tail.dot :
}

...我们可以运行 cat 1.dot 2.dot 3.dot | sed 's/digraph \(\w*\) *{/subgraph cluster\1 { \1/' | cat hdr.dot - tail.dot | dot -Tjpg -oclust1.jpg给文件clust1.jpg :

enter image description here

因此,在头文件中,我为每个子图添加了一个不可见节点,与子图同名,使用 compound=true允许集群之间的边缘。我已经指定了要在集群之间绘制的边缘,并且我已经设置了 lheadltail对于不可见节点之间的每个边,以确保将正确的簇用作每个边的头和尾。在使用 sed 将每个子图转换为集群的过程中,我还为每个子图添加了适当的不可见节点。 .

显示了节点 D、G 和 A 之间的边,因为这些节点在集群之间是公共(public)的。此外,它们中的每一个都只显示在一个集群中。如果节点对集群来说是唯一的,那么集群之间唯一显示的边将是不可见节点之间的边。这可以在下图中看到,其中我重命名了 3.dot 中的节点:

enter image description here

还有一个我还没有完全修复的缺陷。不可见节点仍然占用一点空间,因此集群框看起来不平衡,因为不可见节点位于可见节点旁边。这也意味着簇之间的边的头部指向簇框的一侧而不是中间。目前,我看不出对此能做些什么,除非我们准备好查看每个子图并找到一个已经在该子图/集群中的节点作为该子图/集群的代表节点(即我们为该集群绘制边缘的对象)。对于几个子图,这可以很容易地手动完成,但如果有很多子图,那就太乏味了。

相比之下,我上面使用的方法只需要我们知道集群的名称并且可以将其插入到 hdr.dot 中。文件。

我已经构建了 hdr.dot在这种情况下手动归档,但 hdr.dot 的内容文件可以从另一个 .dot 中提取带有 sed 的文件, awk , perlpython如果有需要。该脚本还可以插入边以将集群链接到 hdr.dot是否可以在某处获得有关应连接哪些集群的信息。

关于graphviz - Graphviz 中的图形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16488216/

相关文章:

plot - 如何使用Graphviz绘制箭头指向的节点?

python-2.7 - 从 DOT 文件在 python 中使用 graphviz 绘制有向图

pycharm - 在 PyCharm 中可视化点文件

java - 从 RDF 文件生成 .DOT 文件

java - 您如何获得项目的可视化 map ?

regex - 帮助在类似 C 的语言中提取匹配花括号之间的文本 block

graphviz - Graphviz .dot节点排序

Graphviz 点算法

width - GraphViz 设置页面宽度

python - Pygraphviz/networkx 设置节点级别或层