家庭树布局与Dot/GraphViz

Bio*_*eek 40 dot graphviz genealogy graph-layout family-tree

我试图用Dot和GraphViz绘制一个家谱.

这就是我目前拥有的:

# just graph set-up
digraph simpsons {
ratio = "auto"
mincross = 2.0

# draw some nodes
"Abraham"   [shape=box, regular=1, color="blue"] ;
"Mona"      [shape=box, regular=1, color="pink"] ;
"Clancy"    [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb"      [shape=box, regular=1, color="blue"] ;
"Homer"     [shape=box, regular=1, color="blue"] ;
"Marge"     [shape=box, regular=1, color="pink"] ;
"Patty"     [shape=box, regular=1, color="pink"] ;
"Selma"     [shape=box, regular=1, color="pink"] ;
"Bart"      [shape=box, regular=1, color="blue"] ;
"Lisa"      [shape=box, regular=1, color="pink"] ;
"Maggie"    [shape=box, regular=1, color="pink"] ;
"Ling"      [shape=box, regular=1, color="blue"] ;
# creating tiny nodes w/ no label, no color
"ParentsHomer" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsMarge" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsBart"  [shape=diamond,style=filled,label="",height=.1,width=.1] ;

# draw the edges
"Abraham"      -> "ParentsHomer" [dir=none, weight=1] ;
"Mona"         -> "ParentsHomer" [dir=none, weight=1] ;
"ParentsHomer" -> "Homer"        [dir=none, weight=2] ;
"ParentsHomer" -> "Herb"         [dir=none, weight=2] ;
"Clancy"       -> "ParentsMarge" [dir=none, weight=1] ;
"Jackeline"    -> "ParentsMarge" [dir=none, weight=1] ;
"ParentsMarge" -> "Marge"        [dir=none, weight=2] ;
"ParentsMarge" -> "Patty"        [dir=none, weight=2] ;
"ParentsMarge" -> "Selma"        [dir=none, weight=2] ;
"Homer"        -> "ParentsBart"  [dir=none, weight=1] ;
"Marge"        -> "ParentsBart"  [dir=none, weight=1] ;
"ParentsBart"  -> "Bart"         [dir=none, weight=2] ;
"ParentsBart"  -> "Lisa"         [dir=none, weight=2] ;
"ParentsBart"  -> "Maggie"       [dir=none, weight=2] ;
"Selma"        -> "Ling"         [dir=none, weight=2] ;
}
Run Code Online (Sandbox Code Playgroud)

如果我通过dot(dot simpsons.dot -Tsvg > simpsons.svg)运行,我得到以下布局: 原创,由dot/graphviz制作

然而,我希望边缘更像是"家族树"般的样子:两个已婚人士之间的T型交叉点,T的垂直线再次分叉在倒置的T形交界处,每个人都有一个小的细分孩子们,就像这个模拟一样,在KolourPaint中完成:

我想要实现的目标

我必须使用什么点语法来实现这一点?

gre*_*reg 16

这是另一种解决方案:

digraph simpsons {  
  subgraph Generation0 {
    rank = same
    Abraham [shape = box, color = blue]
    Mona [shape = box, color = pink]
    AbrahamAndMona [shape = point]
    Abraham -> AbrahamAndMona [dir = none]
    AbrahamAndMona -> Mona [dir = none]

    Clancy [shape = box, color = blue]
    Jackeline [shape = box, color = pink]
    ClancyAndJackeline [shape = point]
    Clancy -> ClancyAndJackeline [dir = none]
    ClancyAndJackeline -> Jackeline [dir = none]
  }

  subgraph Generation0Sons {
    rank = same
    AbrahamAndMonaSons [shape = point]
    HerbSon [shape = point]
    HomerSon [shape = point]
    HerbSon -> AbrahamAndMonaSons [dir = none]
    HomerSon -> AbrahamAndMonaSons [dir = none]

    MargeSon [shape = point]
    PattySon [shape = point]
    SelmaSon [shape = point]
    MargeSon -> PattySon [dir = none] 
    PattySon -> SelmaSon [dir = none] 
  }

  AbrahamAndMona -> AbrahamAndMonaSons [dir = none]
  ClancyAndJackeline -> PattySon [dir = none]

  subgraph Generation1 {
    rank  =  same
    Herb [shape = box, color = blue] 
    Homer [shape = box, color = blue] 
    Marge [shape = box, color = pink] 
    Patty [shape = box, color = pink] 
    Selma [shape = box, color = pink] 

    HomerAndMarge [shape = point]
    Homer -> HomerAndMarge [dir = none]
    Marge -> HomerAndMarge [dir = none]
  }

  HerbSon -> Herb [dir = none]
  HomerSon -> Homer [dir = none]
  MargeSon -> Marge [dir = none]
  PattySon -> Patty [dir = none]
  SelmaSon -> Selma [dir = none]

  subgraph Generation1Sons {
    rank  =  same
    BartSon [shape = point] 
    LisaSon [shape = point] 
    MaggieSon [shape = point] 

    BartSon -> LisaSon [dir = none]
    LisaSon -> MaggieSon [dir = none]
  }

  HomerAndMarge -> LisaSon [dir = none]

  subgraph Generation2 {
    rank  =  same
    Bart [shape = box, color = blue] 
    Lisa [shape = box, color = pink] 
    Maggie [shape = box, color = pink] 
    Ling [shape = box, color = blue] 
  }

  Selma -> Ling [dir = none]
  BartSon -> Bart [dir = none]
  LisaSon -> Lisa [dir = none]
  MaggieSon -> Maggie [dir = none]
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

http://dl.dropbox.com/u/72629/simpsons.png

  • 当我在 webgraphviz.com 上渲染它时,它看起来像上面一样棒,但不是在 dreampuf.github.io/GraphvizOnline 上以及在我的机器上本地:/ (3认同)
  • @patryk.beza 使用 `splines=ortho;` 并且不要在名称上添加隐藏节点(如 Herb、Homer、Marge、Selma、Bart 和 Maggie 上的节点)。 (2认同)

小智 11

Gramps(www.gramps-project.org)为家庭树生成点文件,有或没有婚姻节点.还有一种方法可以在Gramps界面中看到这一点.http://gramps-project.org/wiki/index.php?title=Graph_View 所以我想说,看看Gramps创建的家谱输出

  • 这些名称部分很有意义。美国人确实使用这些名称。使用这些的系统旨在与许多不同的文化兼容。请记住,亚洲文化在写名字时将姓氏放在第一位,因此称其为“姓氏”比称其为“姓氏”更有意义。 (3认同)

E L*_*E L 11

我不认为你可以采用一个任意的族树并自动生成一个点文件,它在GraphViz中总是看起来很好.

但我认为你可以总是让你看起来不错:

  • 使用rank =相同的其他答案来获得OP所需的'T'连接
  • 使用Brian Blank做的订购技巧来防止奇怪的线条
  • 假设没有第二次婚姻和半兄弟姐妹
  • 仅绘制符合以下规则的树的子集:
    • 让S成为"中心"人
    • 如果S有兄弟姐妹,请确保S在所有人的右边.
    • 如果S有配偶且配偶有兄弟姐妹,请确保配偶在他/她的兄弟姐妹的左边.
    • 不要向S或S的配偶展示侄子,侄女,阿姨或叔叔
    • 不要显示兄弟姐妹的配偶
    • 不要显示配偶兄弟姐妹的配偶
    • 展示S的孩子,但不是他们的配偶或孩子
    • 显示S的父母和配偶的父母

这将最终显示不超过3代,S在中间一代.

在下面的图片中S = Homer(稍微修改了Brian Blank的版本):

digraph G {
  edge [dir=none];
  node [shape=box];
  graph [splines=ortho];

  "Herb"      [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
  "Homer"     [shape=box, regular=0, color="blue", style="bold, filled" fillcolor="lightblue"] ;
  "Marge"     [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Clancy"    [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
  "Jackeline" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Abraham"   [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
  "Mona"      [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Patty"     [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Selma"     [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Bart"      [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
  "Lisa"      [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
  "Maggie"    [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;

  a1 [shape=diamond,label="",height=0.25,width=0.25];
  b1 [shape=circle,label="",height=0.01,width=0.01];
  b2 [shape=circle,label="",height=0.01,width=0.01];
  b3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Abraham -> a1 -> Mona};
  {rank=same; b1 -> b2 -> b3};
  {rank=same; Herb; Homer};
  a1 -> b2
  b1 -> Herb
  b3 -> Homer

  p1 [shape=diamond,label="",height=0.25,width=0.25];
  q1 [shape=circle,label="",height=0.01,width=0.01];
  q2 [shape=circle,label="",height=0.01,width=0.01];
  q3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Homer -> p1 -> Marge};
  {rank=same; q1 -> q2 -> q3};
  {rank=same; Bart; Lisa; Maggie};
  p1 -> q2;
  q1 -> Bart;
  q2 -> Lisa;
  q3 -> Maggie;

  x1 [shape=diamond,label="",height=0.25,width=0.25];
  y1 [shape=circle,label="",height=0.01,width=0.01];
  y2 [shape=circle,label="",height=0.01,width=0.01];
  y3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Clancy -> x1 -> Jackeline};
  {rank=same; y1 -> y2 -> y3};
  {rank=same; Patty; Selma; Marge};
  x1 -> y2;
  y1 -> Marge;
  y2 -> Patty;
  y3 -> Selma;
}
Run Code Online (Sandbox Code Playgroud)

这将通过GraphViz生成以下树(带有Power Point添加的注释): 在此输入图像描述


小智 5

尽管您无法控制节点的放置,但我发现可以通过以不同顺序对节点进行排序来帮助节点放置。我对一些节点进行了重新排序,如下所示,并得到了一个没有交叉的图。

如下代码:

digraph G {
  edge [dir=none];
  node [shape=box];

  "Herb"      [shape=box, regular=1, color="blue"] ;
  "Homer"     [shape=box, regular=1, color="blue"] ;
  "Marge"     [shape=box, regular=1, color="pink"] ;
  "Clancy"    [shape=box, regular=1, color="blue"] ;
  "Jackeline" [shape=box, regular=1, color="pink"] ;
  "Abraham"   [shape=box, regular=1, color="blue"] ;
  "Mona"      [shape=box, regular=1, color="pink"] ;
  "Patty"     [shape=box, regular=1, color="pink"] ;
  "Selma"     [shape=box, regular=1, color="pink"] ;
  "Bart"      [shape=box, regular=1, color="blue"] ;
  "Lisa"      [shape=box, regular=1, color="pink"] ;
  "Maggie"    [shape=box, regular=1, color="pink"] ;
  "Ling"      [shape=box, regular=1, color="blue"] ;

  a1 [shape=circle,label="",height=0.01,width=0.01];
  b1 [shape=circle,label="",height=0.01,width=0.01];
  b2 [shape=circle,label="",height=0.01,width=0.01];
  b3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Abraham -> a1 -> Mona};
  {rank=same; b1 -> b2 -> b3};
  {rank=same; Herb; Homer};
  a1 -> b2
  b1 -> Herb
  b3 -> Homer

  p1 [shape=circle,label="",height=0.01,width=0.01];
  q1 [shape=circle,label="",height=0.01,width=0.01];
  q2 [shape=circle,label="",height=0.01,width=0.01];
  q3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Homer -> p1 -> Marge};
  {rank=same; q1 -> q2 -> q3};
  {rank=same; Bart; Lisa; Maggie};
  p1 -> q2;
  q1 -> Bart;
  q2 -> Lisa;
  q3 -> Maggie;

  x1 [shape=circle,label="",height=0.01,width=0.01];
  y1 [shape=circle,label="",height=0.01,width=0.01];
  y2 [shape=circle,label="",height=0.01,width=0.01];
  y3 [shape=circle,label="",height=0.01,width=0.01];
  {rank=same; Clancy -> x1 -> Jackeline};
  {rank=same; y1 -> y2 -> y3};
  {rank=same; Marge; Patty; Selma};
  {rank=same; Bart; Ling}
  x1 -> y2;
  y1 -> Marge;
  y2 -> Patty;
  y3 -> Selma;
  Selma -> Ling;
}
Run Code Online (Sandbox Code Playgroud)

现在产生这个:

家谱布局

我不完全了解为什么它起作用,但是这是我所做更改的思考过程。

  1. 我把克兰西/杰克琳放到亚伯拉罕/莫纳之前,以为他们错了。这改变了画面,但仍然不完美。
  2. 我首先把Homer / Marge放在了首位,以为该软件必须首先考虑这些部分,并且可能将所有其他相对于Homer / Marge的节点放在首位。这进一步有所帮助,但仍不完美。
  3. Herb仍然放错了位置,因此我将Herb放在第一位,以便graphviz可以首先考虑放置Herb。

它起作用了,但是我仍然无法设计出一种算法来确保没有重叠边缘的树的一致性。我觉得没有这些提示,graphviz应该做得更好。我不知道使用的算法,但是如果他们考虑使用目标函数来最小化或消除重叠边缘,则应该有可能设计出更好的算法。