%% $Id: pst-tvz.tex 524 2011-06-14 15:19:21Z herbert $ %% COPYRIGHT 1993-2026 by Timothy Van Zandt %% Herbert Voß % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2003/12/01 or later. % \csname PStvzLoaded\endcsname \let\PStvzLoaded\endinput \ifx\PSTnodesLoaded\endinput\else\input pst-node.tex\fi \ifx\PSTXKeyLoaded\endinput \else\input pst-xkey \fi % \def\fileversion{1.02} \def\filedate{2026/01/02} \message{ v\fileversion, \filedate (tvz,dg,hv)} \message{ v\fileversion, \filedate} \edef\TheAtCode{\the\catcode`\@} \catcode`\@=11 % \pst@addfams{pst-tvz} \def\pstree@puttop#1{#1,\expandafter\pstree@@puttop} \def\pstree@@puttop#1,{} \def\pstree@gettop#1{\expandafter\pstree@@gettop#1\@nil} \def\pstree@@gettop#1,#2\@nil{#1} \def\pstree@poptop#1#2{\expandafter\pstree@@poptop#1\relax#1#2} \def\pstree@@poptop#1,#2\relax#3#4{% #4=#1\relax \def#3{#20,}} \def\pstree@max#1#2{% \pst@cntg=\z@ \expandafter\pstree@@max#1\relax #2=\pst@cntg}% \def\pstree@@max#1,#2{% \ifnum#1>\pst@cntg \pst@cntg=#1 \fi \ifx\relax#2\else \expandafter\pstree@@max \fi #2} \def\pstree@add#1#2{% \def\pst@tempg{}% \pst@cnth=#1\relax \expandafter\pstree@@add#2\relax \let#2\pst@tempg} \def\pstree@@add#1,#2{% \pst@cntg=#1 \advance\pst@cntg\pst@cnth \xdef\pst@tempg{\pst@tempg\the\pst@cntg,}% \ifx\relax#2\else \expandafter\pstree@@add \fi #2} \def\pstree@tightfit#1#2#3{% \pst@cnth=\z@ \let\pstree@xtightfit\pstree@@xtightfit \edef\next{\noexpand\pstree@@tightfit#1\relax#2\relax}% \next #3=\pst@cnth} \def\pstree@@tightfit#1,#2\relax#3,#4\relax{% \pst@cntg=#1 \advance\pst@cntg#3 \pstree@xtightfit \ifnum\pst@cntg>\pst@cnth \pst@cnth=\pst@cntg \fi \let\next\relax \ifx\relax#2\relax\else \ifx\relax#4\relax\else \def\next{\pstree@@tightfit#2\relax#4\relax}% \fi \fi \next} \def\pstree@@xtightfit{% \ifnum\psk@thisxtreesep=\z@ \let\pstree@xtightfit\relax \else \edef\pstree@xtightfit{\advance\pst@cntg\psk@thisxtreesep\relax}% \fi} \def\pstree@loosefit#1#2#3{% \pstree@max#1\pst@cnth \pstree@max#2#3% \advance#3\pst@cnth \ifnum\psk@thisxtreesep=\z@\else\pstree@xloosefit#1#2#3\fi} \def\pstree@xloosefit#1#2#3{% \let\next\relax%%%%%%%%%%%%%% hv 20101029 \edef\next{\noexpand\pstree@@xloosefit#3\relax#1\relax#2\relax}% \next} \def\pstree@@xloosefit#1\relax#2,#3\relax#4,#5\relax{% \ifx\relax#3\relax\else \ifx\relax#5\relax\else\advance#1\psk@thisxtreesep\relax\fi \fi} \def\pstree@zip#1#2#3#4{% \pst@cnth=#1\relax \pst@cnth=-\pst@cnth \def\pst@tempg{}% \edef\next{\noexpand\pstree@@zip#2\relax#3\relax}% \next \global\let#4\pst@tempg} \def\pstree@@zip#1,#2\relax#3,#4\relax{% \pst@cntg=#1 \advance\pst@cntg\pst@cnth \edef\pst@tempg{\pst@tempg\ifnum#3>\pst@cntg#3\else\the\pst@cntg\fi,}% \let\next\relax %%%%%%%%%%%%%%%%%%%%%%%% hv \ifx\relax#2\relax \edef\pst@tempg{\pst@tempg#4}% \else \ifx\relax#4\relax \def\next{\pstree@@add#2\relax}% \else \def\next{\pstree@@zip#2\relax#4\relax}% \fi \fi \next} \def\pstree@bimax#1#2{% \def\pst@tempg{}% \edef\next{\noexpand\pstree@@bimax#1\relax#2\relax}% \next \global\let#1\pst@tempg} \def\pstree@@bimax#1,#2\relax#3,#4\relax{% \edef\pst@tempg{\pst@tempg\ifnum#1>#3 #1\else#3\fi,}% \let\next\relax%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% hv \ifx\relax#2\relax \edef\pst@tempg{\pst@tempg#4}% \else \ifx\relax#4\relax \edef\pst@tempg{\pst@tempg#2}% \let\next\relax \else \def\next{\pstree@@bimax#2\relax#4\relax}% \fi \fi \next} \def\pstree@set#1#2{% \pst@cntg=#1\relax \edef#2{\expandafter\pstree@@set#2\relax}} \def\pstree@@set#1,#2{% \the\pst@cntg,\ifx\relax#2\else\expandafter\pstree@@set\fi#2} \newcount\pstree@ID \newcount\pstree@levelID \newcount\pstree@succID \newcount\pstree@nodeID \newcount\psTREE@sep \newcount\psTREE@width \newcount\psTREE@height \newcount\psTREE@depth \newcount\pstree@cumlevelsep \newcount\pstree@numlevels \newbox\pstree@box \def\pstree{\pst@object{pstree}} \def\pstree@i#1#2{\psTree@i{#1}\\{#2}\endpsTree} \def\psTree{\pst@object{psTree}} \def\psTree@i{% \begingroup \ifnum\psk@predmode=\m@ne \let\pstree@savedshortput\pst@shortput \psset{shortput=tab}% \else \pst@@killglue \fi \let\pstree@thisframe\pstree@frame \global\let\pstree@frame\relax \pstree@savevalues \ifnum\psk@predmode=\m@ne \let\pstree@saveskiplevels\z@ \else \ifnum\psskiplevels>\z@\else \expandafter\pstree@checkskiplevels\pst@par,skiplevels=\z@,\@nil \fi \let\pstree@saveskiplevels\psskiplevels \ifnum\psskiplevels>\z@ \pstree@skipprofile \fi \fi \use@par \let\pstree@saveadjustbbox\psk@adjustbbox \let\pstree@savetreerep\psk@treerep \if@leafaligntree \chardef\pstree@savemaxlevel\pstree@maxlevel \pstree@initleafalign \else \ifnum\psk@predmode=\psk@treemode\else \chardef\pstree@savemaxlevel\pstree@maxlevel \fi \fi \ifnum\psk@predmode=\psk@treemode \global\advance\pstree@ID\@ne \edef\pstree@id{\the\pstree@ID}% \fi \def\\{\pstree@endrow\pst@object{pstreecr}}% \setbox\pstree@box\copy\voidb@x \let\pst@thisbox\relax \pst@makelongbox{}% \pstree@treemode \ignorespaces} \def\pstreecr@i{% \expandafter\pstree@checkskiplevels\pst@par,skiplevels=\z@,\@nil \ifnum\psskiplevels>\z@ \pstree@skiplevelseps \fi \pstree@initnestedpar \use@par \pstree@setlevelpar \edef\pspred{\pstree@gettop\pstree@basenodes}% \let\pst@thisbox\relax \pst@makelongbox{}% \pstree@treemode \ignorespaces} % \def\psPred#1{\psPred@i#10\@nil} \def\psPred@i#1#2\@nil{% \expandafter\ifcase\expandafter#1% \expandafter\psPred@ii\pstree@basenodes,,,,,,,,,\@nil} \def\psPred@ii#1,#2,#3,#4,#5,#6,#7,#8,#9,{% \or#1\or#2\or#3\or#4\or#5\or#6\or#7\or#8\or#9\fi\psPred@iii} \def\psPred@iii#1\@nil{} % \def\pstree@skiplevelseps{% \pst@cntg=\psskiplevels \loop \pstree@setlevelpar \advance\pstree@cumlevelsep\psk@thislevelsep\relax \edef\pstree@levelsizes{\pstree@levelsizes,\psk@thislevelsep,0,0}% \advance\pstree@numlevels\@ne \ifnum\pst@cntg>\@ne \advance\pst@cntg\m@ne \repeat} \def\pstree@endrow{% \pst@@killglue \pst@endlongbox \pstree@checkrow % Check for missing objects or extra space. \ifvoid\pstree@box \pstree@InitTreeDim \else \pstree@joinrows % Join root and successors in a box. \pstree@joinprofiles % Adjust height, depth and profiles. \fi} \def\endpsTree{% \pstree@endrow \pstree@thisframe \ifPst@varlevelsep \ifnum\psk@predmode=\psk@treemode\else \pstree@writelevelsizes \fi \fi \if@leafaligntree \pstree@writemaxlevel \global\chardef\pstree@maxlevel\pstree@savemaxlevel \else \ifnum\psk@predmode=\psk@treemode\else \global\chardef\pstree@maxlevel\pstree@savemaxlevel \fi \fi \let\psk@adjustbbox\pstree@saveadjustbbox \let\psk@treerep\pstree@savetreerep \let\psskiplevels\pstree@saveskiplevels \pstree@makecanonical \pstree@restorevalues \pstree@build \ifnum\psk@treerep>\@ne\pstree@rep\fi \global\let\pssucc\pstree@savedsucc \endgroup \ifnum\psk@predmode>\m@ne\expandafter\ignorespaces\fi} \def\pstree@savevalues{% \edef\pstree@restorevalues{% \pst@ngdef\psTREE@leftprofile \pst@ngdef\psTREE@rightprofile \pst@ngdef\psTREE@levelsizes \pst@ngdef\psTREE@center \pst@ngdef\psTREE@leftbase \pst@ngdef\psTREE@rightbase \pst@ngdef\psTREE@centerbase \pst@ngdef\psTREE@rootnodes \pst@ngdef\psTREE@basenodes \pst@ngdef\psTREE@maxtreesep \pst@ngdef\psTREE@numlevels \pst@ngdef\psTREE@cumlevelsep \global\psTREE@height=\the\psTREE@height\relax \global\psTREE@depth=\the\psTREE@depth\relax \global\psTREE@width=\the\psTREE@width\relax \pst@ngdef\psTREE@addtreesep \pst@ngdef\psk@thistreesep \pst@ngdef\psk@thisxtreesep \pst@ngdef\psk@thistreenodesize \pst@ngdef\psk@thistreefit \global\pstree@succID=\the\pstree@succID\relax}} {\def\pst@ngdef#1{\gdef\noexpand#1{}}\pstree@savevalues\pstree@restorevalues} %%%??? Add error checking \define@key[psset]{pst-tvz}{treemode}[D]{% \chardef\psk@treemode \ifx#1U\@empty2\else\ifx#1R\@empty1\else\ifx#1L\@empty3\else\z@\fi\fi\fi \relax} \psset[pst-tvz]{treemode=D} \define@boolkey[psset]{pst-tvz}[ps]{treeflip}[true]{} \psset[pst-tvz]{treeflip=false} \define@key[psset]{pst-tvz}{root}[\TC]{\def\psroot{#1}} \psset[pst-tvz]{root=\TC} \def\pst@dimtoint#1#2{% should go into pstricks.tex \pssetlength\pst@dimg{#1}% \edef#2{\number\pst@dimg}} \def\pst@ngdef#1{\gdef\noexpand#1{#1}} \define@key[psset]{pst-tvz}{treesep}[0.75cm]{\pst@dimtoint{#1}\psk@treesep} \psset[pst-tvz]{treesep=.75cm} % \define@key[psset]{pst-tvz}{thistreesep}{\pst@dimtoint{#1}\psk@thistreesep} \define@key[psset]{pst-tvz}{xtreesep}[0.75cm]{\pst@dimtoint{#1}\psk@xtreesep} \psset[pst-tvz]{xtreesep=0pt} % \define@key[psset]{pst-tvz}{thisxtreesep}{\pst@dimtoint{#1}\psk@thisxtreesep} % \psset@thistreenodesize,\psk@thistreenodesize} \define@key[psset]{pst-tvz}{treenodesize}[-1pt]{% \pssetlength\pst@dimg{#1}% \divide\pst@dimg\tw@ \edef\psk@treenodesize{\number\pst@dimg}} \psset[pst-tvz]{treenodesize=-1pt} \define@key[psset]{pst-tvz}{thistreenodesize}[-1pt]{% \pssetlength\pst@dimg{#1}% \divide\pst@dimg\tw@ \edef\psk@thistreenodesize{\number\pst@dimg}} \define@key[psset]{pst-tvz}{treefit}[tight]{% \@ifundefined{pstree@#1fit}% {\@pstrickserr{Bad `treefit' parameter value: `#1'}\@ehpa}% {\def\psk@treefit{#1}}}% \psset[pst-tvz]{treefit=tight} % \define@key[psset]{pst-tvz}{thistreefit}[tight]{% \@ifundefined{pstree@#1fit}% {\@pstrickserr{Bad `treefit' parameter value: `#1'}\@ehpa}% {\def\psk@thistreefit{#1}}}% \define@key[psset]{pst-tvz}{treerep}[1]{\chardef\psk@treerep#1\relax} \psset[pst-tvz]{treerep=1} \def\pstree@rep{% \ifnum\psk@treerep>\@ne \pst@cntg\psk@treerep \advance\pst@cntg\m@ne \chardef\psk@treerep\pst@cntg \pstree@build \expandafter\pstree@rep \fi} \def\psk@adjustbbox{} \def\pstree@setadjustbbox#1#2{% \pssetlength\pst@dimg{#1}% \edef\psk@adjustbbox{\psk@adjustbbox#2\number\pst@dimg sp\relax}} \define@key[psset]{pst-tvz}{bbl}{\pstree@setadjustbbox{#1}{\pst@dima=}} \define@key[psset]{pst-tvz}{bbr}{\pstree@setadjustbbox{#1}{\pst@dimb=}} \define@key[psset]{pst-tvz}{bbh}{\pstree@setadjustbbox{#1}{\pst@dimc=}} \define@key[psset]{pst-tvz}{bbd}{\pstree@setadjustbbox{#1}{\pst@dimd=}} \define@key[psset]{pst-tvz}{xbbl}{\pstree@setadjustbbox{#1}{\advance\pst@dima}} \define@key[psset]{pst-tvz}{xbbr}{\pstree@setadjustbbox{#1}{\advance\pst@dimb}} \define@key[psset]{pst-tvz}{xbbh}{\pstree@setadjustbbox{#1}{\advance\pst@dimc}} \define@key[psset]{pst-tvz}{xbbd}{\pstree@setadjustbbox{#1}{\advance\pst@dimd}} \define@boolkey[psset]{pst-tvz}[Pst@]{showbbox}[true]{} \psset[pst-tvz]{showbbox=false} \def\pstree@showbbox{% \setbox\pstree@box=\hbox{% \psset{linewidth=.1pt,linecolor=black,linestyle=solid,% dimen=middle,fillstyle=none}% \def\pst@par{}\@starfalse \psframe@i(-\pst@dima,-\pst@dimd)(\pst@dimb,\pst@dimc)% \box\pstree@box}}% \define@key[psset]{pst-tvz}{levelsep}[2cm]{\pst@dimtoint{#1}\psk@levelsep} \psset[pst-tvz]{levelsep=2cm} \define@key[psset]{pst-tvz}{thislevelsep}{\pst@dimtoint{#1}\psk@thislevelsep} \define@boolkey[psset]{pst-tvz}[Pst@]{varlevelsep}[true]{% \ifnum\psk@predmode=\psk@treemode \@pstrickserr{varlevelsep cannot be changed for proper subtrees}\@ehpa \fi} \let\psk@predmode\m@ne \let\if@predflip\iffalse %\fi \psset[pst-tvz]{varlevelsep=false} \define@key[psset]{pst-tvz}{treeshift}[0]{% \pssetlength\pst@dimg{#1}% \pst@dimg-\pst@dimg \edef\psk@treeshift{\number\pst@dimg}} \psset[pst-tvz]{treeshift=0} \define@key[psset]{pst-tvz}{skiplevels}[0]{\chardef\psskiplevels#1\relax} \psset[pst-tvz]{skiplevels=0} \def\pstree@initnestedpar{% \def\psk@adjustbbox{}% \let\psk@treeshift\z@ \chardef\psskiplevels\z@ \chardef\psk@treerep\@ne \def\psk@thislevelsep{\psk@levelsep}% \def\psk@thistreesep{\psk@treesep}% \def\psk@thisxtreesep{\psk@xtreesep}% \def\psk@thistreenodesize{\psk@treenodesize}% \def\psk@thistreefit{\psk@treefit}% \def\psk@thisunary{\psk@unary}% \let\if@leafaligntree\iffalse} \def\pstree@setlevelpar{% \advance\pstree@levelID\@ne \csname pstreehook\romannumeral\pstree@levelID\endcsname \ifPst@varlevelsep \ifnum\psk@predmode=\psk@treemode\else \pstree@initadjustlevelsep \fi \pstree@adjustlevelsep \fi \edef\pst@tposflip{\ifnum\psk@treemode>\@ne 1 sub neg \fi}}% \def\pstree@build@outer{% \leavevmode \hbox{% \vrule height \pst@dimc depth \pst@dimd width \z@ \kern\pst@dima \ifnum\psk@treerep>\@ne\copy\else\box\fi\pstree@box \kern\pst@dimb}} % % "\pstree@makecanonical@outer" converts trees to nodes. What the left and right profiles correspond to depends on whether the tree is horizontal or vertical, and on whether the tree is flipped. What the tree height and depth correspond to depends on the "treemode". % When a tree is in mode, it may adjust its bounding box. \def\pstree@makecanonical@outer{% \pstree@gettreebbox \ifx\pstree@center\@empty \pst@dimg\pstree@width sp \divide\pst@dimg\tw@ \else \pst@dimg\pstree@center sp \fi \ifnum\pst@dimg=\z@\else \advance\pst@dima\pst@dimg \advance\pst@dimb-\pst@dimg \ifodd\psk@treemode \setbox\pstree@box\hbox{% \ifpstreeflip\lower\else\raise\fi\pst@dimg\box\pstree@box}% \else \setbox\pstree@box\hbox{% \kern\ifpstreeflip\else-\fi\pst@dimg\unhbox\pstree@box}% \fi \fi \wd\pstree@box=\z@ \dp\pstree@box=\z@ \ht\pstree@box=\z@} \def\pstree@gettreebbox{% \pstree@max\pstree@leftprofile\pst@cnta \pstree@max\pstree@rightprofile\pst@cntb \advance\pst@cntb\pstree@width \ifodd\psk@treemode \ifpstreeflip \pst@dimc\pst@cntb sp \pst@dimd\pst@cnta sp \else \pst@dimc\pst@cnta sp \pst@dimd\pst@cntb sp \fi \else \ifpstreeflip \pst@dima\pst@cntb sp \pst@dimb\pst@cnta sp \else \pst@dima\pst@cnta sp \pst@dimb\pst@cntb sp \fi \fi \ifcase\psk@treemode \pst@dimc\pstree@height sp \pst@dimd\pstree@depth sp \or \pst@dima\pstree@height sp \pst@dimb\pstree@depth sp \or \pst@dimc\pstree@depth sp \pst@dimd\pstree@height sp \or \pst@dima\pstree@depth sp \pst@dimb\pstree@height sp \fi \psk@adjustbbox \ifPst@showbbox \pstree@showbbox \fi} % "\pstree@outermode" sets up some values that should be in effect for outer trees. A tree is "outer" is it is not nested inside any tree, or if it is inside any box other than a tree row (e.g., in a "\TR" node, or a label command). This means that "\pstree@outer" must be exected once below (for trees that are not nested inside any tree), and then "\pst@thisbox" is set to "\pstree@outer" inside a tree row. % % "\pst@tposflip" is a hook in the "tput" commands defined in "pst-node.tex" that flips the value of the positioning argument for trees, so that the number always refers to the distance from the predecessor node to successor node. This is initialized within trees, but in outer mode we want to disable the hook. % % "\pst@shortput" is also given a special meaning in trees, and we have to restore its value when entering outer mode. % % "\psk@bboxadust" stores the bounding box adjust parameters. We do not want these parameters to affect nested objects. % % Since "\pst@thisbox" may be set to "\pstree@outermode", the latter must reset "\pst@thisbox". % % Setting "\psk@predmode" to "\m@ne" is a useful flag for outer mode. \newif\ifpstree@outer \def\pstree@outermode{% \pstree@outertrue \let\pstree@makecanonical\pstree@makecanonical@outer \let\psnode@makecanonical\relax \let\pstree@build\pstree@build@outer \let\psk@predmode\m@ne \pstree@levelID=\z@ \chardef\pstree@maxlevel\z@ \let\pstree@themaxlevel\relax \def\pstree@id{outer}% \def\pst@tposflip{}% \let\pst@shortput\pstree@savedshortput \pstree@initnestedpar \let\pst@thisbox\relax} \let\pstree@savedshortput\pst@shortput \pstree@outermode % % This described the process for the canonical tree row object. % \def\pstree@treemode{% \let\pstree@makecanonical\pstree@makecanonical@succ \let\psnode@makecanonical\psnode@makecanonical@succ \let\pstree@build\pstree@build@succ \pstree@initnestedpar \global\pstree@succID=\@ne \gdef\psTREE@addtreesep{\z@}% \global\let\pstree@center\@empty \global\let\psTREE@centerbase\@empty \let\psk@predmode\psk@treemode \let\if@predflip\ifpstreeflip \let\pst@thisbox\pstree@outermode} % % First we actually skip the levels, if necessary. \def\pstree@build@succ{% \ifnum\psskiplevels>\z@ \pstree@skiplevels \fi % If "\pstree@succID=1", indicating that this is the first successor, the successor row dimensions are simply initialized. \ifnum\pstree@succID=\@ne \ifnum\psk@treerep>\@ne\copy\else\box\fi\pstree@box \pstree@initrowdim % Otherwise, "\pstree@fit" sets "\psTREE@sep" to the distance between the centers of the previous and current successors, sets "\psTREE@width" to the total distance from the center of the first to the last successor, and updates the profiles. Then we position the current succcessor. \else \pstree@fit \ifodd\psk@predmode \if@predflip\raise\else\lower\fi\psTREE@width sp \else \kern\if@predflip-\fi\psTREE@sep sp \fi \ifnum\psk@treerep>\@ne\copy\else\box\fi\pstree@box \pstree@UpdateRowDim \fi \ifodd\psk@predmode\else \pst@dimg=\pstree@width sp \kern\if@predflip-\fi\pst@dimg \fi % Now we update the row dimensions. \global\advance\pstree@succID\@ne} % % The first successor's dimensions become the row's dimensions. \def\pstree@initrowdim{% \global\let\psTREE@leftprofile\pstree@leftprofile \global\let\psTREE@rightprofile\pstree@rightprofile \global\let\psTREE@levelsizes\pstree@levelsizes \global\psTREE@height\pstree@height\relax \global\psTREE@depth\pstree@depth\relax \global\psTREE@width\pstree@width\relax \global\let\psTREE@maxtreesep\pstree@maxtreesep \global\let\psTREE@center\pstree@center \xdef\psTREE@numlevels{\the\pstree@numlevels}% \xdef\psTREE@cumlevelsep{\the\pstree@cumlevelsep}% \global\let\psTREE@leftbase\pstree@leftbase \global\let\psTREE@rightbase\pstree@rightbase \global\let\psTREE@centerbase\pstree@centerbase \global\let\psTREE@rootnodes\pstree@rootnodes \global\let\psTREE@basenodes\pstree@basenodes} % First we calculate the distance between successors: \def\pstree@fit{% %% I seem to have deleted the following lines for some reason at one point: \ifnum\psk@thistreenodesize<\z@ \let\pst@tempa\psTREE@rightprofile \let\pst@tempb\pstree@leftprofile \else \edef\pst@tempa{\pstree@puttop\psk@thistreenodesize\psTREE@rightprofile}% \edef\pst@tempb{\pstree@puttop\psk@thistreenodesize\pstree@leftprofile}% \fi \csname pstree@\psk@thistreefit fit\endcsname\pst@tempa\pst@tempb\psTREE@sep %% \csname pstree@\psk@thistreefit fit\endcsname %% \psTREE@rightprofile\pstree@leftprofile\psTREE@sep % Then we add the "treesep", the width of the new object, and any extra space inserted by "\addtreesep". \advance\psTREE@sep\psk@thistreesep\relax \ifnum\psTREE@maxtreesep<\psTREE@sep \xdef\psTREE@maxtreesep{\the\psTREE@sep}% \fi \advance\psTREE@sep\psTREE@addtreesep\relax \gdef\psTREE@addtreesep{\z@}% \global\advance\psTREE@width\psTREE@sep} % % Now we update the row's dimensions. \def\pstree@UpdateRowDim{% \ifnum\psTREE@maxtreesep<\pstree@maxtreesep\relax \let\psTREE@maxtreesep\pstree@maxtreesep \fi %\advance\psTREE@sep\psTREE@width %% TVZ Deleted 96-Oct-18. \pstree@zip\psTREE@sep \psTREE@rightprofile\pstree@rightprofile\psTREE@rightprofile \pstree@zip\psTREE@width \pstree@leftprofile\psTREE@leftprofile\psTREE@leftprofile \global\advance\psTREE@width\pstree@width \pstree@bimax\psTREE@levelsizes\pstree@levelsizes \ifnum\pstree@height>\psTREE@height \global\psTREE@height\pstree@height\relax \fi \ifnum\pstree@depth>\psTREE@depth \global\psTREE@depth\pstree@depth\relax \fi \ifx\pstree@center\@empty\else \pst@cntg=\psTREE@width \advance\pst@cntg\pstree@center \xdef\psTREE@center{\the\pst@cntg}% \fi \xdef\psTREE@rootnodes{\psTREE@rootnodes\pstree@rootnodes}% \ifnum\pstree@numlevels<\psTREE@numlevels\else \global\let\psTREE@rightbase\pstree@rightbase \ifx\pstree@centerbase\@empty\else \pst@cntg=\pstree@centerbase\relax \advance\pst@cntg\psTREE@width \xdef\psTREE@centerbase{\the\pst@cntg}% \fi \ifnum\pstree@numlevels>\psTREE@numlevels\relax \global\let\psTREE@basenodes\pstree@basenodes \xdef\psTREE@numlevels{\the\pstree@numlevels}% \xdef\psTREE@cumlevelsep{\the\pstree@cumlevelsep}% \pst@cntg=\pstree@leftbase\relax \advance\pst@cntg-\psTREE@width \xdef\psTREE@leftbase{\the\pst@cntg}% \else \xdef\psTREE@basenodes{\psTREE@basenodes\pstree@basenodes}% \fi \fi} % "\treecenter" just remembers the current width of the row of successors. \def\treecenter{\xdef\psTREE@center{\the\psTREE@width}} \def\addtreesep#1{% \pssetlength\pst@dimg{#1}% \xdef\psTREE@addtreesep{\number\pst@dimg}% \ignorespaces} % "\pstree@checkrow" checks that the row has at least one successor, and that the row doesn't have extraneous space. \def\pstree@checkrow{% \ifnum\pstree@succID=\@ne \pst@makelongbox \pstree@treemode \psroot{\box\pst@hbox}% \ifnum\pstree@succID=\@ne\Tn\fi \pst@endlongbox \fi \ifnum\wd\pst@hbox=% \ifodd\psk@treemode\z@\else\ifpstreeflip-\fi\psTREE@width\fi \else \@pstrickserr{Extraneous space in tree row (Level \the\pstree@levelID)}\@ehpa \fi \wd\pst@hbox=\z@ \ht\pst@hbox=\z@ \dp\pst@hbox=\z@} % % "\psk@treemode" and "\ifpstreeflip" are the successor tree's "treemode" and "treeflip", and "\psk@predmode" and "\if@predflip" are the successor tree's "treemode" and "treeflip". % Terminal nodes are made into single-level trees. Because \TeX\ is pretty fast at processing conditionals, this should not take so long. Good thing, because terminal nodes are pretty common! \def\psnode@makecanonical@succ{% \edef\pstree@height{% \number \ifcase\psk@predmode\pst@dimc\or\pst@dima\or\pst@dimd\or\pst@dimb\fi}% \edef\pstree@depth{% \number \ifcase\psk@predmode\pst@dimd\or\pst@dimb\or\pst@dimc\or\pst@dima\fi}% \edef\pstree@leftprofile{% \number \ifodd\psk@predmode \if@predflip\pst@dimd\else\pst@dimc\fi \else \if@predflip\pst@dimb\else\pst@dima\fi \fi,}% \edef\pstree@rightprofile{% \number \ifodd\psk@predmode \if@predflip\pst@dimc\else\pst@dimd\fi \else \if@predflip\pst@dima\else\pst@dimb\fi \fi,}% %\edef\pstree@levelsizes{\pstree@height,\pstree@depth,}% Moved below. \pstree@numlevels\@ne \pstree@cumlevelsep\z@ \chardef\pstree@width\z@ \let\pstree@center\@empty \def\pstree@leftbase{\z@}% \def\pstree@rightbase{\z@}% \let\pstree@centerbase\@empty \edef\pstree@rootnodes{\pssucc,}% \let\pstree@basenodes\pstree@rootnodes \def\pstree@maxtreesep{\z@}% %%%% FIX ME?? (also, xtreesep inserted between multiple skiplevel-nodes.) \ifnum\psskiplevels>\z@ \let\pstree@saveskiplevels\psskiplevels \pstree@skipprofile %\pstree@cumlevelsep\pstree@skiplevelsep\relax %%% Caused extra skipping. \pst@cntg=\pstree@depth \advance\pst@cntg\pstree@skiplevelsep\relax \edef\pstree@depth{\the\pst@cntg}% \ifnum\pstree@height>\pstree@cumlevelsep \pst@cntg=\pstree@height\relax \advance\pst@cntg-\pstree@cumlevelsep \edef\pstree@height{\the\pst@cntg}% \else \def\pstree@height{0}% \fi \let\psskiplevels\pstree@saveskiplevels \fi \edef\pstree@levelsizes{\pstree@height,\pstree@depth,}% Used to be above \ifPst@leafalign\pstree@alignleaf\fi} % The canonical successor is a subtree with the same orientation as the tree within which it is nested. Flipped trees of the same type are also easy. \def\pstree@makecanonical@succ{% \ifnum\psk@treemode=\psk@predmode \pstree@@makecanonical@succ % Subtrees of a different type are first converted to canonical outer objects (and in the process, the bounding box may be adjusted), and then they are converted to canonical successor objects as if they were nodes. This is not the most efficient, but such rotated subtrees are not so common. A direct conversion would be faster, but would still involve extensive macros. \else \pstree@makecanonical@outer \def\pssucc,{\pstree@rootnodes}% \psnode@makecanonical@succ \fi} % "\psk@treemode" and "\ifpstreeflip" are for the subtree. "\psk@predmode" and "\ifps@predflip" are for the predecessor tree. \def\pstree@@makecanonical@succ{% \ifx\psk@adjustbbox\@empty\else \@pstrickserr{You cannot adjust a proper subtree's bounding box}\@ehpa \let\psk@adjustbbox\relax \fi \ifx\ifpstreeflip\if@predflip\else \pstree@@@makecanonical@succ \fi \ifPst@showbbox \pstree@gettreebbox \fi} \def\pstree@@@makecanonical@succ{% \let\pst@tempg\pstree@leftprofile \let\pstree@leftprofile\pstree@rightprofile \let\pstree@rightprofile\pst@tempg \let\pst@tempg\pstree@leftbase \let\pstree@leftbase\pstree@rightbase \let\pstree@rightbase\pst@tempg \ifnum\pstree@width=\z@\else \pst@dimg=\pstree@width sp \multiply\pst@dimg\m@ne \ifodd\psk@treemode \setbox\pstree@box=\hbox{\raise\pst@dimg\box\pstree@box}% \else \setbox\pstree@box=\hbox to \pst@dimg{% \kern\pst@dimg\unhbox\pstree@box\hss}% \fi \fi \ifx\pstree@center\@empty\else \pst@cntg\pstree@width \advance\pst@cntg-\pstree@center\relax \edef\pstree@center{\the\pst@cntg}% \fi} % The first successor's dimensions become the row's dimensions. \def\pstree@InitTreeDim{% \setbox\pstree@box\box\pst@hbox \let\pstree@leftprofile\psTREE@leftprofile \let\pstree@rightprofile\psTREE@rightprofile \let\pstree@levelsizes\psTREE@levelsizes \edef\pstree@height{\the\psTREE@height}% \edef\pstree@depth{\the\psTREE@depth}% \edef\pstree@width{\the\psTREE@width}% \let\pstree@maxtreesep\psTREE@maxtreesep \let\pstree@center\psTREE@center \pstree@numlevels\psTREE@numlevels\relax \pstree@cumlevelsep\psTREE@cumlevelsep\relax \let\pstree@leftbase\psTREE@leftbase \let\pstree@rightbase\psTREE@rightbase \let\pstree@centerbase\psTREE@centerbase \let\pstree@rootnodes\psTREE@rootnodes \let\pstree@basenodes\psTREE@basenodes} % % After a row has been processed, the left profiles are with respect to the center of the leftmost toplevel node, the right profiles are with respect to the center of the rightmost toplevel node, and "\psTREE@width" is the distance between the centers of the two extreme toplevel nodes. The row box's current point is the center of the leftmost toplevel node. That is, it is a tree! The previous rows have also been joined into a tree. Here is how we join two trees together, one on top of the other. % Fist, we calculate the distance between the current point of the previous rows and the current point of the next row. We are matching the center of the base of the top row with the center of the root of the bottom row. % "\pstree@setsucccenter" shifts the row's current point to the row's true center (either the midpoint between the two extreme successors or distance "\pstree@center" from the leftmost successor, adjusted by "treeshift"), and then adjust the profiles so that they are with respect to this center. % % First, find the distance from the left successor to the center, for the top of the bottom row. \def\pstree@joinrows{% \ifnum\pstree@succID=\tw@ \csname pstree@unarycenter@\psk@thisunary\endcsname \else \ifx\psTREE@center\@empty \pst@cnta\psTREE@width \divide\pst@cnta\tw@ \else \pst@cnta\psTREE@center\relax \fi \fi \advance\pst@cnta\psk@treeshift\relax % Now do the same for bottom of the top row: \ifx\pstree@centerbase\@empty \psTREE@sep\pstree@leftbase \multiply\psTREE@sep\m@ne \advance\psTREE@sep\pstree@rightbase \advance\psTREE@sep\pstree@width \divide\psTREE@sep\tw@ \else \psTREE@sep\pstree@centerbase\relax \fi % Now find the distance between the current points, after alignment: \advance\psTREE@sep-\pst@cnta % Join the rows: \advance\pstree@cumlevelsep\psk@thislevelsep\relax \ifodd\psk@treemode \setbox\pstree@box=\hbox{% \box\pstree@box \kern\ifnum\psk@treemode=\thr@@-\fi\pstree@cumlevelsep sp \ifpstreeflip\raise\else\lower\fi\psTREE@sep sp\box\pst@hbox}% \else \setbox\pstree@box=\hbox{% \box\pstree@box \kern\ifpstreeflip-\fi\psTREE@sep sp \ifnum\psk@treemode=\z@\lower\else\raise\fi\pstree@cumlevelsep sp \box\pst@hbox}% \fi \wd\pstree@box=\z@ \ht\pstree@box=\z@ \dp\pstree@box=\z@} % Adjust the profiles. \def\pstree@joinprofiles{% \ifnum\psskiplevels>\z@ \pstree@skiprowprofiles \fi \pst@cnta=-\psTREE@sep \pstree@add\pst@cnta\psTREE@leftprofile \advance\pst@cnta\psTREE@leftbase \edef\pstree@leftbase{\the\pst@cnta}% \edef\pstree@leftprofile{\pstree@leftprofile\psTREE@leftprofile}% \ifx\psTREE@centerbase\@empty\else \pst@cnta=\psTREE@sep \advance\pst@cnta\psTREE@centerbase \edef\pstree@centerbase{\the\pst@cnta}% \else \let\pstree@centerbase\@empty \fi \advance\psTREE@width-\pstree@width \advance\psTREE@width\psTREE@sep \pstree@add\psTREE@width\psTREE@rightprofile \edef\pstree@rightprofile{\pstree@rightprofile\psTREE@rightprofile}% \advance\psTREE@width\psTREE@rightbase \edef\pstree@rightbase{\the\psTREE@width}% \edef\pstree@levelsizes{% \pstree@levelsizes\psk@thislevelsep,\psTREE@levelsizes}% % Then we calculate the resulting height and depth of the tree. \advance\psTREE@height-\pstree@cumlevelsep \ifnum\pstree@height<\psTREE@height \edef\pstree@height{\the\psTREE@height}% \fi \advance\psTREE@depth\pstree@cumlevelsep \ifnum\pstree@depth<\psTREE@depth \edef\pstree@depth{\the\psTREE@depth}% \fi \advance\pstree@numlevels\psTREE@numlevels\relax \let\pstree@basenodes\psTREE@basenodes} \def\pstree@skiprowprofiles{% \pst@cntc-\psTREE@sep \pst@cntd\pstree@leftbase\relax \advance\pst@cntc-\pst@cntd \pst@cnta\psTREE@width \advance\pst@cnta\psTREE@sep \advance\pst@cnta-\pstree@width \pst@cntb=\pstree@rightbase \advance\pst@cnta-\pst@cntb \pst@cntg\psskiplevels \advance\pst@cntg\@ne \divide\pst@cntc\pst@cntg \divide\pst@cnta\pst@cntg \loop \advance\pst@cntd\pst@cntc \advance\pst@cntb\pst@cnta \edef\pstree@leftprofile{\pstree@leftprofile\the\pst@cntd,}% \edef\pstree@rightprofile{\pstree@rightprofile\the\pst@cntb,}% \ifnum\pst@cntg>\tw@ \advance\pst@cntg\m@ne \repeat} \def\pstree@unarycenter@middle{\pst@cnta=\z@} \def\pstree@unarycenter@left{% \pst@cnta\psk@thistreesep\relax \divide\pst@cnta\tw@ \advance\pst@cnta \ifnum\psk@thistreenodesize<\z@ \pstree@gettop\psTREE@rightprofile \else \psk@thistreenodesize \fi \relax}% \def\pstree@unarycenter@right{% \pst@cnta\psk@thistreesep\relax \divide\pst@cnta\tw@ \advance\pst@cnta \ifnum\psk@thistreenodesize<\z@ \pstree@gettop\psTREE@leftprofile \else \psk@thistreenodesize \fi \multiply\pst@cnta\m@ne}% \def\pstree@unarycenter@leftternary{% \pst@cnta=% \ifnum\psk@thistreenodesize<\z@ \pstree@gettop\psTREE@rightprofile \else \psk@thistreenodesize \fi \multiply\pst@cnta\tw@ \advance\pst@cnta\psk@thistreesep\relax}% \def\pstree@unarycenter@rightternary{% \pst@cnta=% \ifnum\psk@thistreenodesize<\z@ \pstree@gettop\psTREE@leftprofile \else \psk@thistreenodesize \fi \multiply\pst@cnta\tw@ \advance\pst@cnta\psk@thistreesep \multiply\pst@cnta\m@ne}% \define@key[psset]{pst-tvz}{unary}[middle]{% \@ifundefined{pstree@unarycenter@#1}% {\@pstrickserr{Bad unary parameter: `#1'}\@ehpa}% {\def\psk@unary{#1}}} \psset[pst-tvz]{unary=middle} \define@key[psset]{pst-tvz}{thisunary}[middle]{% \@ifundefined{pstree@unarycenter@#1}% {\@pstrickserr{Bad unary parameter: `#1'}\@ehpa}% {\def\psk@thisunary{#1}}} \newpsobject{psltree}{pstree}{thisunary=left} \newpsobject{psrtree}{pstree}{thisunary=right} \def\pstree@checkskiplevels#1skiplevels=#2,#3\@nil{% \chardef\psskiplevels#2\relax} \def\pstree@skipprofile{% \ifnum\psk@predmode=\m@ne \@pstrickserr{You can only skip levels in the successors of a tree}\@ehpa \else \pst@cnta=\psskiplevels \pst@cntb=\z@ \def\pstree@skiplevelsizes{}% \def\pstree@skiplevelprofiles{}% \pstree@@skipprofile \edef\pstree@skiplevelsep{\the\pst@cntb}% \fi} \def\pstree@@skipprofile{% \advance\pstree@levelID\@ne \csname pstreehook\romannumeral\pstree@levelID\endcsname \ifPst@varlevelsep \pstree@adjustlevelsep \fi \edef\pstree@skiplevelsizes{\pstree@skiplevelsizes\psk@thislevelsep,0,0}% \edef\pstree@skiplevelprofiles{0,\pstree@skiplevelprofiles}% \advance\pst@cntb\psk@thislevelsep\relax \pstree@initnestedpar \advance\pst@cnta\m@ne \ifnum\pst@cnta>\z@ \expandafter\pstree@@skipprofile \fi} \def\pstree@skiplevels{% \ifx\pstree@center\@empty \pst@cnta\pstree@width \divide\pst@cnta\tw@ \else \pst@cnta\pstree@center\relax \fi \advance\pstree@cumlevelsep\pstree@skiplevelsep\relax \ifodd\psk@treemode \setbox\pstree@box=\hbox{% \kern\ifnum\psk@treemode=\thr@@-\fi\pstree@skiplevelsep sp \ifpstreeflip\lower\else\raise\fi\pst@cnta sp\box\pstree@box}% \else \setbox\pstree@box=\hbox{% \kern\ifpstreeflip-\fi\pst@cnta sp \ifnum\psk@treemode=\z@\lower\else\raise\fi\pstree@skiplevelsep sp \box\pstree@box}% \fi \wd\pstree@box=\z@ \ht\pstree@box=\z@ \dp\pstree@box=\z@ % Left profiles \ifnum\pst@cnta=\z@\else\pstree@add\pst@cnta\pstree@leftprofile\fi \pst@cntb\pstree@leftbase \advance\pst@cntb\pst@cnta \edef\pstree@leftbase{\the\pst@cntb}% \edef\pstree@leftprofile{\pstree@skiplevelprofiles\pstree@leftprofile}% \ifx\pstree@centerbase\@empty\else \pst@cntb\pstree@centerbase \advance\pst@cntb-\pst@cnta \edef\pstree@centerbase{\the\pst@cntb}% \fi \pst@cntb\pstree@width \advance\pst@cntb-\pst@cnta \ifnum\pst@cntb=\z@\else\pstree@add\pst@cntb\pstree@rightprofile\fi \edef\pstree@rightprofile{\pstree@skiplevelprofiles\pstree@rightprofile}% \advance\pst@cntb\pstree@rightbase \edef\pstree@rightbase{\the\pst@cntb}% \edef\pstree@levelsizes{\pstree@skiplevelsizes\pstree@levelsizes}% \ifnum\pstree@height>\pstree@skiplevelsep\relax \pst@cntb\pstree@skiplevelsep\relax \multiply\pst@cntb\m@ne \advance\pst@cntb\pstree@height \edef\pstree@height{\the\pst@cntb}% \else \def\pstree@height{\z@}% \fi \advance\pstree@numlevels\psskiplevels \def\pstree@width{0}% \def\pstree@center{}} % \def\pstree@initauxout{% \@ifundefined{@latexerr}{% \immediate\openin1 \jobname.pst \ifeof1 \else {\catcode`\@=11 \input \jobname.pst}% \fi \immediate\closein1 \global\csname newwrite\endcsname\pstree@auxout \immediate\openout\pstree@auxout \jobname.pst }% {\global\let\pstree@auxout\@auxout}% \global\let\pstree@initauxout\relax} \def\pstree@writelevelsizes{% \ifx\if@filesw\iffalse\else \pstree@getlevelsizes \immediate\write\pstree@auxout{% \string\global\string\@namedef{pstree@levelsizes@\pstree@id}% {\pst@tempg}}% \fi} \def\pstree@getlevelsizes{% \def\pst@tempg{}% \expandafter\pstree@@getlevelsizes\psTREE@levelsizes\relax} \def\pstree@@getlevelsizes#1,#2,#3,#4,#5,#6{% \pst@cntg=#2\relax \advance\pst@cntg#4\relax \edef\pst@tempg{\pst@tempg\the\pst@cntg,}% \ifx\relax#6\else \def\next{\pstree@@getlevelsizes,#5,#6}% \expandafter\next \fi} \def\pstree@initadjustlevelsep{% \pstree@initauxout \expandafter\let\expandafter\pstree@thelevelsizes \csname pstree@levelsizes@\pstree@id\endcsname \ifx\pstree@thelevelsizes\relax \def\pstree@thelevelsizes{0,}% \fi} \def\pstree@adjustlevelsep{% \pstree@poptop\pstree@thelevelsizes\pst@cntg \advance\pst@cntg\psk@thislevelsep\relax \edef\psk@thislevelsep{\the\pst@cntg}} % Call a tree whose terminal nodes should be aligned at the bottom of the tree a ``LeafAlign'' tree. % % In a LeafAlign tree, terminal nodes should align themselves by skipping levels, whenever "leafalign" is "true". The LeafAlign tree sets "\pstree@themaxlevel" to the number of the lowest level in the tree. When "leafalign" is "true", terminal nodes in the LeafAlign tree skip enough levels so that they end up at level "\pstree@themaxlevel". % % Setting "leafalign=true" has two effects. First, subsequent nodes take care of skipping levels. Second, top level tree or trees in the scope of the parameter setting become LeafAlign trees. "\psset@leafalign" sets "\if@leafaligntree" to "\iftrue", and this is reset to "\iffalse" by "\pstree@initnestedpar". \newif\ifPst@leafalign \define@key[psset]{pst-tvz}{leafalign}[true]{% \@nameuse{leafalign#1}% \let\if@leafaligntree\ifPst@leafalign}% \psset[pst-tvz]{leafalign=false} % This is invoked by "\psnode@makecanonical@succ" (i.e., by terminal nodes), when "leafalign" is true. % % We keep track of the number of the lowest level in a tree with "\pstree@maxlevel". This is set with "\chardef". % % The the terminal node skips as many levels as are needed. \def\pstree@alignleaf{% \ifnum\pstree@maxlevel<\pstree@levelID \global\chardef\pstree@maxlevel\pstree@levelID \fi \ifx\pstree@themaxlevel\relax\else \ifnum\psskiplevels>\z@\else \ifnum\pstree@themaxlevel>\pstree@levelID \pst@cntg=\pstree@themaxlevel \advance\pst@cntg-\pstree@levelID \chardef\psskiplevels\pst@cntg \pstree@saveskiplevels\psskiplevels \pstree@skipprofile \let\psskiplevels\pstree@saveskiplevels \fi \fi \fi} % When a LeafAlign tree finishes processing its successors, it writes "\pstree@maxlevel" to a file. \def\pstree@writemaxlevel{% \ifx\if@filesw\iffalse\else \immediate\write\pstree@auxout{% \string\global\string\@namedef{pstree@maxlevel@% \pstree@id-\the\pstree@levelID-\the\pstree@succID}% {\the\pstree@maxlevel}}% \fi} % Before processing its successors, a LeafAlign tree looks for the value of "\pstree@maxlevel" that it might have written to the file, and assigns the value to "\pstree@themaxlevel": \def\pstree@initleafalign{% \pstree@initauxout \expandafter\let\expandafter\pstree@themaxlevel \csname pstree@maxlevel@% \pstree@id-\the\pstree@levelID-\the\pstree@succID \endcsname % If "\pstree@themaxlevel" is equal to "\relax", then terminal nodes know that they should not try to align themselves. % % Then tree A needs to initialize "\pstree@maxlevel". \global\chardef\pstree@maxlevel\pstree@levelID} % "\pstree@maxlevel" is set globally. A LeafAlign tree should not pay attention to levels in a subtrees that (i) change directions, (ii) are root trees, or (iii) are LeafAlign trees. Such trees save the value of "\pstree@maxlevel" as "\pstree@savemaxlevel", and then restore the value globally at the end. Here, we just initialize it: \let\pstree@savemaxlevel\z@ \let\pstree@frame\relax % This one is not working. For one thing, "\pstree@getbbox" is not defined. \def\pstreeframe{\pst@object{pstreeframe}} \def\pstreeframe@i{% \let\pstree@theframe\pstreeframe@ii \let\pstree@theframepar\pst@par \let\pstree@theframestar\if@star} \def\pstreeframe@ii{% \pstree@getbbox \pst@dimg\pslinewidth \advance\pst@dimg\psframesep \advance\pst@dima\pst@dimg \advance\pst@dimb\pst@dimg \advance\pst@dimc\pst@dimg \advance\pst@dimd\pst@dimg \setbox\pstree@box=\hbox{% \let\pst@par\pstree@theframepar \let\if@star\pstree@theframestar \pst@useboxpar \ifpsboxsep\aftergroup\pstreeframe@iii\fi \def\psk@dimen{.5 }% \psframe@i(-\pst@dima,-\pst@dimd)(\pst@dimb,\pst@dimc)% \box\pstree@box}% \aftergroup\pstree@relaxtheframe}% \def\pstreeframe@iii{% \ifodd\psk@treemode \pst@cntg=\pst@dimc \pstree@set\pstree@upprofile \pst@cntg=\pst@dimd \pstree@set\pstree@downprofile \else \pstree@add\pst@dima\pstree@leftprofile \pstree@add\pst@dimb\pstree@rightprofile \fi} \def\pstree@relaxtheframe{\let\pstree@theframe\relax} \let\pstree@theframe\relax % "\pstree@firstandlast{}{}{}" assigns the first and last values in to and , respectively. \def\pstree@firstandlast#1#2#3{% \expandafter\pstree@@firstandlast\expandafter#2#1\relax,% #3=\pst@cntg} \def\pstree@@firstandlast#1#2,{% \pst@cntg=#2\relax #1=\pst@cntg \pstree@@@firstandlast} \def\pstree@@@firstandlast#1,{% \ifx\relax#1\else \pst@cntg=#1\relax \expandafter\pstree@@@firstandlast \fi} % This so far does nothing useful. \def\pstreecurve{\pst@object{pstreecurve}} \def\pstreecurve@i{% \let\pstree@frame\pstreecurve@ii \let\pstree@theframepar\pst@par \let\pstree@theframestar\if@star} \def\pstreecurve@ii{% \setbox\pstree@box=\hbox{% \let\pst@par\pstree@theframepar \let\if@star\pstree@theframestar \pst@useboxpar \ifpsboxsep\aftergroup\pstreecurve@iv\fi \pstreecurve@iii \box\pstree@box}% \aftergroup\pstree@relaxtheframe}% \def\pstreecurve@iii{% \begin@ClosedObj \pst@dimg\pslinewidth \divide\pst@dimg2 \advance\pst@dimg\psframesep \ifodd\psk@treemode\pstreecurve@hcoor\else\pstreecurve@vcoor\fi \addto@pscode{[ \pst@coors}% \psccurve@ii} \def\pstreecurve@iv{% \pst@cnta=\pslinewidth \advance\pst@cnta\psframesep \ifodd\psk@treemode \pstree@add\pst@cnta\pstree@upprofile \pstree@add\pst@cnta\pstree@downprofile \else \pstree@add\pst@cnta\pstree@leftprofile \pstree@add\pst@cnta\pstree@rightprofile \fi} \def\pstreecurve@hcoor{% \advance\pst@dima\pst@dimg \advance\pst@dimb\pst@dimg \ifnum\psk@treemode=\@ne \pstree@firstandlast\pstree@upprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@upprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@number\pst@dima neg \pst@number\pst@dimh}% \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@coors \pst@number\pst@dimb \pst@number\pst@dimh}% \ifnum\psk@treemode=\@ne \pstree@firstandlast\pstree@downprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@downprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{% \pst@coor \pst@number\pst@dimb \pst@number\pst@dimh neg }% \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{% \pst@coors \pst@number\pst@dima neg \pst@number\pst@dimh neg }}% \def\pstreecurve@vcoor{% \advance\pst@dimc\pst@dimg \advance\pst@dimd\pst@dimg \ifnum\psk@treemode=\z@ \pstree@firstandlast\pstree@leftprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@leftprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@number\pst@dimh neg \pst@number\pst@dimc}% \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{% \pst@coors \pst@number\pst@dimh neg \pst@number\pst@dimd neg }% \ifnum\psk@treemode=\z@ \pstree@firstandlast\pstree@rightprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@rightprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@coors \pst@number\pst@dimh \pst@number\pst@dimd neg }% \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@coors \pst@number\pst@dimh \pst@number\pst@dimc}} % This seems to do nothing. \def\pstreepyramid{\pst@object{pstreepyramid}} \def\pstreepyramid@i{% \let\pstree@frame\pstreepyramid@ii \let\pstree@theframepar\pst@par \let\pstree@theframestar\if@star} \def\pstreepyramid@ii{% \setbox\pstree@box=\hbox{% \let\pst@par\pstree@theframepar \let\if@star\pstree@theframestar \pst@useboxpar %\ifpsboxsep\aftergroup\pstreepyramid@iv\fi \pstreepyramid@iv \pstreepyramid@iii \box\pstree@box}% \aftergroup\pstree@relaxtheframe}% \def\pstreepyramid@iii{% \begin@ClosedObj \pst@dimg\pslinewidth \advance\pst@dimg\psframesep \ifodd\psk@treemode\pstreepyramid@hcoor\else\pstreepyramid@vcoor\fi \addto@pscode{[ \pst@tempg \pst@temph }% \pspolygon@ii} \def\pstreepyramid@iv{% \pst@cnta=\pslinewidth \advance\pst@cnta\psframesep \ifodd\psk@treemode \pstree@add\pst@cnta\pstree@upprofile \pstree@add\pst@cnta\pstree@downprofile \else \pstree@add\pst@cnta\pstree@leftprofile \pstree@add\pst@cnta\pstree@rightprofile \fi} \def\pstreepyramid@hcoor{% \def\pst@tempg{}% \def\pst@temph{}% \pst@dima=\z@ \pst@dimg=\pst@cntg sp \edef\next{% \pstree@levelsizes\relax \pstree@upprofile\relax \pstree@downprofile\relax}% \expandafter\pstreepyramid@@hcoor\next} \def\pstreepyramid@@hcoor#1,#2,#3,#4\relax#5,#6\relax#7,#8\relax{% \pst@dimc=#5sp \pst@dimd=#7sp \pst@dimd=-\pst@dimd \pst@dimb=#1sp \advance\pst@dimb\pst@dimg \pst@dimb=-\pst@dimb \advance\pst@dimb\pst@dima \edef\pst@tempg{\pst@tempg \pst@number\pst@dimb \pst@number\pst@dimc}% \edef\pst@temph{\pst@number\pst@dimb \pst@number\pst@dimd \pst@temph}% \pst@dimb=#2sp \advance\pst@dimb\pst@dimg \advance\pst@dimb\pst@dima \edef\pst@tempg{\pst@tempg \pst@number\pst@dimb \pst@number\pst@dimc}% \edef\pst@temph{\pst@number\pst@dimb \pst@number\pst@dimd \pst@temph}% \ifx\relax#1% \let\next\relax \else \pst@dimb=#3sp \advance\pst@dima\ifnum\psk@treemode=\@ne\else-\fi\pst@dimb \def\next{\pstreepyramid@@hcoor#4\relax#6\relax#8\relax}% \fi \next} \def\pstreepyramid@vcoor{% \advance\pst@dimc\pst@dimg \advance\pst@dimd\pst@dimg \ifnum\psk@treemode=\z@ \pstree@firstandlast\pstree@leftprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@leftprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@number\pst@dimh neg \pst@number\pst@dimc}% \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{% \pst@coors \pst@number\pst@dimh neg \pst@number\pst@dimd neg }% \ifnum\psk@treemode=\z@ \pstree@firstandlast\pstree@rightprofile\pst@cnta\pst@cntb \else \pstree@firstandlast\pstree@rightprofile\pst@cntb\pst@cnta \fi \pst@dimh=\pst@cntb sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@coors \pst@number\pst@dimh \pst@number\pst@dimd neg }% \pst@dimh=\pst@cnta sp \advance\pst@dimh\pst@dimg \edef\pst@coors{\pst@coors \pst@number\pst@dimh \pst@number\pst@dimc}} % The following applies to nodes that have a successor: % % There are two edge macros. "\psedge" is invoked following each node, except when there is a skipped level between the node and its predecessor, in which case "\skipedge" is invoked. "\psedge" and "\skipedge" can be set by the "edge" and "skipedge" parameters. Setting these parameters for a node should affect the edge drawn to that node, but other parameter changes to a node should not affect the way the edge is drawn. % To reconcile these two goals, after setting its graphics parameters, a node lets "\pstree@edge" be "\psedge" (or If levels are skipped, it lets "\pstree@skipedge" be "\psedge" and lets "\pstree@edge" be "\skipedge"). Then the node closes the group and invokes "\pstree@edge". % \define@key[psset]{pst-tvz}{edge}[\ncline]{\def\psedge{#1}}% \psset[pst-tvz]{edge=\ncline} % \define@key[psset]{pst-tvz}{skipedge}[{}]{% \def\skipedge{#1}% \ifx\skipedge\@empty \def\skipedge{\psedge}% \else \ifx\skipedge\@none \def\skipedge##1##2{}% \fi \fi} \psset[pst-tvz]{skipedge={}} % % Each node sets "\pssucc" to "@T:\pstree@id:\the\pstree@levelID". This does not give every node a unique name, but a nodes name will never be overwritten until it is not needed. % % Here, we only initialize "\pspred", in case it is used inadvertently. \def\pspred{@T} % % For each of the PSTricks node commands, there should be a variant for trees % % "\begin@treenode" takes care of steps \ref{bbt}--\ref{ebt}. "\end@treenode" takes care of steps \ref{bet}--\ref{eet}. A tree node typically invokes "\begin@treenode", takes care of steps \ref{dn1} and \ref{dn2}, and then invokes "\end@treenode". If the tree makes "\pst@hbox", then it must first invoke "\pst@@killglue". \def\begin@treenode{% \pst@@killglue \begingroup \use@par \xdef\pssucc{@T:\pstree@id:\the\pstree@levelID:\the\pstree@succID}} % \def\end@@treenode{% \psk@adjustbbox \ifPst@showbbox\pstree@showbbox\fi \psnode@makecanonical \pstree@build \ifnum\psskiplevels>\z@ \global\let\pstree@skipedge\psedge \global\let\pstree@edge\skipedge \else \global\let\pstree@edge\psedge \fi \endgroup \let\pst@tempa\ignorespaces \ifnum\pstree@levelID>\z@ \ifx\pstree@edge\@none\else \let\pst@tempa\pst@shortput \expandafter\pstree@makeedge\pstree@basenodes\relax\@empty \fi \fi \pst@tempa} % \def\pstree@makeedge#1,#2#3\@empty{% {\pstree@edge{#1}{\pssucc}}% \ifx#2\relax\else\let\pst@tempa\ignorespaces\expandafter\pstree@makeedge\fi #2#3\@empty} % % "\Tn" is the exception. Because it is just a place holder, it sets "\pssucc" to "\pspred", and does not make an edge. \def\Tn{\pst@object{Tn}} \def\Tn@i{% \pst@@killglue \global\let\pssucc\pspred \begingroup \pst@dima=\z@ \pst@dimb=\z@ \pst@dimc=\z@ \pst@dimd=\z@ \setbox\pstree@box=\hbox{}% \psnode@makecanonical \pstree@build \endgroup \ignorespaces} \def\Tp{\pst@object{Tp}} \def\Tp@i{% \begin@treenode \pst@dima=\z@ \pst@dimb=\z@ \pst@dimc=\z@ \pst@dimd=\z@ \setbox\pstree@box=\hbox{% \pst@newnode{\pssucc}{10}{0 0 }{\tx@InitPnode}}% \end@treenode} \def\Tc{\pst@object{Tc}} \def\Tc@i#1{% \begin@treenode \pssetlength\pst@dima{#1}% \pst@dimb=\pst@dima \pst@dimc=\pst@dima \pst@dimd=\pst@dima \Pst@nodealignfalse \setbox\pstree@box=\hbox{\cnode@ii(\z@,\z@){#1}{\pssucc}}% \end@treenode} \def\TC{\pst@object{TC}} \def\TC@i{\Tc@i{\psk@radius}} \def\Toval{\pst@object{Toval}} \def\Toval@i{\pst@@killglue\pst@makebox{\Toval@ii\ovalnode@ii}} \def\Toval@ii#1{% \begin@treenode \Pst@nodealigntrue \setbox\pstree@box=\hbox{#1\pssucc}% \pst@dima=\wd\pstree@box \divide\pst@dima\tw@ \pst@dimb=\pst@dima \pst@dimc=\ht\pstree@box \pst@dimd=\dp\pstree@box \setbox\pstree@box=\hbox to\z@{\hss\unhbox\pstree@box\hss}% \dp\pstree@box=\z@ \ht\pstree@box=\z@ \end@treenode} \def\Tcircle{\pst@object{Tcircle}} \def\Tcircle@i{\pst@@killglue\pst@makebox{\Toval@ii\circlenode@ii}} \def\TCircle{\pst@object{TCircle}} \def\TCircle@i{\pst@@killglue\pst@makebox{\Toval@ii\Circlenode@ii}} \def\Tf{\pst@object{Tf}} \def\Tf@i{\Toval@ii{\fnode@ii()}} \def\Tdia{\pst@object{Tdia}} \def\Tdia@i{\pst@@killglue\pst@makebox{\Toval@ii\dianode@ii}} \def\Ttri{\pst@object{Ttri}} \def\Ttri@i{\pst@@killglue\pst@makebox{\Ttri@ii}} \def\Ttri@ii{% \begin@treenode \Pst@nodealigntrue \setbox\pstree@box=\hbox{\trinode@ii\pssucc}% \pst@dima=\pst@dimg % Set by \pst@triboxsep \pst@dimb=\wd\pstree@box \advance\pst@dimb-\pst@dima \pst@dimc=\ht\pstree@box \pst@dimd=\dp\pstree@box \setbox\pstree@box=\hbox to\z@{\hss\unhbox\pstree@box\hss}% \dp\pstree@box=\z@ \ht\pstree@box=\z@ \end@treenode} \def\Tr{\pst@object{Tr}} \def\Tr@i{\pst@@killglue\pst@makebox{\Tr@ii{\rnode@iii\rnode@iv}}} \def\Tr@ii#1{% \begin@treenode \def\pstree@nodehook{% \xdef\pstree@next{\pst@dima=\number\pst@dima sp\relax}}% \Pst@nodealigntrue \setbox\pstree@box\hbox{#1\pssucc}% \pstree@next \pst@dimb=\wd\pstree@box \advance\pst@dimb-\pst@dima \pst@dimc=\ht\pstree@box \pst@dimd=\dp\pstree@box \setbox\pstree@box\hbox to\z@{\kern-\pst@dima\unhbox\pstree@box\hss}% \ht\pstree@box=\z@ \dp\pstree@box=\z@ \end@treenode} \def\TR{\pst@object{TR}} \def\TR@i{\pst@@killglue\pst@makebox{\Tr@ii{\rnode@iii\Rnode@ii}}} \def\Tdot{\pst@object{Tdot}} \def\Tdot@i{% \begin@treenode \def\pstree@nodehook{\xdef\pstree@next{% \pst@dima=\number\pst@dimg sp\relax \pst@dimc=\number\pst@dimh sp\relax}}% \Pst@nodealignfalse \setbox\pstree@box=\hbox{\dotnode@ii(\z@,\z@)\pssucc}% \pstree@next \pst@dimb=\pst@dima \pst@dimd=\pst@dimc \end@treenode} \define@key[psset]{pst-tvz}{fansize}[1cm]{\pst@@getlength{#1}\psk@fansize} \psset[pst-tvz]{fansize=1cm} % % DEFINITION OF Tfan IS IN psn-beta.doc. % \def\Tfan{\pst@object{Tfan}} \def\Tfan@i{% \addto@par{edge=none,skipedge=none}% \begin@treenode \solid@star % For now, let \pst@dimb and \pst@dimd base and thickness of fan. \pst@dimb=\psk@fansize \pst@dimd=\pslinewidth \advance\pst@dimb-\pst@dimd \divide\pst@dimb 2 \divide\pst@dimd 2 % Set \pst@dima and \pst@dimc to leftsize and height of node \ifodd\psk@treemode \pst@dima=\pst@dimd \pst@dimc=\pst@dimb \else \pst@dima=\pst@dimb \pst@dimc=\pst@dimd \fi \setbox\pstree@box=\hbox{% \pst@newnode{\pssucc}{16}{}{% /Y 0 def /X 0 def /l \pst@number\pst@dima def /r l def /u \pst@number\pst@dimc def /d u def /NodePos { \tx@GetRnodePos } def}% \def\pst@linetype{1}% \nc@object{Closed}{\pspred}{\pssucc}{.5}{% tx@Dict begin \psline@iii pop end /w \pst@number\pst@dimb CLW 2 div sub def /m \ifodd\psk@treemode false \else true \fi def \tx@Tfan}}% \pst@dimb=\pst@dima \pst@dimd=\pst@dimc \end@treenode} \define@key[psset]{pst-tvz}{tnsep}[{}]{% \def\pst@tempg{#1}% \ifx\pst@tempg\@empty \def\psk@tnsep{\number\pslabelsep sp}% \else \pst@@getlength{#1}\psk@tnsep \fi} \psset[pst-tvz]{tnsep={}} \define@key[psset]{pst-tvz}{tnyref}[{}]{\def\psk@tnyref{#1}}% \psset[pst-tvz]{tnyref={}} \define@key[psset]{pst-tvz}{tnheight}[\ht\strutbox]{\def\psk@tnheight{#1}} \psset[pst-tvz]{tnheight=\ht\strutbox} \define@key[psset]{pst-tvz}{tndepth}[\dp\strutbox]{\def\psk@tndepth{#1}} \psset[pst-tvz]{tndepth=\dp\strutbox} \define@key[psset]{pst-tvz}{tnpos}[{}]{% \def\pst@tempg{#1}% \ifx\pst@tempg\@empty \def\psk@tnpos{% \ifcase\psk@treemode b\or r\or a\or l\fi}% \else \@ifundefined{pstree@tnput@#1}% {\@pstrickserr{Bad tnpos: `#1'}\@ehpa}% {\def\psk@tnpos{#1}}% \fi} \psset[pst-tvz]{tnpos={}} % \def\MakeShortTnput#1{% \def\end@treenode{\@ifnextchar#1{\tnput@}{\end@@treenode}}} \MakeShortTnput{~} \def\tnput@#1{\pst@object{tnput}} \def\tnput@i{\pst@@killglue\pst@makebox{\tnput@ii}} \def\tnput@ii{% \begingroup \use@par \if@star\pst@starbox\fi \gdef\next{}% \csname pstree@tnput@\psk@tnpos\endcsname \endgroup \next \setbox\pstree@box=\box\pst@boxg \dp\pstree@box=\z@ \ht\pstree@box=\z@ \wd\pstree@box=\z@ \end@treenode} \@namedef{pstree@tnput@b}{% \pstree@tnput@@v\pst@dimd\ht\dp\lower\psk@tnheight} \@namedef{pstree@tnput@a}{% \pstree@tnput@@v\pst@dimc\dp\ht\raise\psk@tndepth} \def\pstree@tnput@@v#1#2#3#4#5{% \pst@dimh=\wd\pst@hbox \pst@dimg=\psk@href\pst@dimh \advance\pst@dimg\pst@dimh \divide\pst@dimg 2 \advance\pst@dimh-\pst@dimg \ifdim\pst@dimg>\pst@dima \xdef\next{\next\pst@dima=\number\pst@dimg sp\relax}% \fi \ifdim\pst@dimh>\pst@dimb \xdef\next{\next\pst@dimb=\number\pst@dimh sp\relax}% \fi \pst@dimh=\psk@tnsep\relax \ifdim\pst@dimh<\z@ \pst@dimh=-\pst@dimh \else \advance\pst@dimh#1% \fi \pssetlength\dimen@{#5}% \ifdim\dimen@>#2\pst@hbox \advance\pst@dimh\dimen@\relax \else \advance\pst@dimh#2\pst@hbox \fi \global\setbox\pst@boxg=\hbox{% \box\pstree@box #4\pst@dimh\hbox to\z@{\kern-\pst@dimg\unhbox\pst@hbox\hss}}% \xdef\next{\next#1=\number#3\pst@boxg sp\relax}} \@namedef{pstree@tnput@l}{% \pstree@tnput@@h\pst@dima{% \hss \lower\pst@dimg\box\pst@hbox \kern\pst@dimh \box\pstree@box}} \@namedef{pstree@tnput@r}{% \pstree@tnput@@h\pst@dimb{% \box\pstree@box \kern\pst@dimh \lower\pst@dimg\box\pst@hbox \hss}}% \def\pstree@tnput@@h#1#2{% \ifx\psk@tnyref\@empty \pssetlength\pst@dimg\psk@vref \else \pst@dimg=\ht\pst@hbox \advance\pst@dimg\dp\pst@hbox \pst@dimg=\psk@tnyref\pst@dimg \advance\pst@dimg-\dp\pst@hbox \fi \pst@dimh=\psk@tnsep\relax \ifdim\pst@dimh<\z@ \multiply\pst@dimh\m@ne \else \advance\pst@dimh#1% \fi \xdef\next{% \next#1=\number\pst@dimh sp\relax \advance#1\number\wd\pst@hbox sp\relax}% \global\setbox\pst@boxg=\hbox to\z@{#2}% \ifdim\ht\pst@boxg>\pst@dimc \xdef\next{\next\pst@dimc=\number\ht\pstree@box sp\relax}% \fi \ifdim\dp\pst@boxg>\pst@dimd \xdef\next{\next\pst@dimd=\number\dp\pstree@box sp\relax}% \fi} % \catcode`\@=\TheAtCode\relax \endinput %% END pstree.tex