Рисование и рендеринг многогранного дерева в Python - PullRequest
11 голосов
/ 11 августа 2011

Кто-нибудь знает, как мне построить многоходовое дерево эстетически правдоподобным способом?информация:

  • более или менее 100 элементов
  • каждый уровень имеет примерно одинаковое количество элементов
  • 10 уровней
  • каждый узел имеет от 0(лист) и 6 дочерних элементов
  • каждый узел указывает свой собственный уровень, независимо от его корней.

В настоящее время я использую PIL, разделяя каждую "строку" на img.size()[0] /количество узлов и рисование линий с draw.line для представления ребер, но оно полностью испорчено

Надеюсь, вы мне поможете =], любую необходимую информацию я опубликую.

1 Ответ

18 голосов
/ 11 августа 2011

Итак, рендеринг графиков - это особый гений graphviz , который также имеет несколько библиотек, которые обеспечивают привязки к Python. На мой взгляд, лучшая из этих библиотек привязок - pygraphviz . Graphviz, вероятно, лучшее решение, а также, вероятно, самое простое.

Конкретный макет, который вы описываете в своем Вопросе, иерархическая многоуровневая схема, выполняется без усилий с помощью graphviz ' dot движок макетов. Dot выполняет рендеринг, чтобы гарантировать, что граф размещен в конфигурации естественного дерева - то есть родительские узлы расположены над их дочерними элементами; узлы одинакового ранга (уровни от корня) располагаются на равной оси w / r / t по оси y, когда это возможно, и естественная симметрия сохраняется, когда это возможно.

(Примечание: смущает, точка относится к одному из нескольких механизмов компоновки, которые включают graphviz , но точка также является именем и расширением файла формат для всех документов графика, независимо от того, как они отображаются).

Как вы можете видеть в следующем коде, используя pygraphviz, просто выбрать dot в качестве механизма разметки для вашего графика, хотя на самом деле это не значение по умолчанию ( neato is) .

Вот краткий график, который я сделал и затем отрисовал, используя dot - создавал и рендерил, используя graphviz через pygraphviz .

Обратите внимание, что график имеет идеальное расположение - узлы одинаковой степени находятся на одном уровне вдоль вертикальной оси, дочерние элементы отображаются ниже родителей, и естественная «симметрия» сохраняется, когда это возможно (например, родительский узел расположен между и выше двух его дочерних узлов. И, как вы можете видеть, ни один из моего кода не управляет макетом вручную - graphviz, то есть dot , обрабатывает его автоматически.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...