I'm using Graphviz (namely Dot) to draw up a state machine for a Hypermedia API I'm planning on building. In my graph, nodes represent states, while edges represent links. What I'm trying to do is have edges (links) of the same "type" (ie, use the same verb or same rel) to share attributes like color
.
I know you can define "global" attributes that apply to all nodes/edges, but I need something I can apply more generally to several different "types". The closest analogy I can come up with for what I want is HTML classes. I don't need multiple "classes" for my edges (although that would be nice) but repeating attributes like color=red, style=bold
is cumbersome.
Is there a way in Dot to declare something like this? Or at least some way I don't have to repeat myself so often?
I've done this in two different ways:
Option (A): Write the dot
file from another script. This is particularly useful when I'm using a script (in, say, Python or Perl) to rework the input data into dot
format for drawing. In that case, as well as having the Python script write the data into dot
format I can also have it write the attributes for each node and edge into the dot
file. An example is shown below (not runnable because I've extracted it from a larger script that interprets the input data but you can see how the Perl is writing the dot
code).
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";
Option (B): If I'm writing the dot
script by hand, I'll use a macro processor to define common elements. For example given the file polygon.dot.m4
containing the m4
macro define()
as follows:
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];
}
... the command m4 <polygon.dot.m4 | dot -Tjpg -opolygon.jpg
produces:
Changing the definitions of SHAPE1 and SHAPE2 at the top of the file will change the shapes drawn for each of the relevant nodes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With