2013-04-14 2 views
4

Я использую Graphviz (а именно Dot) для создания конечного автомата API Hypermedia, который я планирую построить. На моем графике узлы представляют состояния, а ребра - ссылки. То, что я пытаюсь сделать, это иметь края (ссылки) одного и того же типа (то есть использовать один и тот же глагол или один и тот же rel) для совместного использования атрибутов, таких как color.Graphviz Sharing Атрибуты между узлами или краями

Я знаю, что вы можете определить «глобальные» атрибуты, которые применяются ко всем узлам/ребрам, но мне нужно что-то, что я могу применить в целом к ​​нескольким различным «типам». Ближайшая аналогия, которую я могу придумать для того, что я хочу, - это классы HTML. Мне не нужны несколько «классов» для моих ребер (хотя это было бы хорошо), но повторяющиеся атрибуты, такие как color=red, style=bold, громоздки.

Есть ли способ в Dot объявить что-то вроде этого? Или, по крайней мере, каким-то образом мне не нужно повторять себя так часто?

ответ

4

Я сделал это двумя различными способами:

Опция (A): Написать dot файл из другого сценария. Это особенно полезно, когда я использую скрипт (например, Python или Perl) для перебора входных данных в формат dot для рисования. В этом случае, а также наличие сценария Python для записи данных в формат dot, я также могу написать ему атрибуты для каждого узла и края в файл dot. Пример показан ниже (не работает, потому что я извлек его из большего скрипта, который интерпретирует входные данные, но вы можете видеть, как Perl пишет код dot).

print "graph G {\n graph [overlap = scale, size = \"10,10\"]; node [fontname = \"Helvetica\", fontsize = 9]\n"; 
for ($j = 0; $j <= $#sectionList; $j++) { 
    print "n$j [label = \"$sectionList[$j]\", style = filled, fillcolor = $groupColour{$group{$sectionList[$j]}} ]\n"; 
    } 
for ($j = 0; $j <= $#sectionList; $j++) { 
    for ($i = $j+1; $i <= $#sectionList; $i++) { 
     $wt = ($collab{$sectionList[$j]}{$sectionList[$i]}+0)/ 
     ($collab{$sectionList[$j]}{$sectionList[$j]}+0); 
     if ($wt > 0.01) { 
     print "n$j -- n$i [weight = $wt, "; 
     if ($wt > 0.15) { 
      print "style = bold]\n"; 
     } 
     elsif ($wt > 0.04) { 
      print "]\n"; 
     } else { 
      print "style = dotted]\n"; 
     } 
     } 
    } 
    print "\n"; 
} 

print "}\n"; 

Опция (B): Если я пишу dot сценарий вручную, я буду использовать макропроцессор для определения общих элементов. Например, учитывая файл polygon.dot.m4, содержащий макрос define() в m4 следующим образом:

define(SHAPE1,square) 
define(SHAPE2,triangle) 

digraph G { 
    a -> b -> c; 
    b -> d; 
    a [shape=SHAPE1]; 
    b [shape=SHAPE2]; 
    d [shape=SHAPE1]; 
    e [shape=SHAPE2]; 
    } 

... команда m4 <polygon.dot.m4 | dot -Tjpg -opolygon.jpg производит: enter image description here

Изменение определения SHAPE1 и shape2 в верхней части файла изменится формы, нарисованные для каждого из соответствующих узлов.

+1

Спасибо, я никогда раньше не использовал M4. Это было легко :) –

+1

Я бы рекомендовал вариант (B). Если вы создаете .dot-файл из Python/Perl и т. Д., Я бы предложил использовать библиотеки шаблонов, а не строить строчку по частям. –