Есть много типов данных, которые можно и нужно представить наглядно в виде зависимости одного от другого. Это и генеалогическое дерево, и взаимосвязь проектов друг с другом, и многое другое. Это всё можно вручную отрисовывать в Inkscape, а можно последовать UNIX-way и доверить это GraphViz. Немного своих находок и зарубок на память - пример возможностей GraphViz.
Предыстория
В общем, GraphViz это язык управления взаимосвязями - не нужно их чертить руками, их нужно логически описать на языке программирования и доверить работу по вычерчиванию графов GraphViz. В первый раз я начал задумываться об этом тогда, когда мне пришлось построить взаимосвязи меду своими проектами - было подспудное ощущение, что я что-то пропустил и нужно создать ещё проекты.
Сначала я использовал Kmindmap, но его возможности по построению множественных взаимосвязей на разных уровнях очень ограничены. Inkscape это, конечно, ручная работа, что при числе проектов более трёх десятков совсем не весело. И хотелось бы всё это интегрировать с LaTeX... После недолгих скитаний я понял, что изучение GraphViz сулит много хорошего и не так сложен в освоении.
GraphViz вообще пригоден для всего, что только имеет смысл представлять в виде графов - любые процессы, сети и взаимосвязи. В сочетании с любым скриптовым языком это прекрасный инструмент для анализа и визуализации практически любой информации. Граф при визуализации может быть представлен как иерархически (dot), так и по алгоритму минимизации энергии (energy minimized), когда узлы располагаются максимально компактно, насколько это возможно, не нарушая наглядность (neato). В общем, если информацию можно представить в виде направленного или ненаправленного графа, GraphViz с этим легко справится.
Установка и первые шаги с GraphViz
GraphViz есть в каждом уважающем себя дистрибутиве, и ставится пакетной системой на раз:
# aptitude install graphviz
Единственное, что следует отметить, что GraphViz имеет кучу зависимостей, так что его сборку лучше доверить вашим дистростроителям.
Но допустим, что вы его успешно собрали или просто поставили из пакетного менеджера своего дистрибутива - что дальше? А дальше делаем быстрый старт: открываем свой любимый текстовый редактор и вставляем в него например вот это:
digraph G{
Рождение->Юность->Зрелость->Старость->Смерть;
Юность->Смерть;
Зрелость->Смерть;
}
И сохраняем в виде текстового файла, например temp.dot. Далее в консоли пишем
$ dot -Tpng temp.dot -o temp.png
То есть перегоняем наш граф в формат PNG, чтобы можно было просмотреть его, скажем, с помощью gqview или любым другим просмотрщиком изображений. И вот что мы увидим:
Начальную идею это должно передать, а за подробностями милости просим в это совершенно исключительное по художественной силе описание GraphViz. А я тем временем поделюсь своими заметками.
Небольшой пример
В этом примере я сгруппировал наиболее часто мной используемые находки в GraphViz, такие как уровни в графе, размер текста и форму элементов. Дабы минимизировать проблемы с кириллицей, стоит сохранять данные в кодировке UTF8.
Предварительные обозначения
Сначала эти уровни обозначаем (в данном случае это от 50.000 до 10.000 - читавшие GTD меня поймут, не читавшие могут узнать об этом больше).
{ //Уровни в проектах
node[shape=plaintext]; // чтобы было не видно рамок
edge[color=white]; // чтобы было не видно рамок
50.000->40.000->30.000->20.000->10.000->5.000;
}
Последовательность символов -> означает связь двух объектов, shape - форму объекта (рамка вокруг текста), color - соответственно цвет (здесь белый - чтобы не было видно рамки вокруг текста).
После этого группируем данные и даём понять GraphViz, что группа принадлежит к этому уровню:
{ // <============= Задачи на уровне 10.000 ==============
node[shape=rectangle,fontsize=10]; // порядок важен: описание свойств узлов должно идти раньше, чем сами узлы
rank=same; 10.000; "Диссертация";
"Проект РНП";
"Time-Frequency";
}
Здесь задаём размер текста fontsize поменьше (из эстетических соображений) и говорим GraphViz, что эти куски текста должны быть на высоте 10.000 (определённый уровень).
Теперь выстраиваем взаимосвязи объектов друг с другом:
"Time-Frequency"-> "Научные\nпроекты";
"Диссертация"-> "Научные\nпроекты";
"Проект РНП"-> "Научные\nпроекты";
"Диссертация"->"Time-Frequency"[dir=both]; // зависимость направлена в обе стороны
"Диссертация"->"Проект РНП"[dir=both]; // зависимость направлена в обе стороны
Тут две тонкости:
- чтобы текст в рамке разбить на несколько строк, ставим \n
- если нужно, чтобы стрелка была направлена в обе стороны - взаимная зависимость двух объектов - нужно рядом с зависимостью приписать [dir=both];
После этого можно собирать проект и перегонять его в любой удобный формат: PNG удобнее всего смотреть в просмотрщике, пока выстраивается структура, а потом перегнать это всё в SVG для печати или встраивания куда-нибудь.
А теперь всё вместе
Как только выставленные связи вас устроили и вы хотите посмотреть, что получилось - собираем проект и припадаем к просмотрщику, любуясь результатами своей деятельности. Вот полный код примера:
digraph WorkAnalysis{
rankdir=TB; //как делается граф - сверху вниз.
{ //Уровни в проектах
node[shape=plaintext]; // чтобы было не видно рамок
edge[color=white]; // чтобы было не видно рамок
50.000->40.000->30.000->20.000->10.000;
}
{ // <============= Задачи на уровне 40.000 ============== node[shape=pentagon,fontsize=30]; rank=same; 40.000; "Исследования\nсигналов"; } { // <============= Задачи на уровне 20.000: Сфера ответственности node[shape=egg,fontsize=20]; rank=same; 20.000; "Научные\nпроекты"; } { // <============= Задачи на уровне 10.000 ============== node[shape=rectangle,fontsize=10]; rank=same; 10.000; "Диссертация"; "Проект РНП"; "Time-Frequency"; } "Time-Frequency"-> "Научные\nпроекты";
"Диссертация"-> "Научные\nпроекты";
"Проект РНП"-> "Научные\nпроекты";
"Диссертация"->"Time-Frequency"[dir=both]; // зависимость направлена в обе стороны
"Диссертация"->"Проект РНП"[dir=both]; // зависимость направлена в обе стороны
}
Вставляем его в файл a.dot и набираем:
dot -Tpng a.dot -o a.png
Видим что-то вроде этого:

Собственно, этот пример я состряпал на основе своего графа проектов, и этот код - только часть. Приведённый пример должен проиллюстрировать основные моменты работы с GraphViz, которые я часто забываю :-)
читать далее >>