Family tree layout with Dot/GraphViz

前端 未结 6 1401
慢半拍i
慢半拍i 2020-12-22 17:33

I am trying to draw a family tree with Dot and GraphViz.

This is what I currently have:

# just graph set-up
digraph simpsons {
ratio = \"auto\"
minc         


        
6条回答
  •  天涯浪人
    2020-12-22 17:59

    Although you can't control node placement, I found you can help node placement by ordering the nodes in a different order. I re-ordered some of the nodes as shown below and got a graph that produced no cross-overs.

    The following code:

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

    now produces this:

    family tree layout

    I don't fully understand why it's working, but here is the thought process into the changes that I made.

    1. I placed Clancy/Jackeline before Abraham/Mona thinking that they were on the wrong side. This changed the picture, but still wasn't perfect.
    2. I placed Homer/Marge first thinking that the software had to consider these pieces first and maybe place all other nodes relative to Homer/Marge. This further helped, but still wasn't perfect.
    3. Herb was still mis-placed, so I put Herb first so that graphviz might consider placement of herb first.

    It worked, but I still can't devise an algorithm that would ensure consistent trees with no overlapping edges. I feel that graphviz should do a better job without these hints. I don't know the algorithm used, but if they consider an objective function to minimize or eliminate overlapping edges, it should be possible to devise a better algorithm.

提交回复
热议问题