War*_*now 3 dot graphviz subgraph
我有这个Graphviz图:
digraph
{
rankdir="LR";
overlap = true;
Node[shape=record, height="0.4", width="0.4"];
Edge[dir=none];
A B C D E F G H I
A -> B -> C
D -> E -> F
G -> H -> I
Edge[constraint=false]
A -> D -> G
subgraph clusterX
{
A
B
}
subgraph clusterY
{
E
H
F
I
}
}
Run Code Online (Sandbox Code Playgroud)
产生这个输出:

我原本期望A和D之间的边缘长度最小化,以便节点排列为:
A B C
D E F
G H I
Run Code Online (Sandbox Code Playgroud)
而不是
D E F
G H I
A B C
Run Code Online (Sandbox Code Playgroud)
如果我删除子图定义,这将按预期工作.
为什么Graphviz在引入子图时将ABC置于底部?
这实际上并不是最小化边长,特别是因为在示例中边是用属性定义的constraint=false.
虽然这不是一个完整的答案,但我认为它可以在以下两点内找到:
rankdir为LR包含不可预测(或至少难以预测)的行为,和/或可能仍然是一两个错误(搜索rankdir).我会尝试尽可能地解释并理解graphviz,但是你可能想要继续阅读Emden R. Gansner在graphviz邮件列表上的回复以及Stephen North的以下答案 - 他们应该要知道,所以我会引用一些......
为什么节点的出现顺序很重要?默认情况下,在自上而下的图形中,首先提到的节点将出现在以下节点的左侧,除非边和约束导致更好的布局.
因此,没有集群rankdir=LR,图表看起来像这样(没有惊喜):
A D G
B E H
C F I
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但是什么时候rankdir=LR应用?
ERG写道:
Dot通过普通TB布局处理rankdir = LR,然后逆时针旋转布局90度(当然,然后处理节点旋转,边缘方向等).因此,子图1在TB布局中位于子图2的左侧,正如您所期望的那样,然后在旋转后最终低于它.如果您希望子图1位于顶部,请在图表中将其列为第二个.
因此,如果这是正确的,没有集群,节点应该如下所示:
G H I
D E F
A B C
Run Code Online (Sandbox Code Playgroud)
实际上,它们看起来像这样:
A B C
D E F
G H I
Run Code Online (Sandbox Code Playgroud)
为什么?Stephen North回答说:
在某些时候,我们决定从上到下应该是默认值,
即使图形被旋转,所以有代码在内部翻转平边.
因此,图形布局为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
Run Code Online (Sandbox Code Playgroud)
虽然这对于简单的图表非常有效,但似乎在涉及集群时,事情会有所不同.通常边缘也会在簇内翻转(如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; }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2188 次 |
| 最近记录: |