处理此问题的最简单方法是允许gvpack
执行重命名,而不是尝试反向重命名,以声明节点的标签。
我有一些用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
:
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS83NzB6bS5qcGcifQ==” alt =“在此处输入图像描述”>
如您所见,gvpack
重新标记了重复的节点名称。但是,我们可以轻松地使用gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg
反转重新标记,这将产生以下图形gvsub.jpg
:
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS93blVtNC5qcGcifQ==” alt =“在此处输入图像描述”>“ >>
此方法依赖于具有共同节点名称的子图,因此可能有必要在子图.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
:
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS84WGpjVC5qcGcifQ==” alt =“在此处输入图像描述”>
因此,在头文件中,我向每个子图添加了一个不可见的节点,名称与子图相同,并使用compound=true
允许聚类之间的边。我指定了要在聚类之间绘制的边缘,并为不可见节点之间的每个边缘设置了lhead
和ltail
,以确保将正确的聚类用作这些边缘中的每个的头和尾。在使用sed
将每个子图转换为群集的过程中,我还向每个子图添加了适当的不可见节点。
显示了节点D,G和A之间的边缘,因为这些节点在群集之间是公用的。此外,它们每个仅显示在一个群集中。如果节点对于群集是唯一的,则群集之间唯一显示的边缘将是不可见节点之间的边缘。在下图中可以看到,我在3.dot
中重命名了节点:
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9Fc0c5ay5qcGcifQ==” alt =“在此处输入图像描述”>
还有一个尚无法解决的缺陷。不可见的节点仍占据一点空间,因此群集框看起来偏斜,因为不可见的节点位于可见节点旁边。这也意味着群集之间的边缘的头部指向群集框的一侧而不是中间。目前,我看不到有什么办法,除非我们准备查看每个子图并找到该子图/群集中已经存在的节点作为该子图/群集的代表节点(即我们向该群集绘制边缘或从中绘制边缘)。手动完成几个子图就可以很容易地做到这一点,但是如果有很多子图,那将是乏味的。
相反,我上面使用的方法仅要求我们知道集群的名称,并将其插入hdr.dot
文件即可。
在这种情况下,我已经手动构建了hdr.dot
文件,但可以从其他hdr.dot
文件中使用.dot
,sed
,awk
或perl
提取python
文件的内容],如果有需要。如果可以在某处获得有关应连接哪些集群的信息,该脚本也可以插入边缘以将集群链接到hdr.dot
。
处理此问题的最简单方法是允许gvpack
执行重命名,而不是尝试反向重命名,以声明节点的标签。
以]开头>
digraph g1 {
A -> B;
A -> C;
A [label="A"];
B [label="B"];
C [label="C"];
}
和
digraph g2 { D -> E E -> F D [label="D"]; E [label="E"]; F [label="F"]; }
和
digraph g3 { D -> G G -> A D [label="D"]; G [label="G"]; A [label="A"]; }
并且您应该从最初的第一步中获得想要的结果
处理此问题的最简单方法是允许gvpack
执行重命名,而不是尝试反向重命名,以声明节点的标签。