复杂的graphviz树结构

我试图用graphviz创建一个树结构。 我愿意手工编写graphviz代码或使用ruby-graphviz gem进行ruby。 鉴于以下图片,任何人都可以提供有关必要代码的任何见解吗? 忽略线条不直…它们应该在graphviz构建图形时。 我也愿意在线条交叉时有点/点。

我玩过ruby-graphviz和家谱类…这让我成为了那里的一部分,但我真的需要所有直线和直角相交的线条,开箱即用的代码没有’似乎这样做。

代码应该足够通用,以允许“C”框也有孩子,并且在“A”下也有更多的孩子。

颜色是无关紧要的……例子可以排除任何颜色。

http://docs.google.com/drawings/pub?id=1lUTfgKP_LN0x7C3ItbsFjfLBuDTL84AtmoaW7YFn32Y&w=1036&h=713

据我所知,这需要一些解决方法; 我只会用Graphviz DOT语言来做。 我先给你解决方案,然后提供一些解释,说明如何扩展它。

这是结果图:

outfile.png

这是产生图形的Graphviz代码:

graph atree { Item1 [shape=none,label="Item 1",pos="2.2,1.1!"]; Item2 [shape=none,label="Item 2",pos="2.2,0.1!"]; Item3 [shape=none,label="Item 3",pos="2.9,-0.3!"]; A [shape=box,color=lightblue,style=filled,pos="2,3!"]; B [shape=box,color=lightblue,style=filled,pos="1,2.1!"]; C [shape=box,color=lightblue,style=filled,pos="3,2.1!"]; D [shape=box,color=lightblue,style=filled,pos="1.5,1.5!"]; E [shape=box,color=lightblue,style=filled,pos="1.5,0.5!"]; D0 [style=invisible,fixedsize=true,width=0,height=0,pos="2,2.5!",label=""]; D1 [style=invisible,fixedsize=true,width=0,height=0,pos="1,2.5!",label=""]; D2 [style=invisible,fixedsize=true,width=0,height=0,pos="3,2.5!",label=""]; D3 [style=invisible,fixedsize=true,width=0,height=0,pos="1,1.5!",label=""]; D4 [style=invisible,fixedsize=true,width=0,height=0,pos="1,0.5!",label=""]; D5 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,1.1!",label=""]; D6 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,0.1!",label=""]; D7 [style=invisible,fixedsize=true,width=0,height=0,pos="2.2,-0.3!",label=""]; A -- D0 -- D1 -- B -- D3 -- D4 -- E [color=blue]; E -- D6 -- Item2 -- D7 -- Item3 [color=blue]; D0 -- D2 -- C [color=blue]; D3 -- D -- D5 -- Item1 [color=blue]; } 

如果将其放在名为inputfile.dot文件中,则可以使用命令neato -Tpng inputfile.dot > outfile.png获取生成的图像文件。

现在关于它如何工作的几点评论:使用A, B, C, D, E, Item1, Item2, Item3构建树的代码很简单(属性仅设置颜色和框样式)。 使线条直线和正交的技巧包括:1)向图形添加零大小的不可见节点,以及2)将所有对象定位在canvas上的绝对坐标中。 步骤1)需要辅助节点D1, D2, D3, D4, D5, D6, D7pos="x,y!" 步骤2)需要选项。 注意,你需要的!pos命令结束时签名,否则这些位置不会被认为是最终位置,布局仍会改变。

您可以通过首先定位新节点(通过使用节点A ... Item3的代码作为模板)添加其他节点,添加一个不可见的辅助节点(使用pos使得与其之间的所有连接都是正交的)并且然后通过 -- -- 将连接添加到图形中。

有点晚了,我知道,但我只是想展示另一个版本,而不必弄清楚每个节点的确切位置。

 digraph { splines=false; ranksep=0.05; node[shape=box, color=lightblue, style=filled]; A;B;C;D;E; node[shape=none, color=none, style=solid]; i1[label="Item 1"]; i2[label="Item 2"]; i3[label="Item 3"]; node[label="", width=0, height=0]; edge[arrowhead=none, color=blue]; {rank=same; n2; n1; n3;} n2; n1; n3; A -> n1; n2 -> n1 -> n3; {rank=same; B; C;} n2 -> B; n3 -> C; {rank=same; n4; D;} B -> n4 -> D; {rank=same; n6; n5; i1;} D -> n5 -> i1; n4 -> n6; {rank=same; n7; E;} n6 -> n7 -> E; {rank=same; n8; i2;} E -> n8 -> i2; {rank=same; n9; i3;} i2 -> n9 -> i3; } 

直线强制执行:

  • splines=false – 对样条说不
  • 不可见节点(节点n1,n2,… n9)
  • 将节点放在相同等级上, rank=same

获得正确的点文件仍然是一些工作,但它胜过imho计算每个节点的位置。

输出看起来像这样:

graphviz输出

只要C没有子节点,就必须再应用一些技巧(不可见的节点)来向右显示它。

为了获得不同图形的更通用的解决方案,可能需要进一步调整(对垂直边缘应用权重,或者必须垂直对齐的组节点,或使用子图,……)。

另一个版本使用splines=ortho ,它需要更少的隐藏节点并提供类似的视觉效果。

 digraph example { splines=ortho; ranksep=0.05; node[shape=box, color=lightblue, style=filled]; A;B;C;D;E; node[shape=none, color=none, style=solid]; i1[label="Item 1"]; i2[label="Item 2"]; i3[label="Item 3"]; node[label="", width=0, height=0]; edge[arrowhead=none, color=blue]; n1; n2; n3; n4; n5; {rank=same; B; C;} A -> n1; n1 -> B; n1 -> C; {rank=same; n2; D;} B -> n2; n2 -> D; {rank=same; n3; i1;} D -> n3; n3 -> i1; {rank=same; n4; E;} n2 -> n4; n4 -> E; {rank=same; n5; i2;} E -> n5; n5 -> i2; {rank=same; n6; i3;} i2 -> n6; n6 -> i3; } 

通过PlantUML.com绘制的点图像