7

好的,我知道在 GraphViz 中排序节点的问题已经被散列到了濒临死亡的地步,但我还没有看到有人解决排序集群的问题。我尝试了书中的所有技巧:

  • 文件中节点的顺序是从左到右。如果我不添加集群,dot 只会做正确的事情并以正确的顺序显示它们而无需任何提示。但是,当添加集群时,点会打乱(随机化?)顺序。

  • 我添加了不可见的边缘来尝试强制子集群之间的顺序;但似乎一旦将子集群放置在集群内,dot 就会决定一些特定的顺序,并且会毫不犹豫地让边缘遍布地图以保留它。

  • 由于节点顺序和不可见边使我失败,我转而尝试强制节点的位置。这再次失败,因为只有 dot 会进行聚类,并且它会忽略输入位置。甚至通过 fdp 运行 dot 的未修改输出(使用生成的位置)也会导致崩溃,所以我也放弃了那个方向。

这是一个生成下图的示例点文件。绿线是我添加的“不可见”边缘,但未成功尝试强制 dot 从左到右排序所有内容。如果这成功了,绿线将从锚点向左穿过节点,然后向右移动,而不会相互交叉。例如,每个 be.0 将位于其兄弟 be.1 的左侧,对于 tg-s 也是如此)。如您所见, dot 打乱了子集群的顺序(将 .1 同级放在 .0 的左侧)。就好像它是故意这样做的,由于一些限制,不管任何边缘。我找不到任何方法来说服它不这样做。这非常令人沮丧,因为生成的图表非常适合我的需求。

乱序点簇
(来源:ben-kiki.org

所以。有什么办法可以强制 dot 尊重集群内集群的某种顺序?

编辑:进一步研究,似乎集群的默认顺序与节点的顺序相反。也就是说,通常(在 TB 图中),文本中最先出现的节点往往会出现在文本中稍后出现的节点的左侧;但似乎首先出现在文本中的子集群往往会出现在文本中稍后出现的子集群的右侧。现在,如果这是一条硬性规定,生活将是美好的;然而,dot 仍然有时(但不那么频繁)坚持重新排列子集群,不管任​​何由此产生的交叉边缘,似乎“只是因为”。所以问题仍然存在。

4

1 回答 1

1

有点晚了,但这里有一些其他的想法:(示例数据有点大,无法使用)

无论如何,您是否尝试过:

  • edge[constraint=false] 在一些黑/红线上(constraint=false 可能会出现一些奇怪的长边路由)
  • 和/或 edge[weight=1000] 在绿线上(更难正确),
  • 你可能还想加入更多的脚手架
  • 你不能在集群中排名=相同,所以如果需要它必须在脚手架节点上

这是一个轻量级的例子,它成功地改变了包括集群在内的一半节点的顺序

digraph G {
    subgraph cluster_sa{
    edge[weight=1000]
    subgraph cluster_s1a{ s1a1->s1a2 }
    subgraph cluster_s2a{ s2a1->s2a2 }
    subgraph cluster_s1a_{ s1a1_->s1a2_ }
    subgraph cluster_s2a_{ s2a1_->s2a2_ }
    s1a2->s1a1_
    s2a2->s2a1_
    }
{
    edge[constraint=false]
    subgraph cluster_ta{
    subgraph cluster_t1a{ t1a1->t1a2 }
    subgraph cluster_t2a{ t2a1->t2a2 }
    subgraph cluster_t1a_{ t1a1_->t1a2_ }
    subgraph cluster_t2a_{ t2a1_->t2a2_ }
    t1a2->t1a1_
    t2a2->t2a1_
    }
    edge[tailport=s headport=s]
    s1a2_->t1a1
    s2a2_->t2a1
}
edge[color=green]
node[color=green]
{rank=same s1a0->s2a0->t2a0->t1a0}
s1a0->s1a1
s2a0->s2a1
t1a0->t1a2_
t2a0->t2a2_

t1a2_->t1a1_->t1a2->t1a1
t2a2_->t2a1_->t2a2->t2a1
}

在 viz-js.com 上呈现

弯曲

有时以反向顺序连接节点也可能很有用(例如 t2a2_->t2a1_[dir=back] 而不是上面的实际上会更好,因为绿色箭头可以被删除,给出一个直的黑色箭头)但我不认为这对你的情况会有所帮助

于 2019-01-04T21:05:11.237 回答