2011-08-11 8 views
9

¿Alguien sabe cómo trazar un árbol de múltiples vías de una manera estéticamente plausible? Info:Dibujando y representando árbol de múltiples vías en Python

  • más o menos 100 elementos
  • cada nivel tienen aproximadamente el mismo número de elementos
  • 10 niveles
  • cada nodo tiene entre 0 (hoja) y 6 childs
  • cada nodo especifica su propio nivel, sin importar sus raíces.

Actualmente estoy usando PIL, dividiendo cada "línea" en img.size()[0]/número de nodos, y el trazado de líneas con draw.line para representar los bordes, pero es completamente desordenado

espero que usted pueda help me =], cualquier información necesaria la publicaré.

Respuesta

15

Por lo tanto, renderizar gráficos es el genio particular de graphviz, que también tiene varias bibliotecas que proporcionan enlaces de python. En mi opinión, la mejor de estas bibliotecas de enlaces es pygraphviz. Graphviz es probablemente la mejor solución y también la más simple.

La disposición particular que usted describe en su pregunta, un esquema de capas jerárquicas, se realiza sin esfuerzo por graphviz' punto motor de diseño. Dot realiza la representación para garantizar que el gráfico se distribuye en una configuración de árbol natural, es decir, los nodos principales se colocan por encima de sus elementos secundarios; los nodos de igual rango (niveles desde la raíz) están equidimensionados con/r/t el eje y siempre que sea posible, y la simetría natural se conserva cuando es posible.

(Nota: confusamente, punto se refiere a uno de los varios motores de diseño que componen graphviz, pero punto es también el nombre y la extensión de archivo del formato de archivo para todos los documentos graphviz independientemente de la forma en que se prestan)

Como se puede ver en mi código que sigue, utilizando pygraphviz, es simple para seleccionar punto como motor de diseño de la gráfica, aunque en realidad no es el valor por defecto (Neato es).

Así es un gráfico rápida hice y luego representa utilizando dot --created y rendido usando graphviz través pygraphviz.

Observe que el gráfico tiene una distribución perfecta: los nodos del mismo grado están en el mismo nivel a lo largo de un eje vertical, los niños se representan debajo de los padres y la 'simetría' natural se conserva cuando es posible (p. entre y encima de sus dos nodos secundarios. Y como puede ver, ninguno de mis códigos controla manualmente el diseño - graphviz, es decir, punto, lo maneja automáticamente.

import pygraphviz as PG 

A = PG.AGraph(directed=True, strict=True) 

A.add_edge("7th Edition", "32V") 
A.add_edge("7th Edition", "Xenix") 
# etc., etc. 

# save the graph in dot format 
A.write('ademo.dot') 

# pygraphviz renders graphs in neato by default, 
# so you need to specify dot as the layout engine 
A.layout(prog='dot') 


# opening the dot file in a text editor shows the graph's syntax: 
digraph unix { 
    size="7,5"; 
    node [color=goldenrod2, style=filled]; 
    "7th Edition" -> "32V"; 
    "7th Edition" -> "V7M"; 
    "7th Edition" -> "Xenix"; 
    "7th Edition" -> "UniPlus+"; 
    "V7M" -> "Ultrix-11"; 
    "8th Edition" -> "9th Edition"; 
    "1 BSD" -> "2 BSD"; 
    "2 BSD" -> "2.8 BSD"; 
    "2.8 BSD" -> "Ultrix-11"; 
    "2.8 BSD" -> "2.9 BSD"; 
    "32V" -> "3 BSD"; 
    "3 BSD" -> "4 BSD"; 
    "4 BSD" -> "4.1 BSD"; 
    "4.1 BSD" -> "4.2 BSD"; 
    "4.1 BSD" -> "2.8 BSD"; 
    "4.1 BSD" -> "8th Edition"; 
    "4.2 BSD" -> "4.3 BSD"; 
    "4.2 BSD" -> "Ultrix-32"; 
} 

enter image description here

+0

simplemente perfecto, sólo tengo para optimizar los diseños, colores de la sangre de Jesús ... gracias. =] – BrainStorm

+0

@doug, ¿podría decirme cómo configuro el nivel del nodo (línea) con un parámetro? solo por estética. – BrainStorm

+0

@BrainStorm: bueno, dot generalmente se ocupa de eso sin ninguna configuración adicional. Forzar esta configuración de nodo - establecer una restricción explícita - no es difícil, pero requiere dos pasos: (i) definir un 'subgráfico' (grupo de nodos en su gráfica para tener la misma posición horizontal); y (ii) en la definición del subgráfico, establezca el atributo 'rango', como este: rank = same. Espacio insuficiente en los comentarios para explicar mejor el subgrafo, pero esta página da un ejemplo directo: http://www.graphviz.org/content/cluster – doug