这实际上并不是关于最小化边长,特别是因为在示例中边是用属性定义的constraint=false
。
虽然这不是一个完整的答案,但我认为可以在以下两点中找到它:
- 图中节点的出现顺序很重要。
- 更改
rankdir
为LR
包含不可预测(或至少难以预测)的行为,和/或可能仍然是一两个错误(搜索 rankdir)。
我会尽力解释并理解graphviz,但您可能想继续阅读Emden R. Gansner 在graphviz 邮件列表上的回复以及Stephen North 的以下答案 - 他们应该要知道,所以我会引用其中的一些......
为什么节点出现的顺序很重要?默认情况下,在自上而下的图中,首先提到的节点将出现在后续节点的左侧,除非边和约束导致更好的布局。
因此,如果没有集群 和rankdir=LR
,图形看起来像这样(毫不奇怪):
A D G
B E H
C F I
到现在为止还挺好。但是rankdir=LR
应用时会发生什么?
ERG 写道:
Dot 通过正常的 TB 布局处理 rankdir=LR,然后将布局逆时针旋转 90 度(当然,然后处理节点旋转、边缘方向等)。因此,子图 1 在 TB 布局中位于子图 2 的左侧,如您所料,然后在旋转后最终低于它。如果您希望子图 1 位于顶部,请将其列在图中的第二位。
所以如果这是正确的,没有集群,节点应该是这样的:
G H I
D E F
A B C
实际上,它们确实看起来像这样:
A B C
D E F
G H I
为什么?斯蒂芬诺斯 回复:
在某些时候,我们决定从上到下应该是默认设置,
即使图形是旋转的,所以有代码可以在内部翻转平面边缘。
因此,图形布局为 TB,逆时针旋转,平面边缘翻转:
A D G G H I A B C
B E H --> D E F --> D E F
C F I A B C G H I
虽然这对于简单的图表非常有效,但似乎当涉及到集群时,情况就有些不同了。通常边缘也会在簇内翻转(如clusterY
),但在某些情况下,平面边缘翻转并不像人们想象的那样起作用。您的示例就是其中一种情况。
为什么这些边缘的翻转会出现错误或限制?因为在使用rankdir=TB
.
幸运的是,变通方法通常很容易——例如,您可以使用节点的出现顺序来影响布局:
digraph
{
rankdir="LR";
node[shape=record, height="0.4", width="0.4"];
edge[dir=none];
E; // E is first node to appear
A -> B -> C;
D -> E -> F;
G -> H -> I;
edge[constraint=false]
A -> D -> G;
subgraph clusterX { A; B; }
subgraph clusterY { E; F; H; I; }
}