GraphViz-如何连接子图?


166

用的DOT语言GraphViz,我试图表示一个依赖关系图。我需要能够在容器内具有节点,并能够使节点和/或容器依赖于其他节点和/或容器。

subgraph用来代表我的容器。节点链接工作正常,但我不知道如何连接子图。

给定下面的程序,我需要能够连接cluster_1cluster_2使用箭头,但是我尝试过的任何操作都会创建新节点而不是连接集群:

digraph G {

    graph [fontsize=10 fontname="Verdana"];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Renders fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Both of these create new nodes
    cluster_1 -> cluster_2;
    "Container A" -> "Container C";
}

在此处输入图片说明


2
我遇到了同样的问题,但是他们有一个自然的例子,子图的行为就像节点graphviz.org/content/fdpclust
nlucaroni 2011年

1
@nlucaroni我想知道这个问题是否解决。这个例子给了我错误的图形:边连接子图形的中心。您不知道如何使其像示例中那样工作吗?
k102 2012年

1
@ k102,我知道。再次查看该页面;它说你需要使用fdp。链接的示例以及上面的示例均起作用(此处示例的最后一行需要使用子图名称而不是标签,并且包括图形的行长可能会很好);它有点紧)。
nlucaroni 2012年

1
@nlucaroni使用fdpv2.28.0并从示例中复制/粘贴源代码,这些线连接到子图的中心,而不是边缘。如果你的OmniGraffle打开.DOT它们已正确连接,同时neatodot两者为集群创建多余节点。
Phrogz

Answers:


190

DOT用户手册提供了以下带有簇的图示例,其中簇之间具有边:

重要说明:初始compound=true声明是必需的。

digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

...以及节点和群集之间的边缘:

在此处输入图片说明


14
谢谢-可以,但是确实感觉像是一个丑陋的骇客。我希望我没有一个没有节点的容器的场景。
温斯顿·史密斯,2010年

5
如果有人感兴趣,如果您标记了链接(边),这可能会导致定位问题。尽管边缘的头部或尾部可能隐藏在群集下,但标签仍位于中点,这意味着某些边缘标签似乎漂浮在群集上,而不是由边缘本身定位。
温斯顿·史密斯,2010年

58
@WinstonSmith:老问题了,但是我遇到了类似的问题,并为每个群集使用了一个不可见的虚拟节点来解决它,即使该群集为空,也可以将其链接到。DUMMY_0 [shape=point style=invis]
DevSolar 2012年

2
当使用仅垂直连接的群集时,我发现群集之间的边缘仅折叠为箭头。我用minlen = 1 固定了边缘。c-> g [ltail = cluster0,lhead = cluster1,minlen = 1];
Freenerd 2014年

3
以下是带有示例的手册链接:graphviz.org/Documentation/dotguide.pdf(第30页)。
Kirill Bulygin

90

为了便于参考,HighPerformanceMark的答案中描述的解决方案如下所示:

digraph G {

    graph [fontsize=10 fontname="Verdana" compound=true];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Edges between nodes render fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Edges that directly connect one cluster to another
    "Item 1" -> "Item 3" [ltail=cluster_0 lhead=cluster_1];
    "Item 1" -> "Item 5" [ltail=cluster_0 lhead=cluster_2];
}

compound=truegraph声明中是至关重要的。产生输出:

具有连接簇的图

请注意,我将边缘更改为群集中的参考节点,将ltail和lhead属性添加到每个边缘,指定了群集名称,并添加了图形级属性'compound = true'。

关于可能要连接一个群集而内部没有节点的担心,我的解决方案是始终向每个群集添加一个节点,并使用style = plaintext呈现。使用此节点标记集群(而不是集群的内置“ label”属性,该属性应设置为空字符串(在Python中label='""')。这意味着我不再添加直接连接集群的边,但是在我的特定情况下有效。


24
注意:'graph [fontsize = 10 fontname =“ Verdana” compound = true];' 是必不可少的-如果您错过了链接到ltail / lhead的操作将不起作用。
s.Daniel

1
@JonathanHartley,根据您的最后一段,有什么方法可以使该节点位于群集中间吗?
Pacerier,2014年

集群的名称也不应以大写字母开头
JCLL

7
@ s.Daniel这只是化合物= true;这是必需的
MaxVölkel博士

链接“ Item 1”->“ Item 3”时,不是重置lhead和ltail,我该如何用有意义的代码链接cluster_0和cluster_1?我要说的是,cluster_0 -> cluster_1在您输出时呈现礼物。因为cluster_0中可能有许多项目链接到cluster_1中的其他许多项目(多对多或一对多)。只需链接两个即可。
秘银

11

确保您正在使用fdp文件的布局。我不neato支持集群。


2
我也有经验上发现,该neato引擎不支持集群..我不知道这是否是一个错误或不..
罗斯·罗杰斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.