%% %% Partial Emulation of Emma Pease's tree-dvips.sty using pst-nodes %% %% version 0.5 (an alpha) %% %% License: LaTeX Project Public License %% %% c. Avery D Andrews 2006 %% %% acknowledgements %% Herbert Voss for info on how to get at the corners %% Robert Levine and John Frampton for incitement %% Emma Pease for the original %% %% the philosophy is to combine a reasonable amount of backward %% compatibility for documents based on tree-dvips, without %% trying to push that notation much further (but a little bit, %% if it's easy and seems like it might be useful). %% %% \(a)nodecurve seems to be the biggest problem, since tree-dvips %% wants dimension for curvature, and pst-node's nccurv etc. %% want numbers. The solution adopted is have \(a)nodecurve require %% numbers in the curvature parameters, so that these will have to %% be changed in the documents, but add \pcnodecurve not requiring %% any curvature parameters, but taking linestyle options as a final %% optional [] parameter. %% %% \nodepoint affords a similar problem; no easy way to get vert %% displacement. Implementation treats height parameter as angle %% %% Implemented: %% \node %% \nodepoint (extended with angle option) %% \(a)nodeconnect, \nodeconnect (extended) %% \treelinewidth %% \(a)nodecurve (with curvature issue) %% \pcnodecuve (non tree-dvips) %% \(a)barnodeconnect %% \nodetriangle %% \putstuff: non-tree-dvips, but useful %% \putpoint: " %% %% Partially Implemented: %% %% \nodebox, \nodeoval, \nodecircle : dimension parameters needed %% \csname PSTTreeDvipsEmuLoaded\endcsname \let\PSTTreeDvipsEmuLoaded\endinput \ifx\PSTnodesLoaded\endinput\else\input pst-node.tex\fi\relax { \catcode`\_=11 % sets underbar to letter \catcode` =9 % causes spaces to be ignored \catcode`\^^M=9 % causes to be ignored % % Some tree mode parameters (from tree-dvips.sty) % % \newdimen\nodemargin % \global\nodemargin=2pt \newdimen\treelinewidth \global\treelinewidth=.4pt \newbox\tempbox \gdef\thinline{\treelinewidth=.3pt} \newdimen\dashlength % % makedash at end so spaces will work % % % cheap and nasty test for empty argument, assuming a real % one doesn't start with a colon % \gdef\ada@ifempty#1#2#3{\test@empty#1:{#2}{#3}} \gdef\test@empty{\@ifnextchar :{\@testfirst}{\@testsecond}} \gdef\@testfirst#1:#2#3{#2} \gdef\@testsecond#1:#2#3{#3} \gdef\ada@ifnotempty#1#2{\ada@ifempty{#1}{}{#2}} % % machinery for parsing an arglist of the form [a(,b)] % n-ary generalization possible? Yes, see gloss/lingtrees code! % \gdef\oneortwoargs#1#2[#3]{\@oneortwoargs{#1}{#2}[#3,]} \gdef\@oneortwoargs#1#2[#3,{\@ifnextchar ] {#1[#3} {\@secondarg{#2}[#3]} } \gdef\@secondarg#1[#2]#3,]{#1[#2,#3]} % % These commands retrieve coords from names, for use when % pstricks \SpecialCoor is active. They must be surrounded % by parens in their environments in order to work % \gdef\loc@tl#1{#1_tl} \gdef\loc@t#1{#1|#1_tl} \gdef\loc@tr#1{#1_br|#1_tl} \gdef\loc@r#1{#1_br|#1} \gdef\loc@br#1{#1_br} \gdef\loc@b#1{#1|#1_br} \gdef\loc@bl#1{#1_tl|#1_br} \gdef\loc@l#1{#1_tl|#1} \gdef\loc@c#1{#1} \gdef\ang@tl{135} \gdef\ang@t{90} \gdef\ang@tr{45} \gdef\ang@r{0} \gdef\ang@br{-45} \gdef\ang@b{-90} \gdef\ang@bl{-135} \gdef\ang@l{180} % % a prettier package for the above, usable in the document % \gdef\nodeloc#1#2{\csname loc@#1\endcsname{#2}} % #2 for node; does nothing yet, but maybe someday ... \gdef\nodeang#1#2{\csname ang@#1\endcsname} % \node{label}{content} % Perhaps a dive into postscript could let us do it with one node instead of 3 % (if, in postscript, nodes know how big they are) % \gdef\node#1#2{ \rnode[tl]{#1_tl}{ \rnode[br]{#1_br}{ \rnode{#1}{#2} } } } % % \nodepoint{nodename}[displacement distance](angle) % default is current point. Maybe someday [vertical displacement] % \gdef\nodepoint#1{\@ifnextchar [{\@nodepoint#1}{\pnode{#1}}} \gdef\@nodepoint#1[#2]{\@ifnextchar ({\@@nodepoint#1[#2]} {\@ifnextchar [{\@@@nodepoint#1[#2]} {\@@nodepoint#1[#2](0)} } } \gdef\@@nodepoint#1[#2](#3){{ \SpecialCoor \pnode{@a} % % this below seems excessive but how else to get \nodeconnect to work? % \uput{#2}[#3](@a){\pnode{#1}\pnode{#1_tl}\pnode{#1_br}} }} \gdef\@@@nodepoint#1[#2][#3]{{ \psset{xunit=#2, yunit=#3} \uput{0}[0](1,1){\pnode{#1}\pnode{#1_tl}\pnode{#1_br}} }} % \putpoint{label}{distance}(angle)[from corner]{from node} % 1 2 3 4 5 % 2 is either {num} or {num,num}=x,y; in the latter case 3 is ignored % \gdef\putpoint#1#2{\@ifnextchar ( {\@putpoint{#1}{#2}} {\@putpoint{#1}{#2}(0)} } \gdef\@putpoint#1#2(#3){\@ifnextchar [ {\@@putpoint{#1}{#2}(#3)} {\@@putpoint{#1}{#2}(#3)[]} } \gdef\@@putpoint#1#2(#3)[#4]#5{ \def\procloc[##1]{\oneortwoargs{\oneloc}{\twolocs}[##1]} \def\oneloc[##1]{\putpoint_ang} \def\twolocs[##1,##2]{\putpoint_cart} \procloc[#2]{#1}[#2]{#3}[#4]{#5} } \gdef\putpoint_ang#1[#2]#3[#4]#5{{ \SpecialCoor \uput{#2}[#3](\nodeloc{#4}{#5}){\nodepoint{#1}} \uput{#2}[#3](\nodeloc{#4}{#5}){\nodepoint{#1_tl}} \uput{#2}[#3](\nodeloc{#4}{#5}){\nodepoint{#1_br}} }} \gdef\putpoint_cart#1[#2,#3]#4[#5]#6{{ \SpecialCoor % \message{xunit is #2} \ifdim #2=0em \putpoint_ang{#1}[#3]{90}[#5]{#6} \else \ifdim #3=0em \putpoint_ang{#1}[#2]{0}[#5]{#6} \else \psset{xunit=#2,yunit=#3} \rput(\nodeloc{#5}{#6}){\uput{0}[0](1,1){\nodepoint{#1}}} \rput(\nodeloc{#5}{#6}){\uput{0}[0](1,1){\nodepoint{#1_tl}}} \rput(\nodeloc{#5}{#6}){\uput{0}[0](1,1){\nodepoint{#1_br}}} \fi \fi }} % \putstuff{label}{distance}(angle)[from corner]{from node} % 1 2 3 4 5 % 2 is either {num} or {num,num}=x,y; in the latter case 3 is ignored % \gdef\putstuff#1#2{\@ifnextchar ( {\@putstuff{#1}{#2}} {\@putstuff{#1}{#2}(0)} } \gdef\@putstuff#1#2(#3){\@ifnextchar [ {\@@putstuff{#1}{#2}(#3)} {\@@putstuff{#1}{#2}(#3)[]} } \gdef\@@putstuff#1#2(#3)[#4]#5{ \def\procloc[##1]{\oneortwoargs{\oneloc}{\twolocs}[##1]} \def\oneloc[##1]{\putstuff_ang} \def\twolocs[##1,##2]{\putstuff_cart} \tracingmacros=1 \procloc[#2]{#1}[#2]{#3}[#4]{#5} } \gdef\putstuff_ang#1[#2]#3[#4]#5{{ \SpecialCoor \uput{#2}[#3](\nodeloc{#4}{#5}){\nodestuff{#1}} \uput{#2}[#3](\nodeloc{#4}{#5}){\nodestuff{#1_tl}} \uput{#2}[#3](\nodeloc{#4}{#5}){\nodestuff{#1_br}} }} \gdef\putstuff_cart#1[#2,#3]#4[#5]#6{{ \SpecialCoor % \message{xunit is #2} \ifdim #2=0em \putstuff_ang{#1}[#3]{90}[#5]{#6} \else \ifdim #3=0em \putstuff_ang{#1}[#2]{0}[#5]{#6} \else \psset{xunit=#2,yunit=#3} \rput(\nodeloc{#5}{#6}){\uput{0}[0](1,1){#1}} \fi \fi }} % \nodeconnect(pre-options)[fromloc]{fromnode}[toloc]{tonode}[style parameters] % 1 2 3 4 5 6 7 % % plain lines by default. \pc node connection command should work; \nc's won't % % the pre-options are for defining variants (e.g. \anodeconnect), not general use % in definitions, inherent properties first, then pre-option and finally the % style parameters % \gdef\nodeconnect{\@ifnextchar < {\@nodeconnect} {\@nodeconnect<\pcline>} } \gdef\@nodeconnect<#1>{\@ifnextchar ( {\@@nodeconnect<#1>} {\@@nodeconnect<#1>()} } \gdef\@@nodeconnect<#1>(#2){\@ifnextchar [ {\@@@nodeconnect<#1>(#2)} {\@@@nodeconnect<#1>(#2)[b]} } \gdef\@@@nodeconnect<#1>(#2)[#3]#4{\@ifnextchar [ {\@@@@nodeconnect<#1>(#2)[#3]{#4}} {\@@@@nodeconnect<#1>(#2)[#3]{#4}[t]} } \gdef\@@@@nodeconnect<#1>(#2)[#3]#4[#5]#6{\@ifnextchar [ {\@@@@@nodeconnect<#1>(#2)[#3]{#4}[#5]{#6}} {\@@@@@nodeconnect<#1>(#2)[#3]{#4}[#5]{#6}[]} } \gdef\@@@@@nodeconnect<#1>(#2)[#3]#4[#5]#6[#7]{{\SpecialCoor \psset{nodesep=0pt, linewidth=\treelinewidth} \ada@ifnotempty{#2}{\psset{#2}} \ada@ifnotempty{#7}{\psset{#7}} #1(\nodeloc{#3}{#4})(\nodeloc{#5}{#6}) }} % \anodeconnect[fromloc]{fromnode}[toloc]{tonode}[style options] % % connecting line with arrow at the end (for complicated arrows, % use \nodeconnect with arrows option) % \gdef\anodeconnect{\nodeconnect(arrows=->)} % % application of oneortwoargs machinery for the nodecurve curvature argument % \gdef\getncurv[#1]{\oneortwoargs{\ncurv@}{\ncurv@AB}[#1]} \gdef\ncurv@[#1]{\psset{ncurv=#1}} \gdef\ncurv@AB[#1,#2]{\psset{ncurvA=#1,ncurvB=#2}} % \nodecurve(pre-option)[fromloc]{fromnode}[toloc]{tonode}(curve)[style options] % 1 2 3 4 5 6 7 8 % for curve, either one number or 2, separated by commas, eg: (2) or (1,2) % 1 does nothing for the moment, but maybe someday (curved zigags?) % % for curve, either one number or 2, separated by commas, eg: (2) or (1,2) % \gdef\nodecurve{\@ifnextchar < {\@nodecurve} {\@nodecurve<\pccurve>} } \gdef\@nodecurve<#1>{\@ifnextchar ( {\@@nodecurve<#1>} {\@@nodecurve<#1>()} } \gdef\@@nodecurve<#1>(#2){\@ifnextchar [ {\@@@nodecurve<#1>(#2)} {\@@@nodecurve<#1>(#2)[b]} } \gdef\@@@nodecurve<#1>(#2)[#3]#4{\@ifnextchar [ {\@@@@nodecurve<#1>(#2)[#3]{#4}} {\@@@@nodecurve<#1>(#2)[#3]{#4}[t]} } \gdef\@@@@nodecurve<#1>(#2)[#3]#4[#5]#6{\@ifnextchar ( {\@@@@@nodecurve<#1>(#2)[#3]{#4}[#5]{#6}} {\@@@@@nodecurve<#1>(#2)[#3]{#4}[#5]{#6}()} } \gdef\@@@@@nodecurve<#1>(#2)[#3]#4[#5]#6(#7){\@ifnextchar [ {\@@@@@@nodecurve<#1>(#2)[#3]{#4}[#5]{#6}(#7)} {\@@@@@@nodecurve<#1>(#2)[#3]{#4}[#5]{#6}(#7)[]} } \gdef\@@@@@@nodecurve<#1>(#2)[#3]#4[#5]#6(#7)[#8]{{ \SpecialCoor \ada@ifnotempty{#7}{\getncurv[#7]} \psset{nodesep=\nodemargin, linewidth=\treelinewidth, angleA=\nodeang{#3}{#4}, angleB=\nodeang{#5}{#6}} \ada@ifnotempty{#2}{\psset{#2}} \ada@ifnotempty{#8}{\psset{#8}} #1(\nodeloc{#3}{#4})(\nodeloc{#5}{#6}) }} % \anodecurve[fromloc]{fromnode}[toloc]{tonode}{depth} % for fancy options use \pcnodecurve with arrows style. % \gdef\anodecurve{\nodecurve(arrows=->)} % % connect two words with straight-edge U % % \barnodeconnect(pre-options)[arm]{from}{to}[style] % 1 2 3 4 5 % \gdef\barnodeconnect{\@ifnextchar ( {\@barnodeconnect} {\@barnodeconnect()} } \gdef\@barnodeconnect(#1){\@ifnextchar [ {\@@barnodeconnect(#1)} {\@@barnodeconnect(#1)[]} } \gdef\@@barnodeconnect(#1)[#2]#3#4{\@ifnextchar [ {\@@@barnodeconnect(#1)[#2]{#3}{#4}} {\@@@barnodeconnect(#1)[#2]{#3}{#4}[]} } \gdef\@@@barnodeconnect(#1)[#2]#3#4[#5]{{ \psset{nodesep=\nodemargin, linewidth=\treelinewidth, angle=-90} \ada@ifnotempty{#1}{\psset{#1}} \ada@ifnotempty{#2}{\psset{arm=#2}} \ada@ifnotempty{#5}{\psset{#5}} \ncbar{#3}{#4} }} % % \abarnodeconnect[arm]{from}{to}[linestyle] % \gdef\abarnodeconnect{\barnodeconnect(arrows=->)} % triangles of laziness % % \nodetriangle {apex}{base}[style] % 1 2 3 % \gdef\nodetriangle#1#2{\@ifnextchar [ {\@nodetriangle{#1}{#2}} {\@nodetriangle{#1}{#2}[]} } \gdef\@nodetriangle#1#2[#3]{{ \nodeconnect{#1}[tl]{#2}[#3] \nodeconnect{#1}[tr]{#2}[#3] \nodeconnect[tl]{#2}[tr]{#2}[#3] }} % % \nodecircle{node}{radius}[style options[ % \gdef\nodecircle#1(#2){\@ifnextchar [ {\@nodecircle#1(#2)} {\@nodecircle#1(#2)[]} } \gdef\@nodecircle#1(#2)[#3] {{ \SpecialCoor \ada@ifempty{#3}{\pscircle(#1){#2}} {\pscircle[#3](#1){#2}} % \psset{#3} doesn't seem to work here }} % % \nodeoval{node}{hradius, vradius}[style options] % \gdef\nodeoval#1(#2){\@ifnextchar [ {\@nodeellipse#1(#2)} {\@nodeellipse#1(#2)[]} } \gdef\@nodeellipse#1(#2,#3)[#4] {{ \SpecialCoor \ada@ifempty{#4}{\psellipse(#1)(#2,#3)} {\psellipse[#4](#1)(#2,#3)} }} % % \nodebox{node}[style options] % \gdef\nodebox#1{\@ifnextchar [ {\@nodebox#1} {\@nodebox#1[]} } \gdef\@nodebox#1[#2] {{ \SpecialCoor \putpoint{@a}{\nodemargin}(135)[tl]{#1} \putpoint{@b}{\nodemargin}(-45)[br]{#1} \ada@ifempty{#2}{\psframe(@a)(@b)} {\message{fuccon arg #2} \psframe[#2](@a)(@b)} % \psset{#3} doesn't seem to work here }} } % end group & restore standard catcodes % \makedash{dimen} makes dashes of dimen length (0 dimen = none not solid) \gdef\makedash#1{\psset{linestyle=dashed, dash=2pt #1}} \gdef\nodepointerror{third argument of nodepoint must now be angle (number)} \psset{arrowsize=2pt 2, arrowlength=1.2, arrowinset=.3}