Graphviz Dot - 奇怪的边缘路由和节点放置

时间:2014-06-01 13:34:06

标签: graphviz dot

我是Graphviz / Dot的新手,并尝试创建我的第一个Dot-Diagram。 基础知识非常快,但修复布局花了我很多时间,我觉得我现在已经失去了足够的时间,更好地向更有经验的人寻求帮助......

关于边缘的路由,我已经尝试通过告诉如何在节点处找到边缘来解决这个问题:Strange edge placement in Graphviz Dot 这有效,但路由是同样奇怪的事情(应该是正确而不是通过所有内容)。

第二个是左边三个底部节点的节点放置。这可以放得更好,以便图表在Portrait A4页面上完美匹配......

State Diagram

digraph {
"PassSlave1" [label="Pass command to slave (2nd tier)"]
"PassSlave2" [label="Pass command to slave (2nd tier)"]
"Success1" [label="CMD_SIGNAL_SUCCESS", shape=box]
"Success2" [label="CMD_SIGNAL_SUCCESS", shape=box]
"PowerUp" [label="Power up / System reset", peripheries=2, color="red", fontcolor="red"]
"Acknowledge1" [label="CMD_SIGNAL_ACKNOWLEDGE", shape=box]
"Acknowledge2" [label="CMD_SIGNAL_ACKNOWLEDGE", shape=box]

subgraph bl {
    "PowerUp" -> "Wait for \"Enter bootloader\" request"

    "Wait for \"Enter bootloader\" request" -> "Enter bootloader" [label="\"Enter bootloader\" request received"]
    "Wait for \"Enter bootloader\" request" -> "Start Firmware" [label="Timeout while awaiting \"Enter bootloader\" request"]

    "Enter bootloader" -> "idle" // [constraint=false]
    "idle" -> "idle" [label="No command received"]
    "idle" -> "Check device ID" [label="SET_BOOTLOAD_TARGET (Device ID) received"]
}
subgraph {
    rankdir=LR

    subgraph match {
        "Check device ID" -> "Acknowledge1" [label="Match"]
        "Acknowledge1" -> "isTarget (flash mode)"
        "isTarget (flash mode)" -> "Acknowledge2" [label="CMD_START_DOWNLOAD (Byte count) received"]

            "Acknowledge2" -> "isTarget (flash mode)"
            "isTarget (flash mode)" -> "isTarget (flash mode)" [label="No data / commands received"]
            "isTarget (flash mode)" -> "Process data (Hex records)" [label="Data received"]
            "Process data (Hex records)" -> "isTarget (flash mode)" [constraint=false]
            "isTarget (flash mode)" -> "Success1" [label="CMD_END_DOWNLOAD received"]
            "Success1" -> "idle" [constraint=false]

            //"Process data (Hex records)" -> "isTarget (flash mode)" [label="No error occured"]
            //"Process data (Hex records)" -> "isTarget (flash mode)" [label="Error occured"]
    }

    subgraph mismatch {
        "Check device ID" -> "Pass command to slaves (2nd tier)" [label="Mismatch"]
        "Pass command to slaves (2nd tier)" -> "awaitingSlaveBootloadTargetAcknowledge"
        "awaitingSlaveBootloadTargetAcknowledge" -> "awaitingSlaveBootloadTargetAcknowledge" [label="No acknowledge received"]
        "awaitingSlaveBootloadTargetAcknowledge" -> "hasTarget" [label="Acknowledge received"]

        "hasTarget" -> "hasTarget" [label="No command received"]
        "hasTarget" -> "PassSlave1" [label="CMD_START_DOWNLOAD (Byte count) received"]
        "PassSlave1" -> "awaitingSlaveStartDownloadAcknowledge"
        "awaitingSlaveStartDownloadAcknowledge" -> "awaitingSlaveStartDownloadAcknowledge" [label="No acknowledge received"]
        "awaitingSlaveStartDownloadAcknowledge" -> "hasDownloadTarget" [label="Acknowledge received"]

        "hasDownloadTarget" -> "hasDownloadTarget" [label="No data / commands received"]
        "hasDownloadTarget" -> "Pass data (Hex records) to slave (2nd tier)" [label="Data received"]
        "Pass data (Hex records) to slave (2nd tier)" -> "hasDownloadTarget"
        //"hasDownloadTarget" -> "awaitingSlaveEndDownloadResponse" [label="CMD_END_DOWNLOAD received"]
        "hasDownloadTarget" -> "PassSlave2" [label="CMD_END_DOWNLOAD received"]
        "PassSlave2" -> "awaitingSlaveEndDownloadResponse"
        "awaitingSlaveEndDownloadResponse" -> "awaitingSlaveEndDownloadResponse" [label="No command received"]
        "awaitingSlaveEndDownloadResponse"  -> "Success2"
        "Success2":e -> "idle":n [constraint=false]
    }
}

}

1 个答案:

答案 0 :(得分:1)

如果边缘放置问题涉及边缘“Success2”:e - > “空闲”:n向左而不是直线向上,原因是dot想要最小化边缘交叉。任何其他路径将导致至少1次交叉,因此当前路径被选为仅有1次交叉。至于3个左下方节点,点算法想要使边缘尽可能短,同时试图尊重边缘方向,因此“最佳”解决方案是将它们并排放置。因此,在给定约束的情况下,dot正在做它应该做的事情。解决第二个问题的一种方法是将minlen = 2添加到边缘“isTarget(flash mode)” - > “Acknowledge2”。

但是,我会建议使用更少的约束来使用不同的课程。如果图形具有自然流,那么应该描述节点和边的顺序。这应该最小化添加constraint = false属性的需要。例如,您显然希望Success2和Success1位于底部,因此不应在图表顶部提及它们。如果将“PowerUp”节点视为根节点,则剩余的边和节点应以DFS顺序出现。此外,如果节点A出现在节点B之前,并且它们处于相同的等级,则节点A可能位于节点B的左侧。因此,我将列出“等待\”输入bootloader \“请求“ - > “等待”之前的“启动固件”输入bootloader \“request” - > “输入bootloader”。基本上,只需按照自然的自上而下的顺序描述图形,并避免添加结构约束,除非真的有必要得到你想要的。

另一个建议涉及边缘标签。边缘标签在虚拟节点处理。这通常很有效,但有时候这种重量级方法会扭曲布局,特别是对于长标签。我会考虑将一些或多个较长边标签更改为xlabels。通过这种方式,它们在基本布局完成后放置。

请注意,rankdir属性在子图中无效。它只影响根图。

无论如何,here是重构图表文件的方式,给出结果result http://www.graphviz.org/Misc/forum/place.png

相关问题