【问题标题】:GraphViz - How to connect subgraphs?GraphViz - 如何连接子图?
【发布时间】:2011-01-01 23:49:51
【问题描述】:

GraphVizDOT 语言中,我试图表示一个依赖关系图。我需要能够在容器内拥有节点,并且能够使节点和/或容器依赖于其他节点和/或容器。

我使用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";
}

【问题讨论】:

  • 我遇到了同样的问题,但是他们有一个自然的例子,子图就像节点一样,graphviz.org/content/fdpclust
  • @nlucaroni 我想知道这个问题是否解决了。这个例子给了我错误的图:边连接子图的中心。你不知道如何让它像示例中一样工作吗?
  • @k102,我知道。再次查看该页面;它说你需要使用fdp。链接的示例和上面的示例都有效(此处示例中的最后一行需要使用子图名称而不是标签,并且包含图的线长可能会很好);它有点紧)。
  • @nlucaroni 使用fdp v2.28.0 并复制/粘贴示例中的源代码,这些线连接到子图的中心,而不是边缘。如果您在 OmniGraffle 中打开 .dot,它们会正确连接,而 neatodot 都会为集群创建多余的节点。

标签: graphics graphviz dot directed-graph subgraph


【解决方案1】:

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;
}

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

【讨论】:

  • 谢谢 - 这行得通,但它真的感觉像一个丑陋的黑客。我希望我没有容器没有节点的情况。
  • 万一有人感兴趣,如果您标记了链接(边缘),这可能会导致定位问题。虽然边缘的头部或尾部可能隐藏在群集下方,但标签仍位于中点,这意味着某些边缘标签似乎漂浮在群集上方,而不是由边缘本身定位。
  • @WinstonSmith:老问题,但我有一个类似的问题,并用每个集群的一个不可见的虚拟节点解决了它,即使集群是空的,也可以链接到它。 DUMMY_0 [shape=point style=invis]
  • 当使用仅垂直连接的集群时,我发现我的集群间边缘仅折叠为箭头。我在边缘用minlen=1 修复了这个问题。 c -> g [ltail=cluster0,lhead=cluster1,minlen=1];
  • 这里是带有示例的手册链接:graphviz.org/Documentation/dotguide.pdf(第 30 页)。
【解决方案2】:

为了便于参考,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];
}

graph 声明中的compound=true 至关重要。这会产生输出:

请注意,我将边更改为集群内的引用节点,为每条边添加了 ltail 和 lhead 属性,指定集群名称,并添加了图级属性“compound=true”。

考虑到人们可能想要连接其中没有节点的集群,我的解决方案是总是向每个集群添加一个节点,并以 style=plaintext 呈现。使用此节点标记集群(而不是集群的内置“label”属性,该属性应设置为空字符串(在 Python 中,label='""')。这意味着我不再添加直接连接集群的边,但它适用于我的特定情况。

【讨论】:

  • 注:'graph [fontsize=10 fontname="Verdana" Compound=true];'是必不可少的 - 如果您错过链接到 ltail/lhead 不起作用。
  • @JonathanHartley,根据您的最后一段,有没有办法将该节点置于集群中间?
  • 集群名称也不应该以大写字母开头
  • @s.Daniel 这只是复合=true;这是必需的
  • 链接 "Item 1" -> "Item 3" 时不重置 lhead 和 ltail ,如何将 cluster_0 和 cluster_1 链接到有意义的代码?我想,在你输出时让cluster_0 -> cluster_1 出现。因为 cluster_0 中可能有许多项目链接到 cluster_1 中的其他许多项目(多对多或一对多)。最好只链接两个。
【解决方案3】:

确保您对文件使用fdp 布局。我不认为neato 支持集群。

【讨论】:

  • 我也有经验发现neato引擎不支持集群..我不确定这是否是一个错误..
猜你喜欢
  • 1970-01-01
  • 2017-10-08
  • 2021-11-10
  • 1970-01-01
  • 2013-05-13
  • 2012-11-01
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
相关资源
最近更新 更多