summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/metapost/automata
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2007-07-16 16:30:43 +0000
committerKarl Berry <karl@freefriends.org>2007-07-16 16:30:43 +0000
commita139ebaf3bcef1c8ad4177ead9ac6ed426f6b6e0 (patch)
tree956ca4f0b861b9d488a3d17375953394cab420ec /Master/texmf-dist/metapost/automata
parentf3105f85f6529b65da9843627709258f82d384fa (diff)
new metapost package automata 0.1 (4jul07)
git-svn-id: svn://tug.org/texlive/trunk@4617 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/metapost/automata')
-rw-r--r--Master/texmf-dist/metapost/automata/automata.mp700
1 files changed, 700 insertions, 0 deletions
diff --git a/Master/texmf-dist/metapost/automata/automata.mp b/Master/texmf-dist/metapost/automata/automata.mp
new file mode 100644
index 00000000000..35ed9e6ae73
--- /dev/null
+++ b/Master/texmf-dist/metapost/automata/automata.mp
@@ -0,0 +1,700 @@
+% PACKAGE FOR METAPOST TO DRAW FINITE STATE MACHINES, GRAPHS, TREES, ETC.
+% Version 0.2
+% Author: gabriele puppis
+
+% declares a grid of equally-spaced nodes
+%
+% syntax: matrix.<name>(<#rows>,<#cols>);
+%
+% example: matrix.a(2,3);
+%
+% parameters: spacing = (60,30) | ...
+% offset = (0,0) | ...
+% numbering = (0,0) | ...
+%
+% (nodes are identified by <name>[<row>][<col>],
+% <name> can't be c,h,x,y or any other global variable,
+% the center/anchor of a node is <name>[<row>][<col>].c/.h,
+% <row> and <col> start from 0,
+% so <name>[0][0] is the top left-most node,
+% <name>[<#rows>-1][<#cols>-1] is the bottom right-most node)
+vardef matrix@# expr d =
+ pair @#[][].c;
+ pair @#[][].h;
+ pair @#[][].s;
+ path @#[][].f;
+ numeric @#[][].m;
+
+ for i=0 upto xpart(d)-1:
+ for j=0 upto ypart(d)-1:
+ @#[xpart(numbering)+i][ypart(numbering)+j].c :=
+ (xpart(spacing)*j,-ypart(spacing)*i) shifted offset;
+ endfor;
+ endfor;
+enddef;
+
+
+% declares a tree-shaped arrangement of nodes
+%
+% syntax: tree.<name>(<#levels>,<arity>);
+%
+% example: tree.a(4,2);
+%
+% parameters: spacing = (60,30) | ...
+% offset = (0,0) | ...
+% numbering = (0,0) | ...
+%
+% (nodes are identified by <name>[<depth>][<child>],
+% <name> can't be c,h,x,y or any other global variable,
+% the center/anchor of a node is <name>[<depth>][<child>].c/.h,
+% <depth> and <child> start from 0,
+% so <name>[0][0] is the root,
+% <name>[1][0] ... <name>[1][<arity>-1] are the children of the root,
+% and so on)
+vardef tree@# expr d =
+ pair @#[][].c;
+ pair @#[][].h;
+ pair @#[][].s;
+ path @#[][].f;
+ numeric @#[][].m;
+
+ for i=0 upto xpart(d)-1:
+ for j=0 upto (ypart(d)**i) - 1:
+ @#[xpart(numbering)+i][ypart(numbering)+j].c =
+ (xpart(spacing) * ((j+0.5)*(ypart(d)**(xpart(d)-i)) - 0.5*(ypart(d)**xpart(d))),
+ -ypart(spacing) * i) shifted offset;
+ endfor;
+ endfor;
+enddef;
+
+
+% declares a single node
+%
+% syntax: put.<name>(x,y);
+%
+% example: put.a(100,100);
+%
+% (the center/anchor of a node is <name>.c/.h,
+% <name> can't be c,h,x,y or any other global variable)
+vardef put@# expr p =
+ pair @#.c;
+ pair @#.h;
+ pair @#.s;
+ path @#.f;
+ numeric @#.m;
+
+ @#.c := p;
+enddef;
+
+
+% declares an additional single node inside an existing matrix or tree
+% (or change the position of an existing node)
+%
+% syntax: setpos.<name>[<row>][<col>](x,y);
+%
+% example: setpos.a[0][0](100,100);
+%
+% (the center/anchor of a node is <name>[<row>][<col>].c/.h)
+vardef setpos@# expr p =
+ @#.c := p;
+enddef;
+
+
+% change the position of an existing node
+%
+% syntax: movepos.<name>(x,y);
+%
+% example: movepos.a(100,100);
+% movepos.b[0][0](100,100);
+vardef movepos@# expr p =
+ @#.c := @#.c shifted p;
+ @#.h := @#.h shifted p;
+enddef;
+
+
+% draws an existing node
+%
+% syntax: node.<node> <label>;
+%
+% example: node.a[0][0] btex $\alpha$ etex;
+%
+% parameters: size = 7 | ...
+% nodemargin = 1.5 | ...
+% shape = circle | utriangle | ltriangle | btriangle | rtriangle |
+% box | fixedbox | rbox | rfixedbox | none
+% boxmargin = 5 | ...
+% fixedboxwidth = 7 | ...
+% fixedboxheight = 7 | ...
+% border = solid | bold | dash | double | none
+% bordercolor = black | white | ...
+% filling = none | solid | left | right
+% fillingcolor = black | white | ...
+% nodelabel = yes | no
+% nodelabelcolor = black | white | ...
+% solidsize = 0.9 | ...
+% boldsize = 1.5 | ...
+% dashsize = 0.75 | ...
+% doublesize = 0.75 | ...
+vardef node@#(expr l) =
+ save pic,fs,fm;
+ picture pic; pic := thelabel(l, (0,0));
+ pair fs;
+ numeric fm;
+
+ if (shape=circle):
+ @#.s := (size,size);
+ @#.f := circlepath;
+ @#.h := @#.c;
+ fs := (size,size);
+ fm := 0;
+ elseif (shape=utriangle):
+ @#.s := (size+solidsize,size+solidsize);
+ @#.f := utrianglepath;
+ @#.h := @#.c shifted (0,0.5ypart(@#.s));
+ fs = (size,size);
+ fm := 4solidsize;
+ elseif (shape=ltriangle):
+ @#.s := (size+solidsize,size+solidsize);
+ @#.f := ltrianglepath;
+ @#.h := @#.c shifted (-0.5xpart(@#.s),0);
+ fs = (size,size);
+ fm := 4solidsize;
+ elseif (shape=btriangle):
+ @#.s := (size+solidsize,size+solidsize);
+ @#.f := btrianglepath;
+ @#.h := @#.c shifted (0,-0.5ypart(@#.s));
+ fs = (size,size);
+ fm := 4solidsize;
+ elseif (shape=rtriangle):
+ @#.s := (size+solidsize,size+solidsize);
+ @#.f := rtrianglepath;
+ @#.h := @#.c shifted (0.5xpart(@#.s),0);
+ fs := (size,size);
+ fm := 4solidsize;
+ elseif (shape=box):
+ @#.s := urcorner pic - llcorner pic + (boxmargin,boxmargin);
+ @#.f := squarepath;
+ @#.h := @#.c;
+ fs := @#.s;
+ fm := 0;
+ elseif (shape=fixedbox):
+ @#.s := (fixedboxwidth,fixedboxheight);
+ @#.f := squarepath;
+ @#.h := @#.c;
+ fs := @#.s;
+ fm := 0;
+ elseif (shape=rbox):
+ @#.s := urcorner pic - llcorner pic;
+ @#.f := rrectangle(xpart(@#.s),ypart(@#.s));
+ @#.h := @#.c;
+ fs := @#.s;
+ fm := 0;
+ elseif (shape=rfixedbox):
+ @#.s := (fixedboxwidth,fixedboxheight);
+ @#.f := rrectangle(xpart(@#.s),ypart(@#.s));
+ @#.h := @#.c;
+ fs := @#.s;
+ fm := 0;
+ elseif (shape=none):
+ @#.s := (0,0);
+ @#.f := (0,0)..(0,0);
+ @#.h := @#.c;
+ @#.m := 0;
+ fs := (0,0);
+ fm := 0;
+ else:
+ errmessage("Node shape not defined");
+ fi
+
+ if (shape<>none):
+
+ if (filling=solid):
+ if (border=double):
+ fill @#.f xscaled (xpart(fs)-2doublesize) yscaled (ypart(fs)-2doublesize)
+ shifted @#.c withcolor fillingcolor;
+ else:
+ fill @#.f xscaled xpart(fs) yscaled ypart(fs)
+ shifted @#.c withcolor fillingcolor;
+ fi
+ elseif (filling=left):
+ if (border=double):
+ fill buildcycle(@#.f,(0,-1)--(0,1))
+ xscaled (xpart(fs)-2doublesize) yscaled (ypart(fs)-2doublesize)
+ shifted @#.c withcolor fillingcolor;
+ else:
+ fill buildcycle(@#.f,(0,-1)--(0,1))
+ xscaled xpart(fs) yscaled ypart(fs)
+ shifted @#.c withcolor fillingcolor;
+ fi
+ elseif (filling=right):
+ if (border=double):
+ fill buildcycle(@#.f,(0,-1)--(0,1)) rotated 180
+ xscaled (xpart(fs)-2doublesize) yscaled (ypart(fs)-2doublesize)
+ shifted @#.c withcolor fillingcolor;
+ else:
+ fill buildcycle(@#.f,(0,-1)--(0,1)) rotated 180
+ xscaled xpart(fs) yscaled ypart(fs)
+ shifted @#.c withcolor fillingcolor;
+ fi
+ fi
+
+ if (border=solid):
+ @#.m := nodemargin * solidsize + fm;
+ draw @#.f xscaled xpart(fs) yscaled ypart(fs) shifted @#.c
+ withpen pencircle scaled solidsize withcolor bordercolor;
+ elseif (border=bold):
+ @#.m := nodemargin * boldsize + fm;
+ draw @#.f xscaled xpart(fs) yscaled ypart(fs) shifted @#.c
+ withpen pencircle scaled boldsize withcolor bordercolor;
+ elseif (border=dash):
+ @#.m := nodemargin * solidsize + fm;
+ draw @#.f xscaled xpart(fs) yscaled ypart(fs) shifted @#.c
+ withpen pencircle scaled solidsize dashed evenly scaled dashsize withcolor bordercolor;
+ elseif (border=double):
+ @#.m := nodemargin * solidsize + fm;
+ draw @#.f xscaled (xpart(fs)-2doublesize) yscaled (ypart(fs)-2doublesize) shifted @#.c
+ withpen pencircle scaled solidsize withcolor bordercolor;
+ draw @#.f xscaled xpart(fs) yscaled ypart(fs) shifted @#.c
+ withpen pencircle scaled solidsize withcolor bordercolor;
+ elseif (border=none):
+ @#.m := nodemargin;
+ else:
+ errmessage("Node border not defined");
+ fi
+
+ fi
+
+ if (nodelabel=yes):
+ if ((urcorner pic - llcorner pic) <> (0,0)):
+ label(l, @#.c) withcolor nodelabelcolor;
+ fi
+ fi
+enddef;
+
+
+% draws an arrow between two nodes and labels it
+%
+% syntax: arrow.<labelpos>(<labeloff>,<label>)(<node>,<node>) <path>;
+% where <labelpos> = lft | rt | top | bot | ulft | urt | llft | lrt
+% <labeloff> is between 0.0 and 1.0
+% <node> is a node
+% <path> is a path
+%
+% example: arrow.top(0.5, btex $a$ etex)(a[0][0],a[0][1]) a[0][0].c{dir90}..a[0][1].c;
+%
+% parameters: style = solid | bold | dash | bolddash
+% arrowcolor = black | white | ...
+% arrowlabel = yes | no
+% unfillonarrowlabel = yes | no
+% arrowlabelcolor = black | white | ...
+% tipangle = 25 | ...;
+% tipsharpness = 10 | ...;
+% tipsize = 4 | ...;
+% arrowmargin = 1.5 | ...
+% solidsize = 0.9 | ...
+% boldsize = 1.5 | ...
+% dashsize = 0.75 | ...
+vardef arrow@#(expr o,l)(suffix a,b) expr p =
+ save cutp;
+ path cutp;
+ if ((style=bold) or (style=bolddash)):
+ cutp := (p) cutbefore (a.f xscaled xpart(a.s) yscaled ypart(a.s) shifted a.c)
+ cutafter (b.f xscaled (xpart(b.s)+b.m+arrowmargin*boldsize)
+ yscaled (ypart(b.s)+b.m+arrowmargin*boldsize) shifted b.c);
+ else:
+ cutp := (p) cutbefore (a.f xscaled xpart(a.s) yscaled ypart(a.s) shifted a.c)
+ cutafter (b.f xscaled (xpart(b.s)+b.m+arrowmargin*solidsize)
+ yscaled (ypart(b.s)+b.m+arrowmargin*solidsize) shifted b.c);
+ fi
+
+ save endpoint,endpointdir,pathtotip,tippoint,tipa,tipb,tip;
+ pair endpoint; endpoint := point length(cutp) of cutp;
+ pair endpointdir; endpointdir := unitvector(direction length(cutp) of cutp);
+ path pathtotip; pathtotip := cutp cutafter (circlepath scaled 2tipsize shifted endpoint);
+ pair tippoint; tippoint := point length(pathtotip) of pathtotip;
+ path tipa; tipa := endpoint{-endpointdir rotated tipsharpness}..
+ (endpoint - ((endpoint-tippoint) rotated tipangle));
+ path tipb; tipb := endpoint{-endpointdir rotated -tipsharpness}..
+ (endpoint - ((endpoint-tippoint) rotated -tipangle));
+ path tip;
+ if ((style=bold) or (style=bolddash)):
+ tip := reverse(tipa)--tipb--cycle;
+ else:
+ tip := tipa--reverse(tipa)--tipb--reverse(tipb)--cycle;
+ fi
+
+ if (style=solid):
+ draw cutp withpen pencircle scaled solidsize withcolor arrowcolor;
+ draw tip withpen pencircle scaled solidsize withcolor arrowcolor;
+ elseif (style=bold):
+ draw cutp withpen pencircle scaled boldsize withcolor arrowcolor;
+ draw tip withpen pencircle scaled boldsize withcolor arrowcolor;
+ elseif (style=dash):
+ draw cutp withpen pencircle scaled solidsize dashed evenly scaled dashsize withcolor arrowcolor;
+ draw tip withpen pencircle scaled solidsize withcolor arrowcolor;
+ elseif (style=bolddash):
+ draw cutp withpen pencircle scaled boldsize dashed evenly scaled dashsize withcolor arrowcolor;
+ draw tip withpen pencircle scaled boldsize withcolor arrowcolor;
+ else:
+ errmessage("Arrow style not defined");
+ fi
+
+ if (arrowlabel=yes):
+ save lab;
+ picture lab;
+ lab := thelabel.@#(l, point o*length(cutp) of cutp);
+ if (unfillonarrowlabel=yes):
+ unfill (bbox lab);
+ fi
+ draw lab withcolor arrowlabelcolor;
+ %label.@#(l, point o*length(cutp) of cutp) withcolor arrowlabelcolor;
+ fi
+enddef;
+
+
+% draws an arrow looping around a node and labels it
+%
+% syntax: loop.<labelpos>(<labeloff>,<label>)(<node>) <dir>;
+% where <labelpos> = lft | rt | top | bot | ulft | urt | llft | lrt
+% <labeloff> is between 0.0 and 1.0
+% <node> is a node
+% <dir> is an angle
+%
+% example: loop.top(0.5, btex $a$ etex)(a[0][0]) 90;
+%
+% parameters: loopsize = 15 | ...
+% looporientation = counterclockwise | clockwise
+% style = solid | bold | dash | bolddash
+% arrowcolor = black | white | ...
+% arrowlabel = yes | no
+% tipangle = 25 | ...;
+% tipsharpness = 10 | ...;
+% tipsize = 4 | ...;
+% arrowmargin = 1.5 | ...
+% boldsize = 1.5 | ...
+% dashsize = 0.75 | ...
+vardef loop@#(expr o,l)(suffix a) expr d =
+ save p;
+ path p;
+ if (looporientation=clockwise):
+ p := (-0.5*loopsize,0)..(0,0.5*loopsize)..(0.5*loopsize,0)..(0,-0.5*loopsize)..cycle;
+ elseif (looporientation=counterclockwise):
+ p := (-0.5*loopsize,0)..(0,-0.5*loopsize)..(0.5*loopsize,0)..(0,0.5*loopsize)..cycle;
+ else:
+ errmessage("Loop orientation not defined");
+ fi
+ arrow.@#(o,l)(a,a) (p shifted (0.6*loopsize,0) rotated d shifted a.c)
+enddef;
+
+
+% draws an arrow reaching a node and labels it
+%
+% syntax: incoming.<labelpos>(<labeloff>,<label>)(<node>) <dir>;
+% where <labelpos> = lft | rt | top | bot | ulft | urt | llft | lrt
+% <labeloff> is between 0.0 and 1.0
+% <node> is a node
+% <dir> is an angle
+%
+% example: incoming.lft(0.5, btex $a$ etex)(a[0][0]) 90;
+%
+% parameters: incominglength = 20 | ...
+% style = solid | bold | dash | bolddash
+% arrowcolor = black | white | ...
+% arrowlabel = yes | no
+% tipangle = 25 | ...;
+% tipsharpness = 10 | ...;
+% tipsize = 4 | ...;
+% arrowmargin = 1 | ...
+% boldsize = 1.5 | ...
+% dashsize = 0.75 | ...
+vardef incoming@#(expr o,l)(suffix a) expr d =
+ save incoming_a;
+ put.incoming_a ((incominglength,0) rotated d shifted a.c);
+ node_marker.incoming_a("");
+
+ arrow.@#(o,l)(incoming_a,a) incoming_a.c--a.c;
+enddef;
+
+
+% draws an arrow departing from a node and labels it
+%
+% syntax: outgoing.<labelpos>(<labeloff>,<label>)(<node>) <dir>;
+% where <labelpos> = lft | rt | top | bot | ulft | urt | llft | lrt
+% <labeloff> is between 0.0 and 1.0
+% <node> is a node
+% <dir> is an angle
+%
+% example: outgoing.lft(0.5, btex $a$ etex)(a[0][0]) 90;
+%
+% parameters: outgoinglength = 20 | ...
+% style = solid | bold | dash | bolddash
+% arrowcolor = black | white | ...
+% arrowlabel = yes | no
+% tipangle = 25 | ...;
+% tipsharpness = 10 | ...;
+% tipsize = 4 | ...;
+% arrowmargin = 1 | ...
+% boldsize = 1.5 | ...
+% dashsize = 0.75 | ...
+vardef outgoing@#(expr o,l)(suffix a) expr d =
+ save outgoing_a;
+ put.outgoing_a ((outgoinglength,0) rotated d shifted a.c);
+ node_marker.outgoing_a("");
+
+ arrow.@#(o,l)(a,outgoing_a) a.c--outgoing_a.c;
+enddef;
+
+
+% shorthand macros
+def node_circle = with shape(circle) node enddef;
+def node_utriangle = with shape(utriangle) node enddef;
+def node_ltriangle = with shape(ltriangle) node enddef;
+def node_dtriangle = with shape(dtriangle) node enddef;
+def node_rtriangle = with shape(rtriangle) node enddef;
+def node_unfilled = with filling(none) node enddef;
+def node_filled = with filling(solid) node enddef;
+def node_filledleft = with filling(left) node enddef;
+def node_filledright = with filling(right) node enddef;
+def node_solid = with border(solid) node enddef;
+def node_bold = with border(bold) node enddef;
+def node_dash = with border(dash) node enddef;
+def node_double = with border(double) node enddef;
+def node_hidden = with border(none) node enddef;
+def node_box = with shape(box) node enddef;
+def node_fixed = with shape(fixedbox) node enddef;
+def node_rbox = with shape(rbox) node enddef;
+def node_rfixed = with shape(rfixedbox) node enddef;
+def node_marker = with shape(none) node enddef;
+def arrow_solid = with style(solid) arrow enddef;
+def arrow_bold = with style(bold) arrow enddef;
+def arrow_dash = with style(dash) arrow enddef;
+def arrow_bolddash = with style(bolddash) arrow enddef;
+def loop_solid = with style(solid) loop enddef;
+def loop_bold = with style(bold) loop enddef;
+def loop_dash = with style(dash) loop enddef;
+def loop_bolddash = with style(bolddash) loop enddef;
+def loop_cw = with looporientation(clockwise) loop enddef;
+def loop_ccw = with looporientation(counterclockwise) loop enddef;
+def incoming_solid = with style(solid) incoming enddef;
+def incoming_bold = with style(bold) incoming enddef;
+def incoming_dash = with style(dash) incoming enddef;
+def incoming_bolddash = with style(bolddash) incoming enddef;
+def outgoing_solid = with style(solid) outgoing enddef;
+def outgoing_bold = with style(bold) outgoing enddef;
+def outgoing_dash = with style(dash) outgoing enddef;
+def outgoing_bolddash = with style(bolddash) outgoing enddef;
+% e.g. with fillingcolor(black) node ...
+vardef with@#(expr v) text e = push.@#; @# := v; e; pop.@# enddef;
+% e.g. light.gray, light.light.gray, ...
+vardef dark@# = 0.5[@#,black] enddef;
+vardef light@# = 0.5[white,@#] enddef;
+def gray = dark.white enddef;
+% e.g. push fillingcolor; fillingcolor := gray; ... pop fillingcolor;
+vardef push@# = @#.back[@#.count] := @#; @#.count := @#.count + 1 enddef;
+vardef pop@# = @#.count := @#.count - 1; @# := @#.back[@#.count] enddef;
+
+
+% default paths
+def circlepath = ((0.5,0)..(0,0.5)..(-0.5,0)..(0,-0.5)..cycle) enddef;
+def trianglepath = ((0.433,-0.25)--(0,0.5)--(-0.433,-0.25)--cycle) enddef;
+def utrianglepath = trianglepath enddef;
+def ltrianglepath = (trianglepath rotated 90) enddef;
+def btrianglepath = (trianglepath rotated 180) enddef;
+def rtrianglepath = (trianglepath rotated 270) enddef;
+def squarepath = ((0.5,-0.5)--(-0.5,-0.5)--(-0.5,0.5)--(0.5,0.5)--cycle) enddef;
+vardef rrectangle(expr w,h) = (((0.5w-0.25h,-0.5h)---(-0.5w+0.25h,-0.5h)..
+ (-0.5w+0.25h,0.5h)---(0.5w-0.25h,0.5h)..cycle)
+ xscaled (1/w) yscaled (1/h)) enddef;
+
+
+% general appearence constants and variables
+def none = 1 enddef;
+def yes = 2 enddef;
+def no = 3 enddef;
+def circle = 10 enddef;
+def utriangle = 11 enddef;
+def ltriangle = 12 enddef;
+def btriangle = 13 enddef;
+def rtriangle = 14 enddef;
+def box = 15 enddef;
+def fixedbox = 16 enddef;
+def rbox = 17 enddef;
+def rfixedbox = 18 enddef;
+def solid = 20 enddef;
+def left = 21 enddef;
+def right = 22 enddef;
+def bold = 30 enddef;
+def dash = 31 enddef;
+def bolddash = 32 enddef;
+def double = 33 enddef;
+def clockwise = 40 enddef;
+def counterclockwise = 41 enddef;
+
+pair spacing;
+pair offset;
+pair numbering;
+numeric size;
+numeric shape;
+numeric boxmargin;
+numeric fixedboxwidth;
+numeric fixedboxheight;
+numeric border;
+numeric filling;
+numeric style;
+numeric nodelabel;
+numeric arrowlabel;
+numeric unfillonarrowlabel;
+numeric tipangle;
+numeric tipsharpness;
+numeric tipsize;
+numeric loopsize;
+numeric looporientation;
+numeric incominglength;
+numeric outgoinglength;
+numeric solidsize;
+numeric boldsize;
+numeric dashsize;
+numeric doublesize;
+numeric nodemargin;
+numeric arrowmargin;
+color bordercolor;
+color fillingcolor;
+color nodelabelcolor;
+color arrowcolor;
+color arrowlabelcolor;
+
+spacing = (60,30);
+offset = (0,0);
+numbering = (0,0);
+size := 5;
+shape := circle;
+boxmargin := 5;
+fixedboxwidth := 7;
+fixedboxheight := 7;
+border := solid;
+filling := none;
+style := solid;
+nodelabel := yes;
+arrowlabel := yes;
+unfillonarrowlabel := no;
+tipangle := 20;
+tipsharpness := 15;
+tipsize := 4;
+loopsize := 14;
+looporientation := counterclockwise;
+incominglength := 20;
+outgoinglength := 20;
+solidsize := 0.7;
+boldsize := 1.5;
+dashsize := 0.7;
+doublesize := 1.3;
+nodemargin := 1.5;
+arrowmargin := 3.8;
+bordercolor = black;
+fillingcolor = black;
+nodelabelcolor = black;
+arrowcolor = black;
+arrowlabelcolor = black;
+linecap := butt;
+linejoin := mitered;
+
+
+% variable stacks
+pair spacing.back[];
+pair offset.back[];
+pair numbering.back[];
+numeric size.back[];
+numeric shape.back[];
+numeric boxmargin.back[];
+numeric fixedboxwidth.back[];
+numeric fixedboxheight.back[];
+numeric border.back[];
+numeric filling.back[];
+numeric style.back[];
+numeric nodelabel.back[];
+numeric arrowlabel.back[];
+numeric unfillonarrowlabel.back[];
+numeric tipangle.back[];
+numeric tipsharpness.back[];
+numeric tipsize.back[];
+numeric loopsize.back[];
+numeric looporientation.back[];
+numeric incominglength.back[];
+numeric outgoinglength.back[];
+numeric solidsize.back[];
+numeric boldsize.back[];
+numeric dashsize.back[];
+numeric doublesize.back[];
+numeric nodemargin.back[];
+numeric arrowmargin.back[];
+color bordercolor.back[];
+color fillingcolor.back[];
+color nodelabelcolor.back[];
+color arrowcolor.back[];
+color arrowlabelcolor.back[];
+
+numeric spacing.count;
+numeric offset.count;
+numeric numbering.count;
+numeric size.count;
+numeric shape.count;
+numeric boxmargin.count;
+numeric fixedboxwidth.count;
+numeric fixedboxheight.count;
+numeric border.count;
+numeric filling.count;
+numeric style.count;
+numeric nodelabel.count;
+numeric arrowlabel.count;
+numeric unfillonarrowlabel.count;
+numeric tipangle.count;
+numeric tipsharpness.count;
+numeric tipsize.count;
+numeric loopsize.count;
+numeric looporientation.count;
+numeric incominglength.count;
+numeric outgoinglength.count;
+numeric solidsize.count;
+numeric boldsize.count;
+numeric dashsize.count;
+numeric doublesize.count;
+numeric nodemargin.count;
+numeric arrowmargin.count;
+numeric bordercolor.count;
+numeric fillingcolor.count;
+numeric nodelabelcolor.count;
+numeric arrowcolor.count;
+numeric arrowlabelcolor.count;
+
+spacing.count := 0;
+offset.count := 0;
+numbering.count := 0;
+size.count := 0;
+shape.count := 0;
+boxmargin.count := 0;
+fixedboxwidth.count := 0;
+fixedboxheight.count := 0;
+border.count := 0;
+filling.count := 0;
+style.count := 0;
+nodelabel.count := 0;
+arrowlabel.count := 0;
+unfillonarrowlabel.count := 0;
+tipangle.count := 0;
+tipsharpness.count := 0;
+tipsize.count := 0;
+loopsize.count := 0;
+looporientation.count := 0;
+incominglength.count := 0;
+outgoinglength.count := 0;
+solidsize.count := 0;
+boldsize.count := 0;
+dashsize.count := 0;
+doublesize.count := 0;
+nodemargin.count := 0;
+arrowmargin.count := 0;
+bordercolor.count := 0;
+fillingcolor.count := 0;
+nodelabelcolor.count := 0;
+arrowcolor.count := 0;
+arrowlabelcolor.count := 0;