【问题标题】:How to influence layout of graph items?如何影响图形项目的布局?
【发布时间】:2012-07-20 06:43:30
【问题描述】:

我正在尝试使用 Graphviz 可视化一个简单的有限状态机图。 Graphviz 创建的布局并不完全符合我的喜好。我期待一个更紧凑的结果,边缘更短。

到目前为止,我已经尝试过使用组并更改边的权重,但运气不佳。我不清楚为什么 Graphviz 以它的方式绘制图形,以及如何根据我的喜好调整它的算法。我可以设置任何参数来实现这一目标吗?还是应该使用dot 以外的其他命令?我试过neato,但结果看起来完全一团糟,我真的不明白我在做什么......

这是我迄今为止最好的结果:

尝试显示比这更好的布局,我认为如果红色框以不同的方式对齐,图表会看起来更好,更紧凑,例如如图中的箭头所示:

我使用dot创建图表,源代码如下:

  1 digraph JobStateDiagram
  2 {
  3   rankdir=LR;
  4   size="8,5";
  5 
  6   node  [style="rounded,filled,bold", shape=box, fixedsize=true, width=1.3, fontname="Arial"];
  7   Created   [fillcolor=black, shape=circle, label="", width=0.25];
  8   Destroyed [fillcolor=black, shape=doublecircle, label="", width=0.3];
  9   Empty     [fillcolor="#a0ffa0"];
 10   Announced [fillcolor="#a0ffa0"];
 11   Assigned  [fillcolor="#a0ffa0"];
 12   Working   [fillcolor="#a0ffa0"];
 13   Ready     [fillcolor="#a0ffa0"];
 14   TimedOut  [fillcolor="#ffa0a0"];
 15   Failed    [fillcolor="#ffa0a0"];
 16 
 17   {
 18     rank=source; Created Destroyed;
 19   }
 20 
 21   edge  [style=bold, fontname="Arial" weight=2]
 22   Empty     -> Announced [ label="announce"   ];
 23   Announced -> Assigned  [ label="assign"     ];
 24   Assigned  -> Working   [ label="start"      ];
 25   Working   -> Ready     [ label="finish"     ];
 26   Ready     -> Empty     [ label="revoke"     ];
 27 
 28   edge  [fontname="Arial" color="#aaaaaa" weight=1]
 29   Announced -> TimedOut  [ label="timeout"    ];
 30   Assigned  -> TimedOut  [ label="timeout"    ];
 31   Working   -> TimedOut  [ label="timeout"    ];
 32   Working   -> Failed    [ label="error"      ];
 33   TimedOut  -> Announced [ label="announce"   ];
 34   TimedOut  -> Empty     [ label="revoke"     ];
 35   Failed    -> Announced [ label="announce"   ];
 36   Failed    -> Empty     [ label="revoke"     ];
 37 
 38   edge  [style=bold, fontname="Arial" weight=1]
 39   Created   -> Empty     [ label="initialize" ];
 40   Empty     -> Destroyed [ label="finalize"   ];
 41   Announced -> Empty     [ label="revoke"     ];
 42   Assigned  -> Empty     [ label="revoke"     ];
 43   Working   -> Empty     [ label="revoke"     ];
 44 }

另外,如果我在上面的 Graphviz 文件中做了任何奇怪的事情,请让我知道 - 任何反馈都非常感谢。


更新:

更多的实验和尝试一些建议,比如用户marapet给出的端口,增加了我的困惑......例如,在下图中,dot为什么选择为Working->Failed和@987654330画这些奇怪的弯路@,而不是直线?

