graphviz - Graphviz Dot,不同形状的自指向箭头
问题描述
我正在尝试制作一个具有到某些节点的一些环回的最终状态机。
digraph g{
rankdir=TB;
forcelabels=true;
ranksep=1.5;
pad=0.5;
nodesep=2;
node[shape=circle];
A[label="Wait for call\n0 from above"];
B[label="Wait for\nACK 0 || ACK 1"];
E[label="Wait for call\n1 from above"];
F[label="Wait for\nACk 2 || ACK 3"];
C[label="Wait for ACK 0"];
D[label="Wait for ACK 1"];
G[label="Wait for ACK 2"];
H[label="Wait for ACk 3"];
A -> B[label=" rdt_send(data) \n sndpkt=make_pkt(0,data,checksum) \n udt_send(sndpkt) \n start_timer 1 and 2 \n"];
B -> D[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,0) \n stop_timer 1"];
B -> C[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,1) \n stop_timer 2"];
C -> E[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,0) \n stop_timer 2"];
D -> E[label= " rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,1) \n stop_timer 1"];
C:nw -> C:nw[constraint=none,xlabel="PLACEHOLDER"];
C:sw -> C:sw[constraint=none,xlabel="PLACEHOLDER"];
D:ne -> D:ne[constraint=none,xlabel="PLACEHOLDER"];
D:se -> D:se[constraint=none,xlabel="PLACEHOLDER"];
E -> F[constraint=none, xlabel=" \n rdt_send(data) \n sndpkt=make_pkt(1,data,checksum) \n udt_send(sndpkt)\n start_timer "];
F -> G[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,3) \n stop_timer "];
F -> H[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,2) \n stop_timer "];
G -> A[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,3) \n stop_timer "];
H -> A[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,2) \n stop_timer "];
G:sw -> G:sw[constraint=none,xlabel="PLACEHOLDER"];
G:nw -> G:nw[constraint=none,xlabel="PLACEHOLDER"];
H:se -> H:se[constraint=none,xlabel="PLACEHOLDER"];
H:ne -> H:ne[constraint=none,xlabel="PLACEHOLDER"];
A:w -> A:w[label=" rdt_rcv(rcvpkt) \n ᐱ"];
B:n -> B:n[label=" rdt_rcv(rcvpkt) \n && corrupt(rcvpkt) \n || isAck(rcvpkt,1) \n ᐱ "];
B:e -> B:e[label=" timeout \n udt_send(sndpkt) \n start_timer \n "];
E:e -> E:e[label=" rdt_rcv(rcvpkt)\nᐱ "];
F:s -> F:s[label=" rdt_rcv(rcvpkt) \n && corrupt(rcvpkt) \n || isAck(rcvpkt,0) \n ᐱ "];
F:w -> F:w[label=" timeout \n udt_send(sndpkt) \n start_timer "];
{rank=same;A;B}
{rank=same;C,D,G,H}
{rank=same;E;F}
}
然后我使用命令
dot -Tsvg in.dot -o out.svg
这会生成以下图表
请注意四个中间节点上的不同环回边缘及其标签位置。即使我增加了 nodeep 属性,边缘也似乎被拉伸了。我如何有效地解决这个问题?
解决方案
令人惊讶的是,增加nodeep也会增加循环大小。
下面减少了nodeep,添加了一个不可见的节点(和 2 条边),并为(一些)边标签添加了一些空格。
digraph g{
rankdir=TB;
forcelabels=true;
ranksep=1.5;
pad=0.5;
nodesep=1; // was 2
node[shape=circle];
A[label="Wait for call\n0 from above"];
B[label="Wait for\nACK 0 || ACK 1"];
E[label="Wait for call\n1 from above"];
F[label="Wait for\nACk 2 || ACK 3"];
C[label="Wait for ACK 0"];
D[label="Wait for ACK 1"];
G[label="Wait for ACK 2"];
H[label="Wait for ACk 3"];
A -> B[label=" rdt_send(data) \n sndpkt=make_pkt(0,data,checksum) \n udt_send(sndpkt) \n start_timer 1 and 2 \n"];
B -> D[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,0) \n stop_timer 1"];
B -> C[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,1) \n stop_timer 2"];
C -> E[xlabel=" rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,0) \n stop_timer 2"];
D -> E[label= " rdt_rcv(rcvpkt) && \n notcorrupt(rcvpkt) \n && isAck(rcvpkt,1) \n stop_timer 1"];
C:nw -> C:nw[constraint=none,xlabel="1PLACEHOLDER"];
C:sw -> C:sw[constraint=none,xlabel="2PLACEHOLDER "]; // spaces
D:ne -> D:ne[constraint=none,xlabel=" 3PLACEHOLDER"]; // spaces
D:se -> D:se[constraint=none,xlabel="4PLACEHOLDER"];
E -> F[constraint=none, xlabel=" \n rdt_send(data) \n sndpkt=make_pkt(1,data,checksum) \n udt_send(sndpkt)\n start_timer "];
F -> G[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,3) \n stop_timer "];
F -> H[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,2) \n stop_timer "];
G -> A[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,3) \n stop_timer "];
H -> A[xlabel=" rdt_rcv(rcvpkt) \n && notcorrupt(rcvpkt) \n && isAck(rcvpkt,2) \n stop_timer "];
G:sw -> G:sw[constraint=none,xlabel="5PLACEHOLDER"];
G:nw -> G:nw[constraint=none,xlabel="6PLACEHOLDER"];
H:se -> H:se[constraint=none,xlabel=" 7PLACEHOLDER"]; // spaces
H:ne -> H:ne[constraint=none,xlabel="8PLACEHOLDER"];
A:w -> A:w[label=" rdt_rcv(rcvpkt) \n ᐱ"];
B:n -> B:n[label=" rdt_rcv(rcvpkt) \n && corrupt(rcvpkt) \n || isAck(rcvpkt,1) \n ᐱ "];
B:e -> B:e[label=" timeout \n udt_send(sndpkt) \n start_timer \n "];
E:e -> E:e[label=" rdt_rcv(rcvpkt)\nᐱ "];
F:s -> F:s[label=" rdt_rcv(rcvpkt) \n && corrupt(rcvpkt) \n || isAck(rcvpkt,0) \n ᐱ "];
F:w -> F:w[label=" timeout \n udt_send(sndpkt) \n start_timer "];
{rank=same;A;B}
{rank=same;C,D,G,H BOGUS[style=invis]}
{rank=same;E;F}
edge [style=invis]
H -> BOGUS -> C
}
推荐阅读
- visual-studio-code - VSC 缺少调试和任务菜单
- angular - Angular 6 动画在 IE 中不起作用
- git - 从 master 创建新分支而不检查它
- android - 无法解析 BottomNavigationView 中的方法“setShiftingMode(Boolean)”
- bash - 我应该如何正确遍历 gitconfig 别名上的列表?
- c# - 如果返回将在内部,将使用销毁数据
- python - 如何使用 Bokeh 动态隐藏字形和图例项
- amqp - Esper AMQPSource 未收到事件
- gtk3 - 如何摆脱标题栏添加到基本操作系统中的非 gtk 应用程序
- android - aapt2 错误:检查日志以获取详细信息