2010-02-16 31 views
33

Estoy tratando de dibujar un árbol genealógico con Dot y GraphViz.Diseño del árbol genealógico con Dot/GraphViz

Esto es lo que tengo actualmente:

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

Si funciono a través de este punto (dot simpsons.dot -Tsvg > simpsons.svg), consigo la siguiente distribución: Original, made by dot/graphviz

Sin embargo, me gustaría a los bordes ser más "árbol genealógico" -como una unión en T entre dos personas casadas con la línea vertical de la T ramificándose nuevamente en una unión en T invertida con pequeñas subdivisiones para cada uno de los niños, como esta maqueta, hecha en KolourPaint:

what I would like to achieve

¿Cuál es la sintaxis de punto que tengo que usar para lograr esto?

+11

Usted se olvidó de Hugo entre Bart y Lisa – tur1ng

Respuesta

15

Aquí es una otra solución:

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

Y el resultado:

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

+1

Tu código produce una imagen [ligeramente diferente] (http://oi61.tinypic.com/14smybl.jpg) para mí. ;/ –

+0

@ patryk.beza use 'splines = ortho;' y no agregue los nodos ocultos sobre los nombres (como los de Herb, Homer, Marge, Selma, Bart y Maggie). –

+1

@ patryk.beza http://stackoverflow.com/a/36953206/1312346 –

3

Para hacer esto en graphviz es bastante sencillo; hay un par de patrones de sintaxis que necesita: (i) sintaxis para representar la conexión de línea a línea (la "T" -junction en sus trazados arriba); (ii) sintaxis para aplicar la estructura jerárquica (es decir, nodos de la misma generación en el mismo plano en el eje vertical). Es más fácil show:

digraph G { 
    nodesep=0.6; 
    edge [arrowsize=0.3]; 

    "g1" -> "g2" -> "g3" -> "g4" 

    { rank = same; 
     "g1"; "King"; "ph1"; "Queen"; 
    }; 

    { rank = same; 
     "g2"; "ph2"; "ph2L"; "ph2R"; "ph2LL"; "ph2RR" 
    }; 

    { rank = same; 
     "g3"; "ps1"; "ps2"; "pr1"; "pr2" 
    }; 

    "King" -> "ph1" [arrowsize=0.0]; 
    "ph1" -> "Queen" [arrowsize=0.0]; 

    "ph1" -> "ph2" [arrowsize=0.0]; 
    "ph2LL" -> "ph2L" [arrowsize=0.0]; 
    "ph2L" -> "ph2" [arrowsize=0.0]; 
    "ph2" -> "ph2R" [arrowsize=0.0]; 
    "ph2R" -> "ph2RR" [arrowsize=0.0]; 

    "ph2LL" -> "ps1" [arrowsize=0.0]; 
    "ph2L"-> "pr1" [arrowsize=0.0]; 
    "ph2R" -> "ps2" [arrowsize=0.0]; 
    "ph2RR" -> "pr2" [arrowsize=0.0]; 

} 

El código anterior producirá el siguiente gráfico (i omite el código i utilizado para dar color a los nodos). Dejé visible la "guía" a la izquierda (g1-> g2 ....) solo para mostrar cómo reforcé las posiciones entre nodos de igual rango, probablemente querrás hacerlo invisible en tus propias parcelas. Finalmente, los nodos con las etiquetas que comienzan con 'ph' son los nodos de marcador de posición para las "uniones en T".

alt text http://img525.imageshack.us/img525/352/fmtree2.png

+0

Estoy casi allí, ver mi respuesta a continuación. La única cosa con la que todavía tengo problemas es controlar el orden de colocación en el eje horizontal (quiero que Abraham y Mona estén a la izquierda de Clancy y Jackeline para tener una imagen bien alineada.) ¿Hay alguna manera de hacerlo? – BioGeek

+0

seguro, mira mi código anterior: fíjate en el orden en el que he especificado los bordes (de izquierda a derecha). – doug

+0

Para este ejemplo limitado, esto realmente funciona. Pero en los datos del árbol genealógico de la vida real, todos los niños también tienen socios. Y esos socios siguen saltando el uno sobre el otro. No hay forma de que pueda encontrar para forzar a los maridos a que siempre vayan a la izquierda de sus esposas. Por ejemplo, en http://i.imgur.com/Do7fz.png: Piet debe ir a la izquierda de Inge, Wim (y Jan C, su segundo marido) debe ir a la izquierda de Manu y Jan debe ir a la izquierda de Dominique. – BioGeek

1

casi estoy allí, inspirado por an old response on the graphviz-interest mailinglist y doug's answer.

El siguiente código:

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

    "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"] ; 

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