【问题讨论】:

    标签: graph graphviz


    【解决方案1】:

    对我来说,你的输出看起来不错。 TimedOutFailed 当然一直向右,因为从 Working 到它们有一条边。这就是 dot 最擅长的,虽然您可以进行一些调整来调整 graphviz 布局,但我认为如果您想创建特定的图形布局并控制一切,最好使用其他工具。

    话虽如此,我确实用 graphviz 快速尝试了一下。我更改了一些线以创建一条包含所有绿色节点的直线,并按照您的问题中的指示对齐红色节点。我还添加了边缘集中器 - 结果对我来说看起来并不好:

    digraph JobStateDiagram
    {
      rankdir=LR;
      size="8,5";
      concentrate=true;
    
      node  [style="rounded,filled,bold", shape=box, fixedsize=true, width=1.3, fontname="Arial"];
      Created   [fillcolor=black, shape=circle, label="", width=0.25];
      Destroyed [fillcolor=black, shape=doublecircle, label="", width=0.3];
      Empty     [fillcolor="#a0ffa0"];
      Failed    [fillcolor="#ffa0a0"];
      Announced [fillcolor="#a0ffa0"];
      Assigned  [fillcolor="#a0ffa0"];
      Working   [fillcolor="#a0ffa0"];
      Ready     [fillcolor="#a0ffa0"];
      TimedOut  [fillcolor="#ffa0a0"];
    
      {
        rank=source; Created; Destroyed;
      }
      {
        rank=same;Announced;Failed;
      }
      {
        rank=same;Assigned;TimedOut;
      }
    
      edge  [style=bold, fontname="Arial", weight=100]
      Empty     -> Announced [ label="announce"   ];
      Announced -> Assigned  [ label="assign"     ];
      Assigned  -> Working   [ label="start"      ];
      Working   -> Ready     [ label="finish"     ];
      Ready     -> Empty     [ label="revoke", weight=1     ];
    
      edge  [color="#aaaaaa", weight=1]
      Announced -> TimedOut  [ label="timeout"    ];
      Assigned  -> TimedOut  [ label="timeout"    ];
      Working   -> TimedOut  [ label="timeout"    ];
      Working   -> Failed    [ label="error"      ];
      TimedOut  -> Announced [ label="announce"   ];
      TimedOut  -> Empty     [ label="revoke"     ];
      Failed    -> Announced [ label="announce"   ];
      Failed    -> Empty     [ label="revoke"     ];
    
      Created   -> Empty     [ label="initialize" ];
      Empty     -> Destroyed [ label="finalize"   ];
      Announced -> Empty     [ label="revoke"     ];
      Assigned  -> Empty     [ label="revoke"     ];
      Working   -> Empty     [ label="revoke"     ];
    }
    

    您还可以通过使用端口来控制边缘的开始和结束位置。

    关于你的点文件中奇怪的东西的问题:除了行号(这最终让我可以很好地使用我的文本编辑器的列模式)和对齐,您的文件在我看来很好。我会尽可能地以类似方式构建我的点文件(图形属性、节点列表、分组、边)。请注意,节点首次出现的顺序可能会影响最终布局。

    【讨论】:

    • 感谢您尝试这个并给我更多建议。我已经用一些结果更新了这个问题。我认为这还不是一个完整的解决方案,所以这需要我进行更多的试验才能实现我想要的。
    【解决方案2】:

    虽然这是一个非常古老的问题,但我也遇到了类似的问题,并想分享我的结果。除了“weight”、“rank=same”的技巧,我发现这些方法可以用来调整布局结果:

    • dir=back
    • 添加更多边或节点并设置 style=invis

    当涉及到问题中的这个特定图表时,实际上 rank=same 和 weight 会做主要工作,而 style=invis 可以做一些微调。所以通过添加这些行

     {
      rank=same;Announced;Failed;
     }
     {
      rank=same;Assigned;TimedOut;
     }
    

    到文件中并将weight=1 添加到“准备清空”边缘,并使用一些不可见的边缘来微调我得到的空间:

    完整的图点源:

    digraph JobStateDiagram
    {
      rankdir=LR;
      size="8,5";
    
      node  [style="rounded,filled,bold", shape=box, fixedsize=true, width=1.3, fontname="Arial"];
      Created   [fillcolor=black, shape=circle, label="", width=0.25];
      Destroyed [fillcolor=black, shape=doublecircle, label="", width=0.3];
      Empty     [fillcolor="#a0ffa0"];
      Announced [fillcolor="#a0ffa0"];
      Assigned  [fillcolor="#a0ffa0"];
      Working   [fillcolor="#a0ffa0"];
      Ready     [fillcolor="#a0ffa0"];
      TimedOut  [fillcolor="#ffa0a0"];
      Failed    [fillcolor="#ffa0a0"];
    
      {
        rank=source; Created Destroyed;
      }
      {
        rank=same;Announced;Failed; #change here
      }
      {
        rank=same;Assigned;TimedOut; #change here
      }
    
      edge  [style=bold, fontname="Arial" weight=20] #change here
      Empty     -> Announced [ label="announce"   ];
      Announced -> Assigned  [ label="assign"     ];
      Assigned  -> Working   [ label="start"      ];
      Working   -> Ready     [ label="finish"     ];
      Ready     -> Empty     [ label="revoke" weight=1 ]; #change here
    
      edge  [fontname="Arial" color="#aaaaaa" weight=2] #change here
      Announced -> TimedOut  [ label="timeout"    ];
      Assigned  -> TimedOut  [ label="timeout" weight=1]; #change here
      Working   -> TimedOut  [ label="timeout"    ];
      Working   -> Failed    [ label="error"      ];
      TimedOut  -> Announced [ label="announce"   ];
      TimedOut  -> Empty     [ label="revoke"     ];
      Failed    -> Announced [ label="announce"   ];
      Failed    -> Empty     [ label="revoke"     ];
    
      edge  [style=bold, fontname="Arial" weight=1]
      Created   -> Empty     [ label="initialize" ];
      Empty     -> Destroyed [ label="finalize"   ];
      Announced -> Empty     [ label="revoke"     ];
      Assigned  -> Empty     [ label="revoke"     ];
      Working   -> Empty     [ label="revoke"     ];
      
      Assigned  -> Working   [ label="start"  style=invis     ]; #change here 
      Assigned  -> Working   [ label="start"  style=invis     ]; #change here 
    }
    

    更新:不要将“失败”和“宣布”放在同一等级,将“失败”、“已分配”和“超时”放在同一等级可能会产生更好的结果,如下所示,IMO 更好地说明了相似性和Failed 和 TimedOut 之间的区别。 (您必须移除 invis 边缘才能获得下图)

    【讨论】:

    • 感谢您回答一个老问题。在我看来,你的图表看起来确实是迄今为止最好的。我不明白你的修改是如何实现的。特别是,您能解释一下使用style=invis 包含边的理由吗?
    • style=invis 的边的目的是为了让从 Working 到 TimedOut 的超时边更弯曲,让结果图看起来更好(更对称)。没有它们,结果看起来几乎相同,只是超时边缘是一条直线。正如我所说,这只是一些“微调”。 :)
    猜你喜欢
    • 2019-09-09
    • 2018-08-16
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    相关资源
    最近更新 更多