% grestore % special commands for setting up tree macros %% version .91 - May 16, 1995 TeXDict begin % the commands needed to get any of this working. The first section % may need to be modified if different dvi to postscript programs are % used. % redefinition of /@beginspec suggested by Gintas Grigelionis % (gintas@theophys.kth.se) 5/95. also dropped bop_hook and texpsmatrix % % /@beginspec {gsave texpsmatrix setmatrix treedict begin} def /@beginspec {gsave Resolution 72 div VResolution -72 div scale treedict begin} def /@endspec {end grestore} def % for landscape Landscape=true, letter Landscape=false % In dvips 5.5 and later, the matrix in landscape was changed from % [0.0 -1.0 1.0 0.0 0.0 0.0] to the current setting of [0.0 1.0 -1.0 % 0.0 0.0 0.0]. If you are using an earlier version, switch back. /treedict 200 dict def treedict begin % num pt num (converts a number in TeX pts (72.27 pts/in) to % postscript pts (72pts/in) /pt {72 mul 72.07 div} def % end of first section % definition of a node as a box containing the following information % The x y location of the lower left hand corner of the box % the height of the box (h) % the width of the box (w) % nodemargin is added to all sides to ensure a boundary around the box % str w h d node - % (nodemargin is defined in the TeX file) /nodemargin 2 def /nodes 100 dict def /node { /dpth exch def /hght exch def /wdth exch def 4 dict dup begin /x /y currentpoint dpth sub nodemargin sub exch 3 1 roll def nodemargin sub def /h hght dpth add nodemargin dup add add def /w wdth nodemargin dup add add def end nodes 3 1 roll put} def % commands to find various locations around the nodebox % % nodetopleft nodetop nodetopright % *--------*--------* % | | % | | % nodeleft * (nodebox) * noderight % | | % | | % *--------*--------* % nodebotleft nodebottom nodebotright % % all of these take % dict nodebottom x1 y1 [dict has x y h w defined] /nodebottom {begin x w 2 div add y end} def /nodetop {begin x w 2 div add y h add end} def /nodeleft {begin x y h 2 div add end} def /noderight {begin x w add y h 2 div add end} def /nodetopleft {begin x y h add end} def /nodetopright {begin x w add y h add end} def /nodebottomleft {begin x y end} def /nodebottomright {begin x w add y end} def % some more locations of use /farright {begin x w add depth add h 2 div y add end} def /farleft {begin x depth sub h 2 div y add end} def /farbottom {begin x w 2 div add y depth sub end} def /fartop {begin x w 2 div add y h add depth add end} def /farbottomleft {begin x depth 45 cos mul sub y depth 45 sin mul sub end} def /farbottomright {begin x w add depth 45 cos mul add y depth 45 sin mul sub end} def /fartopright {begin x w add depth 45 cos mul add y h add depth 45 sin mul add end} def /fartopleft {begin x depth 45 cos mul sub y h add depth 45 sin mul add end} def % connects two nodes with a straight line % add location information (e.g., whether to go from % nodetop to nodeleft ... % nodename1 loc1 nodename2 loc2 nodeconnect - % e.g., a nodetop b nodebottom nodeconnect % to see if straight lines are indeed straight % x1 x2 alignpoint x1' x2' finds out if the two numbers are less than % one pixel apart if so make x1'=x2' /alignpoint {2 copy sub abs 1 le {add 2 div round dup} if} def % nodelocation nodename getnodepoint x y /getnode {nodes exch get} def % xfrom yfrom xto yto nodeconnect - /nodeconnect { gsave transform 4 2 roll transform exch 4 1 roll alignpoint 4 2 roll alignpoint 4 1 roll exch itransform moveto itransform lineto stroke grestore } def % arrowheads % xtail ytail xtip ytip headthickness headlength insetlength arrow - /arrowdict 15 dict def arrowdict begin /mtrx matrix def end /arrow {arrowdict begin /insetlength exch def /headlength exch def /halfheadthickness exch 2 div def /tipy exch def /tipx exch def /taily exch def /tailx exch def /dx tipx tailx sub def /dy tipy taily sub def /angle dy dx atan def /savematrix mtrx currentmatrix def tipx tipy translate angle rotate % following is for arrow 0 0 moveto headlength neg halfheadthickness neg lineto headlength insetlength sub neg 0 lineto headlength neg halfheadthickness lineto closepath fill savematrix setmatrix end } def % does regular filled arrowhead /arrowfill {gsave newpath arrowwidth arrowlength arrowinset arrow grestore} def % draws line for arrow but not arrow head(s) % xtail ytail xtip ytip tailfix tipfix arrowline /arrowline {arrowdict begin gsave newpath /tipfix exch def /tailfix exch def /tipy exch def /tipx exch def /taily exch def /tailx exch def /dx tipx tailx sub def /dy tipy taily sub def /angle dy dx atan def /savematrix mtrx currentmatrix def tipx tipy translate angle rotate tipfix neg 0 moveto savematrix setmatrix /savematrix mtrx currentmatrix def tailx taily translate angle rotate tailfix 0 lineto savematrix setmatrix stroke grestore end} def % xfrom yfrom xto yto testcmd - % arrownodeconnect /arrownodeconnect{ gsave transform 4 2 roll transform exch 4 1 roll alignpoint 4 2 roll alignpoint 4 1 roll exch itransform 4 2 roll itransform % line 4 copy 0 arrowdict begin arrowlength arrowinset sub end arrowline % arrow gsave newpath arrowfill grestore grestore } def /doublearrownodeconnect{ gsave transform 4 2 roll transform exch 4 1 roll alignpoint 4 2 roll alignpoint 4 1 roll exch itransform 4 2 roll itransform % line % 4 copy moveto lineto % stroke 4 copy arrowdict begin arrowlength arrowinset sub end dup arrowline 4 copy % arrow at one end gsave newpath arrowfill grestore % arrow at other end gsave newpath 4 2 roll arrowfill grestore grestore } def % connecting with a bar like % _______________ % | | % or like % _______________ % | | % | node % node % depth fromnode fromloc tonode toloc % depth x1 y1 x2 y2 barnodeconnect - /barnodeconnect {4 2 roll 2 copy moveto 5 -1 roll add dup 3 1 roll lineto 2 index exch lineto lineto stroke } def /arrowbarnodeconnect {4 2 roll 2 copy moveto 5 -1 roll add dup 3 1 roll lineto 2 index exch 4 copy lineto lineto gsave newpath 4 2 roll arrowfill fill grestore stroke } def % Takes two nodes and forms a triangle % node1 % /\ % / \ % ---- % nodess % % fromnodename tonodename nodetriangle - /nodetriangle { gsave exch nodes exch get nodebottom moveto dup nodes exch get nodetopleft lineto nodes exch get nodetopright lineto closepath stroke grestore } def % not sure what I am using the following for % x y x y slope num /slope {/y1 exch def /x1 exch def /y0 exch def /x0 exch def y1 y0 sub x1 x0 sub div } def % x y x y midpoint x y /midpoint {/y1 exch def /x1 exch def /y0 exch def /x0 exch def x1 x0 sub abs x1 x0 ge {x0 add} {x1 add} ifelse y1 y0 sub abs y1 y0 ge {y0 add} {y1 add} ifelse } def % variant of curveto where x1 y1 = x2 y2 /tancurveto {1 index exch curveto} def /nodetancurve {/depth exch def /to exch def /from exch def gsave nodes from get noderight moveto nodes to get noderight tancurveto stroke grestore } def % the node curves draw curves between two points % % this swaps a dictionary around an angle, pulls out depth, & dismisses % the dictionary. % node locname farloc angle depth /getloc {3 -1 roll nodes exch get dup begin depth end 3 1 roll exch cvx exec 4 2 roll} def % nodename rightcur x1 y1 x2 y2 /rightcur {0 /noderight getloc} def /leftcur {180 /nodeleft getloc } def /topcur {90 /nodetop getloc} def /bottomcur {270 /nodebottom getloc} def /topleftcur {135 /nodetopleft getloc} def /toprightcur {45 /nodetopright getloc} def /bottomleftcur {225 /nodebottomleft getloc} def /bottomrightcur {315 /nodebottomright getloc} def % (depth predefined) x1 y1 x2 y2 x3 y3 x4 y4 nodecurve - % where nodename nodeposition produces x1 y1 x2 y2 % where x1 y1 are the endpoint, x2 y2 end-control, etc. % adjustments for arrowheads, etc. /arrowfiddledict 10 dict def % x1 y1 angle depth shift twist arrowfiddle x3 y3 x4 y4 % where x3 y3 are revised endpoint for arrow-headed bezier curves /arrowfiddle {arrowfiddledict begin /twist exch def /shift exch def /shaft exch def /angle exch twist add def /tipy exch def /tipx exch def tipx angle cos shaft mul add tipy angle sin shaft mul add tipx angle cos shift mul add tipy angle sin shift mul add end} def /nodecurve {gsave 0 fromangle arrowfiddle moveto 6 2 roll 0 toangle arrowfiddle curveto stroke grestore} def /arrownodecurve {gsave 0 fromangle arrowfiddle % adjust from angle moveto 6 2 roll 4 copy 10 4 roll % prepare arrowhead material arrowlength arrowinset sub %arrowfiddle param. toangle % ditto arrowfiddle curveto 0 toangle arrowfiddle arrowfill stroke grestore} def /arrow2nodecurve {gsave 4 copy 0 fromangle arrowfiddle arrowfill arrowlength arrowinset sub fromangle arrowfiddle moveto 6 2 roll 4 copy 10 4 roll % prepare arrowhead material arrowlength arrowinset sub %arrowfiddle param. toangle % ditto arrowfiddle curveto 0 toangle arrowfiddle arrowfill stroke grestore} def % commands for doing things along line % blong (predefined) xfrom yfrom xto yto delink - % need to find halfway point /delink { gsave 4 copy newslope 6 2 roll newmidpoint delinkline } def %% calculated (dx dy xmid ymid) now moveto midpoint % moveto dup 0 eq %% duplicate dy and check whether line is horizontal % {blong 2 div neg 0 rmoveto blong 0 rlineto 2 pop} %% line not horizontal so check whether vertical % {exch dup 0 eq % {0 blong 2 div neg rmoveto 0 blong rlineto 2 pop} %% If neither than calculate standard case (dy dx) % {div neg dup dup mul 1 add sqrt % blong exch div % 2 copy mul 2 copy 2 div neg exch 2 div neg exch % rmoveto rlineto 1 pop} ifelse} ifelse % stroke % grestore % } def % actually draws the line % dx dy xmid ymid delinkline - /delinkline { moveto dup 0 eq % duplicate dy and check whether line is horizontal {blong 2 div neg 0 rmoveto blong 0 rlineto 2 pop} % line not horizontal so check whether vertical {exch dup 0 eq {0 blong 2 div neg rmoveto 0 blong rlineto 2 pop} % If neither than calculate standard case (dy dx) {div neg dup dup mul 1 add sqrt blong exch div 2 copy mul 2 copy 2 div neg exch 2 div neg exch rmoveto rlineto 1 pop} ifelse} ifelse stroke grestore } def % % delink curve % blong (predefined) x0 y0 x1 y1 x2 y2 x3 y3 delinkcurve - /delinkcurve { 8 copy 8 copy bezslope 10 2 roll % push to back bezmidpoint delinkline } def % x0 y0 x1 y1 x2 y2 x3 y3 xyarrange x0 x1 x2 x3 y0 y1 y2 y3 % x0 y0 x1 y1 x2 y2 x3 y3 /xyarrange { exch % x0 y0 x1 y1 x2 y2 y3 x3 3 1 roll % x0 y0 x1 y1 x2 x3 y2 y3 5 -1 roll % x0 y0 x1 x2 x3 y2 y3 y1 7 -1 roll % x0 x1 x2 x3 y2 y3 y1 y0 exch % x0 x1 x2 x3 y2 y3 y0 y1 4 2 roll } def % x0 x1 x2 x3 y0 y1 y2 y3 % x0 x1 x2 x3 calcx xn 8(x3+3x2+3x1+x0)=xn /calcx { exch 3 mul 3 -1 roll 3 mul add add add 8 mul} def % x0 x1 x2 x3 calcx xn x3+x2-x1-x0=xn /calcy { add exch sub exch sub } def % x0 y0 x1 y1 x2 y2 x3 y3 bezmidpoint xm ym % using the following equations % xb=8*(x3+3x2+3x1+x0) % yb=8*(y3+3y2+3y1+y0) /bezmidpoint {xyarrange calcx 5 1 roll calcx exch } def % x0 y0 x1 y1 x2 y2 x3 y3 bezslope dx dy % equations are dx=x3+x2-x1-x0 % dy=y3+y2-y1-y0 /bezslope {xyarrange calcy 5 1 roll calcy exch } def % finds midpoint between two points xfrom yfrom xto yto newmidpoint xmid ymid /newmidpoint { exch 4 -1 roll add 2 div 3 1 roll add 2 div } def % finds slope between two points: xfrom yfrom xto yto newslope dx dy /newslope { 4 -1 roll exch 4 1 roll sub 3 1 roll sub exch } def %% commands for drawing things around nodes % nodename nodebox - /nodebox {nodes exch get begin gsave newpath x y moveto h w dobox cleanup stroke grestore end} def % nodename nodecircle - % would be nice to have a parameter that adjusts diameter of circle % depth nodename nodecircle - /nodecircle {nodes exch get begin gsave newpath w 2 div x add h 2 div y add w w mul h h mul add sqrt 2 div 4 -1 roll add 360 0 arcn cleanup stroke grestore end} def % no cleanup /nodecircletrans {nodes exch get begin gsave newpath w 2 div x add h 2 div y add w w mul h h mul add sqrt 2 div 4 -1 roll add 360 0 arcn stroke grestore end} def % nodename nodeoval - /nodeoval {nodes exch get begin gsave newpath x 2 sub y 2 sub moveto h 4 add w 4 add dooval cleanup stroke grestore end } def % ratio depth nodename testnodeoval - % ratio should be between 0 and 1 /testnodeoval {nodes exch get begin gsave newpath h h mul w w mul add sqrt div dup dup dup w mul neg x add exch h mul neg y add moveto dup h mul 2 mul h add exch w mul 2 mul w add testdooval stroke grestore end } def /cleanup{gsave x y moveto h nodemargin sub .5 add w nodemargin sub .5 add doccbox 1 setgray fill grestore }def /boxdict 4 dict def boxdict /mtrx matrix put /dobox{boxdict begin /w exch def /h exch def /savematrix mtrx currentmatrix def 0 h rlineto w 0 rlineto 0 h neg rlineto closepath savematrix setmatrix end} def % do box in counterclockwise fashion /doccbox{boxdict begin /w exch def /h exch def /savematrix mtrx currentmatrix def w 0 rlineto 0 h rlineto w neg 0 rlineto closepath savematrix setmatrix end} def /ovaldict 6 dict def ovaldict /mtrx matrix put % h w ovaldict - /dooval{ovaldict begin /w exch def /h exch def /savematrix mtrx currentmatrix def 0 h 2 div rmoveto 0 h 2 div nodemargin sub nodemargin h 2 div w 2 div h 2 div rcurveto w 2 div nodemargin sub 0 w 2 div nodemargin neg w 2 div h 2 div neg rcurveto 0 h 2 div neg nodemargin add nodemargin neg h 2 div neg w 2 div neg h 2 div neg rcurveto w 2 div neg nodemargin add 0 w 2 div neg nodemargin w 2 div neg h 2 div rcurveto savematrix setmatrix end} def % give height and width of a box and the lower left hand point % produce a curve that will enclose the box. % initial point already defined % ratio h w testdooval - /testdooval{ovaldict begin /w exch def /h exch def /r exch def h 2 div neg r mul dup h 2 div dup r mul 3 1 roll 2 r sub mul 0 h rcurveto w 2 div dup r mul exch 2 r sub mul w 2 div r mul dup 3 1 roll w 0 rcurveto h 2 div r mul dup h 2 div neg dup r mul 3 1 roll 2 r sub mul 0 h neg rcurveto w 2 div neg dup r mul exch 2 r sub mul w 2 div neg r mul dup 3 1 roll w neg 0 rcurveto end} def end % of treedict end % of TeXdict % gsave