一个脚本如何最优地布局一个纯层级的Graphviz/dot图形?

6

我将要写一个脚本,生成具有以下两个特征的Graphviz / Dot图:

  1. 除了一个节点外,所有节点都只有一个父节点(因此是一棵树)。
  2. 如果两个或更多节点共享相同的父节点,则它们本身应按特定顺序排序。

基于这些特征,我希望我的结果图(即dot生成的图形)看起来像这样:

  1. 没有边会交叉
  2. 具有相同父级的节点应该与图的顶部边界保持相同距离。
  3. 具有相同父级的节点应按照其排序从左到右绘制。

然而,我无法让dot表现出我想要的方式。这里有一个dot文件来演示我的问题:

digraph G {

  node [shape=plaintext fontname="Arial"];

  0  [label="zero"      ];
  1  [label="one"       ];
  2  [label="two"       ];
  3  [label="three"     ];
  4  [label="four"      ];
  5  [label="five"      ];
  6  [label="six"       ];
  7  [label="seven"     ];
  8  [label="eight"     ];
  9  [label="nine"      ];
  10 [label="ten"       ];
  11 [label="eleven"    ];
  12 [label="twelve"    ];
  13 [label="thirteen"  ];
  14 [label="fourteen"  ];
  15 [label="fivteen"   ];
  16 [label="sixteen"   ];
  17 [label="seventeen" ];
  18 [label="eighteen"  ];
  19 [label="nineteen"  ];
  20 [label="twenty"    ];
  21 [label="twenty-one"];
  22 [label="twenty-two"];

  0  -> 1  [arrowhead=none];
  1  -> 2  [arrowhead=none];
  2  -> 7  [arrowhead=none];
  7  -> 8  [arrowhead=none];
  8  -> 9  [arrowhead=none];
  8  -> 10 [arrowhead=none];
  9  -> 10 [color="#aaaaaa" constraint=false];
  10 -> 11 [arrowhead=none];
  10 -> 12 [arrowhead=none];
  11 -> 12 [color="#aaaaaa" constraint=false];
  7  -> 13 [arrowhead=none];
  8  -> 13 [color="#aaaaaa" constraint=false];
  13 -> 14 [arrowhead=none];
  7  -> 15 [arrowhead=none];
  13 -> 15 [color="#aaaaaa" constraint=false];
  15 -> 16 [arrowhead=none];
  15 -> 17 [arrowhead=none];
  16 -> 17 [color="#aaaaaa" constraint=false];
  2  -> 3  [arrowhead=none];
  7  -> 3  [color="#aaaaaa" constraint=false];
  3  -> 4  [arrowhead=none];
  2  -> 5  [arrowhead=none];
  3  -> 5  [color="#aaaaaa" constraint=false];
  5  -> 6  [arrowhead=none];
  2  -> 18 [arrowhead=none];
  5  -> 18 [color="#aaaaaa" constraint=false];
  18 -> 19 [arrowhead=none];
  19 -> 20 [arrowhead=none];
  19 -> 21 [arrowhead=none];
  20 -> 21 [color="#aaaaaa" constraint=false];
  18 -> 22 [arrowhead=none];
  19 -> 22 [color="#aaaaaa" constraint=false];
}

导致的结果是

导致的图形

请注意,兄弟节点之间的顺序由灰色边缘(箭头)表示。

例如,我对七 -> 三 -> 五 -> 十八这些兄弟很满意,因为它们按照正确的顺序从左到右绘制(如箭头所示)。

但是,我对八 -> 十三 -> 十五这些兄弟不满意,因为它们的边缘穿过其他边缘,并且它们的顺序不是我想要的从左到右。

此外,九 -> 十二十 -> 二十一十九 -> 二十二方向错误。

我知道如果使用额外的(不可见)边缘和weight属性以及可能更多的功能,我可能可以得到我想要的图片。但是,因为这些图表(而且有很多)是由脚本生成的,我无法手动执行此操作。

那么,有没有办法实现我想要的效果?

1个回答

13
在这种情况下,实际上非常简单:脚本中节点出现的顺序确实很重要。在您的脚本中,它们从节点0到节点22出现,并尽可能地按照这个顺序布置。但是,它们应该按照您添加边缘的顺序出现(0、1、2、7、3、5、18等)。因此,最简单的解决方法是将定义标签的块 移动到 定义边缘的块之后,您将会得到:

有序的图表

没有权重、没有不可见的边和没有不可见的节点。


1
因此,通常情况下,节点ID在dot文件中出现得越早,相应的节点就越有可能出现在左侧? - René Nyffenegger
1
至少在这种情况下是这样的,如果没有边交叉的话。否则,dot将尝试最小化边交叉。Emden Ganser在graphviz论坛上发表了有趣的最近相关评论:http://www.graphviz.org/content/does-dot-layout-optimization-work-not-perfect#comment-770 - marapet

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