我有一组用DOT语言编码的有向图.我想构建一个图形图形,使得超图中的每个节点都是这些有向图之一.有没有办法在GraphViz框架内执行此操作?
我知道这gvpack将允许我将多个图组装成一个.dot文件.但我不知道它是否允许我在这些图之间声明边缘.
简短的回答是gvpack不会在子图之间声明边.实际上,当子图之间存在公共节点名称时,gvpack重命名它们以避免冲突.但是,这是可以解决的.
例如,给定三个.dot文件1.dot:
digraph {
A -> B
A -> C
}
Run Code Online (Sandbox Code Playgroud)
2.dot:
digraph {
D -> E
E -> F
}
Run Code Online (Sandbox Code Playgroud)
......和3.dot:
digraph {
D -> G
G -> A
}
Run Code Online (Sandbox Code Playgroud)
...运行gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg给出如下图gvp1.jpg:

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

这种方法依赖于具有共同节点名称的子图,因此可能需要在子图.dot文件中插入其他节点来实现此目的.
(编辑:上面的解决方案显示了节点合并但不与群集中的子图合并的图.以下解决方案显示了群集中的子图.)
给定.dot文件1.dot(这些与上面的文件相同,除了我给每个有向图命名):
digraph g1 {
A -> B
A -> C
}
Run Code Online (Sandbox Code Playgroud)
2.dot:
digraph g2 {
D -> E
E -> F
}
Run Code Online (Sandbox Code Playgroud)
......和3.dot:
digraph g3 {
D -> G
G -> A
}
Run Code Online (Sandbox Code Playgroud)
......以及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]
Run Code Online (Sandbox Code Playgroud)
......和tail.dot:
}
Run Code Online (Sandbox Code Playgroud)
...我们可以运行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:

因此,在头文件中,我为每个子图添加了一个invisble节点,其名称与子图相同,用于compound=true允许集群之间的边.我所指定的边缘处的簇之间的绘制和我设置lhead并且ltail用于每个隐形节点之间的边缘,以确保正确的簇被用作每个那些边缘的头部和尾部.我还在使用每个子图转换成一个集群的过程中为每个子图添加了相应的不可见节点sed.
显示节点D,G和A之间的边缘,因为这些节点在簇之间是共同的.此外,它们中的每一个仅显示在一个群集中.如果节点对于簇是唯一的,则在簇之间显示的唯一边缘将是不可见节点之间的边缘.这可以在下图中看到,我在其中重命名了以下节点3.dot:

还有一个我无法解决的缺陷.不可见节点仍占用一点空间,因此集群框看起来不平衡,因为隐藏节点位于可见节点旁边.这也意味着簇之间的边缘的头部指向簇盒的一侧而不是中间.目前,我无法看到可以做些什么,除非我们准备查看每个子图并找到一个已经在该子图/集群中的节点作为该子图/集群的代表节点(即我们为该集群绘制边缘的一个或多个.对于一些子图,这可以很容易地手工完成,但如果有许多子图则会很乏味.
相比之下,我上面使用的方法只需要知道集群的名称并将其插入到hdr.dot文件中.
我已经构建了hdr.dot手工文件对于这种情况,但内容hdr.dot文件可以从其他中提取.dot的文件有sed,awk,perl或者python如果有必要.hdr.dot如果有关哪些集群应该连接的信息在某处可用,则脚本还可以插入边缘以链接集群.
| 归档时间: |
|
| 查看次数: |
3609 次 |
| 最近记录: |