ahora produce esto:

alt text

Por lo tanto, se ve bien a excepción de que el borde extraña alrededor Homer.If pudiera encontrar una manera de mover Abraham, Mona y Herb en el lado izquierdo de la imagen, entonces tendría una imagen perfectamente alineada.

¿Alguna idea sobre cómo lograr eso?

11

abuelo (www.gramps-project.org) genera archivos punto de árboles genealógicos, con o sin Nodos de matrimonio. También hay una forma de ver esto en la interfaz de Gramps.http://gramps-project.org/wiki/index.php?title=Graph_View así que diría, mira a la salida de su árbol de familia como creado por el abuelo

4

Aunque no se puede controlar la colocación nodo, he encontrado que puede ayudar a la colocación nodo ordenando los nodos en un orden diferente. Rehice algunos de los nodos como se muestra a continuación y obtuve un gráfico que no produjo cruces.

El siguiente código:

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

ahora produce esto:

family tree layout

No entiendo del todo por qué está funcionando, pero aquí es el proceso de pensamiento en los cambios que he realizado .

  1. Coloqué a Clancy/Jackeline antes de que Abraham/Mona pensara que estaban en el lado equivocado. Esto cambió la imagen, pero aún así no fue perfecto.
  2. Puse a Homer/Marge primero pensando que el software tenía que considerar estas piezas primero y tal vez colocar todos los demás nodos relativos a Homer/Marge. Esto ayudó aún más, pero aún así no fue perfecto.
  3. La hierba aún estaba mal colocada, así que puse a Herb primero para que graphviz considere primero la colocación de la hierba.

Funcionó, pero todavía no puedo diseñar un algoritmo que asegure árboles uniformes sin bordes superpuestos. Siento que graphviz debería hacer un mejor trabajo sin estas pistas. No conozco el algoritmo utilizado, pero si consideran una función objetivo para minimizar o eliminar los bordes superpuestos, debería ser posible diseñar un algoritmo mejor.

+1

+1 para mantenernos actualizados! – Potherca

10

No creo que pueda tomar un árbol genealógico arbitrario y generar automáticamente un archivo de puntos donde siempre se vea bien en GraphViz.

Pero creo que puede siempre que se vea bien si:

  • Usar el rango = mismas otras respuestas mencionadas para obtener conexiones de la 'T' deseado por el OP
  • uso del ordenamiento truco Brian Blank hizo para evitar que las líneas extrañas
  • no asumen ninguna segundos matrimonios y medio hermanos
  • Empató sólo un subconjunto del árbol que obedece a las siguientes reglas:
    • Sea S el “centro” persona
    • Si S tiene hermanos, asegúrese de que S es a la derecha de todos ellos.
    • Si S tiene un cónyuge y el cónyuge tiene hermanos, asegúrese de que el cónyuge esté a la izquierda de todos sus hermanos.
    • No mostrar sobrinos, sobrinas, tías o tíos de S o el cónyuge del S
    • No mostrar cónyuges de los hermanos
    • No mostrar cónyuges de los hermanos del cónyuge
    • Mostrar hijos de S, pero no sus cónyuges o hijos
    • mostrar a los padres de S y padres del cónyuge

Esto va a terminar mostrando no más de 3 generaciones a la vez, la S en el medio ge neracion

En la imagen de abajo S = Homer (ligeramente modificada de la versión de Brian en blanco):

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

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

Esto produce el siguiente árbol por GraphViz (con anotaciones que he ido añadiendo con Power Point): enter image description here

Cuestiones relacionadas