【问题标题】:Graphviz Dot - Strange edge routing and node placementGraphviz Dot - 奇怪的边缘路由和节点放置
【发布时间】:2014-06-01 13:34:06
【问题描述】:

我是 Graphviz/Dot 的新手,并尝试创建我的第一个点图。 基础知识进行得非常快,但修复布局花了我很多时间,我想我现在已经浪费了足够的时间,最好向更有经验的人寻求帮助......

这是关于边缘的路由,我已经尝试通过告诉在节点处定位边缘的位置来修复它,如下所述:Strange edge placement in Graphviz Dot 这行得通,但路由是同样奇怪的东西(在所有内容中应该向右而不是向左)。

第二个是左边三个底部节点的节点放置。这可以更好地放置,以便图表完美适合肖像 A4 页面...

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]
    }
}

}

【问题讨论】:

    标签: graphviz dot


    【解决方案1】:

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

    但是,我会推荐一个不同的课程,使用更少的限制。如果您的图形具有自然流动,那就是描述节点和边的顺序。这应该最大限度地减少添加 constraint=false 属性的需要。例如,您显然希望 Success2 和 Success1 在底部,因此不应在图表顶部提及它们。如果将“PowerUp”节点视为根节点,则其余边和节点应按 DFS 顺序出现。此外,如果节点 A 出现在节点 B 之前,并且它们处于同一等级,则节点 A 很可能位于节点 B 的左侧。因此,我将列出“等待\”输入引导加载程序\”请求" -> "等待\"输入引导加载程序\" 请求之前的"启动固件" -> "输入引导加载程序"。基本上,只需按自然的自上而下的顺序描述图形,避免添加结构约束,除非确实需要得到你想要的。

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

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

    无论如何,here 是我将如何重构您的图形文件并给出结果
    (来源:graphviz.org
    .

    【讨论】:

    • 嘿,我现在设法让它几乎完全符合我的要求...... :D 非常感谢您提供定义顺序的提示,我不知道这真的很重要。 .. 非常感谢您的 xlabel 提示!这有时帮助我获得了更好的布局。最后,要正确使用左侧的“成功”,我必须“向后”(idle->success->istarget)并使用 dir=back。不幸的是,atm 我不能在 graphviz 论坛上发帖,在这里我不能发布点代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2019-06-07
    • 2012-09-05
    • 2017-12-19
    相关资源
    最近更新 更多