Graphviz:创建从结构到自身的非重叠边

Graphviz: create non overlapping edges from a struct to itself

我正在尝试在 graphviz 中重新创建一张类似于从 CLR book 中截取的图表:

我在 Python 中使用以下代码:

s = Digraph(node_attr={'shape': 'record'})
s.node('struct', '<f0> 3|<f1> 13|<f2> 1|<f3> 2|<f4> 8|<f5> 5')
s.edge("struct:f0", "struct:f1")
s.edge("struct:f0", "struct:f2")
s.edge("struct:f1", "struct:f3")
s.edge("struct:f1", "struct:f4")
s

结果是:

这非常接近我想要的,除了边缘与节点重叠而不是 above/below 它们。

我找不到修改边缘行为的方法。另外,我有一种感觉,我在滥用 graphviz 的 struct 功能,但我不知道如何强制图形元素在一行中粘在一起。

我能否避免边缘重叠(当然,除非自己修改 SVG)或完全使用不同的方法?

您可以使用“端口”来设置连接点。

我在在线服务上试过你的图表,你的渲染似乎是带点的 http://dreampuf.github.io/GraphvizOnline

你可以和其他人一起测试,Circo和其他人不跨单元格,但默认情况下它们都在一侧(底部)绘制并且边缘很乱。

然而,“端口”属性允许通过指定后缀“:s”、“:n”等来解决这个问题。n、s、e、w、nw、ne、sw、s。 - 即南、北等....

似乎 Dot 的默认端口与 Circo 和 Neato 不同,后者可以:

digraph Structs {
    node [shape=record];        
    s [label="<f0> 3|<f1> 13|<f2> 1|<f3>2|<f4>8|<f5>5"];
    s:f0 -> s:f1;
    s:f0 -> s:f2;
    s:f1:n -> s:f3:n;
    s:f1:n -> s:f4:n;
}

dot也需要指定前两个节点的端口:

digraph Structs {
    node [shape=record];       
    s [label="<f0> 3|<f1> 13|<f2> 1|<f3>2|<f4>8|<f5>5"];
    s:f0:s -> s:f1:s;
    s:f0:s -> s:f2:s;
    s:f1:n -> s:f3:n;
    s:f1:n -> s:f4:n;
}

所以我猜,在你的代码中:

s.edge("struct:f0:s", "struct:f1:s")
s.edge("struct:f0:s", "struct:f2:s")
s.edge("struct:f1:n", "struct:f3:n")
s.edge("struct:f1:n", "struct:f4:n")

参见:How to prevent edges in graphviz to overlap each other

Graphviz Dot Edge Ports for Family Tree