将子图之间的边强制向左或向右走

3
我有一个PATRICA trie,正在生成一个GraphViz文件。内部节点是跳过值,边缘是虚线0和实线1。最好将0放在1左边,给叶子节点一个字母顺序。我重新排列了访问图的顺序,所以dot给出了这个结果。但是,当我使用子图将它们分组成森林时,我似乎无法强制dot可靠地尊重子图之间的边缘顺序。
digraph {
    rankdir=TB;
    node [shape = box, style = filled, fillcolor = lightsteelblue];
    // forest size 2.

    subgraph cluster_tree0 {
        style = filled; fillcolor = lightgray; label = "tree 0";
        // branches
        branch0_0 [label = "3", shape = none, fillcolor = none];
        branch0_0 -> branch0_1;
        branch0_1 [label = "0", shape = none, fillcolor = none];
        branch0_1 -> branch0_2 [style = dashed];
        branch0_2 [label = "1", shape = none, fillcolor = none];
        branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
        branch0_2 -> leaf0_2 [color = royalblue];
        branch0_1 -> branch0_3;
        branch0_3 [label = "2", shape = none, fillcolor = none];
        branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
        branch0_3 -> leaf0_4 [color = royalblue];
        // leaves
        leaf0_1 [label = "u"];
        leaf0_2 [label = "v"];
        leaf0_3 [label = "x"];
        leaf0_4 [label = "y"];
    }
    branch0_0 -> branch1_0 [lhead = cluster_tree0, ltail = cluster_tree1, color = firebrick, style = dashed];

    subgraph cluster_tree1 {
        style = filled; fillcolor = lightgray; label = "tree 1";
        // branches
        branch1_0 [label = "0", shape = none, fillcolor = none];
        branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
        branch1_0 -> branch1_1;
        branch1_1 [label = "1", shape = none, fillcolor = none];
        branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
        branch1_1 -> branch1_2;
        branch1_2 [label = "0", shape = none, fillcolor = none];
        branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
        branch1_2 -> leaf1_3 [color = royalblue];
        // leaves
        leaf1_0 [label = "f"];
        leaf1_1 [label = "m"];
        leaf1_2 [label = "n"];
        leaf1_3 [label = "o"];
    }

}

在一个图表上,它运行得很好,但子图的顺序与我想要的相反。

Patrica tree.

我在文件中反转了顺序,但它看起来仍然一样。我试着用 rank=sameordering=outinvis 边缘来调整它,不知怎么搞的就把它翻转了,但我希望它是程序化的。有没有简单的方法将表示 0 的红色虚线画到实线表示 1 的左侧,而不是右侧?

你是在询问如何通过编程将“Tree 1”放置在“Tree 0”的左侧吗? - sroush
是的,那就是我想要的。这样字母就是按顺序排列的。在ASCII中,所有字母的第4个MSB对于树1为0,对于树0为1。 - Neil
你是如何使用rank=same、ordering=out和invis做到的? - sroush
我想我可以反着画,“branch1_0 -> branch0_0 [lhead = cluster_tree1, ltail = cluster_tree0, color = firebrick, style = dashed, dir = back];” 这样就可以按正确的顺序排列它们,但是垂直间距会有问题,很难预测。我尝试了很多方法。 - Neil
1个回答

1

enter image description here

好的,这是一个完全的临时解决方案,但可能是可以完全脚本化的。

首先,您的输入需要进行一些改进:

digraph {
    rankdir=TB;
    newrank=true  // helps
    graph [splines=false]
    node [shape = box, style = filled, fillcolor = lightsteelblue];
    // forest size 2.

    subgraph cluster_tree1 {
        style = filled; fillcolor = lightgray; label = "tree 1";
        // branches
        branch1_0 [label = "0", shape = none, fillcolor = none];
        branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
        branch1_0 -> branch1_1;
        branch1_1 [label = "1", shape = none, fillcolor = none];
        branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
        branch1_1 -> branch1_2;
        branch1_2 [label = "0", shape = none, fillcolor = none];
        branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
        branch1_2 -> leaf1_3 [color = royalblue];
        // leaves
        leaf1_0 [label = "f"];
        leaf1_1 [label = "m"];
        leaf1_2 [label = "n"];
        leaf1_3 [label = "o"];
    }
  subgraph cluster_tree0 {
        style = filled; fillcolor = lightgray; label = "tree 0";
        // branches
        branch0_0 [label = "3", shape = none, fillcolor = none];
        branch0_0 -> branch0_1;
        branch0_1 [label = "0", shape = none, fillcolor = none];
        branch0_1 -> branch0_2 [style = dashed];
        branch0_2 [label = "1", shape = none, fillcolor = none];
        branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
        branch0_2 -> leaf0_2 [color = royalblue];
        branch0_1 -> branch0_3;
        branch0_3 [label = "2", shape = none, fillcolor = none];
        branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
        branch0_3 -> leaf0_4 [color = royalblue];
        // leaves
        leaf0_1 [label = "u"];
        leaf0_2 [label = "v"];
        leaf0_3 [label = "x"];
        leaf0_4 [label = "y"];
    }
    // position the clusters (trees)
    {rank=same    branch1_0 ->  branch0_1 [style=invis weight=0]} 
  
     // a kludge, we'll add this edge in later
     graph [comment="branch0_0 -> branch1_0 [color = firebrick, style = dashed  constraint=false weight=0 ];"]
}

"问题"在于簇与簇之间的分支,所以我们将其删除(第一个点通行)。然后,我们添加无形边缘来定位我们想要的簇。
运行此输入到dot -Tdot > myfile.dot。这为所有节点和边缘设置位置。
通过gawk(任何语言)运行,以取消注释的分支并插入文件中。
最后,neato -n2 -Tpng fixedfile >fixed.png
(很难看,但有效)。"

f=atrie4.gv;

T=png; F=`basename $f .gv`;dot -Tdot $f >$F.dot;
gawk '
$1~/comment/{
  sub(/[\t ]*comment="/,"")
  sub(/"[\],;]?[\t ]*$/,"")
  add[++a]=$0
  next
}
{oline[++o]=$0}
END{
  for (i=1;i<o;i++)print oline[i]
  for (i=1;i<=a;i++)print add[i]
  print oline[o]
}' $F.dot|
neato -n2 -Tpng >$F.$T
firefox $F.$T 

这真是太棒了。为什么要使用 neato -n2,关闭样条有什么帮助? - Neil
1
样条设置没有任何影响,这是一个(失败的)实验留下的。这个链接(https://www.graphviz.org/faq/#FaqDotWithNodeCoords)解释了`neato -n(或neato -n2)。-n2`并不是必需的,但为什么要重新计算边缘,当我喜欢从点出来的边缘。再次强调,最终布局没有任何区别。 - sroush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接