\catcode`\_=8 \catcode`\<=13 \def\CurrentPackages{spqr,pstcol} \newcounter{myN} \setlongtables \author[Sebastian Rahtz]{Sebastian Rahtz\\Elsevier Science Ltd\\ Email: \texttt{s.rahtz@elsevier.co.uk}} \title{An introduction to PSTricks, part 3} \begin{Article} %\section{Introduction} %%\begin{multicols}{2} \section{Tree diagrams} \PST\ has an extremely rich environment for drawing trees, which allows for very complex structures and presentation. The available commands are listed in Table~\ref{PSTtree} and the graphical parameters which apply especially to these are listed in Table~\ref{PSTtreeparms}. As one might expect, most other commands and parameters are also available, from both the generalized drawing, and the node connectors and labels. Each of the node types described earlier is turned into a `tree' node, and named by prefixing it with a `T' and removing the `node' suffix. %\end{multicols} \begin{small} \begin{longtable}{lH{.5\textwidth}} \caption{\protect\PST\ tree drawing commands\label{PSTtree}}\\ \hline \endfirsthead \multicolumn{2}{l}{\protect\PST\ tree drawing commands \emph{cont.}}\\ \hline \endhead \PSTCom \pstree{node}{subtrees} & draws a node and subtrees connected to it\\ \PSTCom \psTree{rootnode} subtrees %\endpsTree & an `environment' form of \Lcs{psTree}\\ \PSTCom \Tn & null tree node \\ \PSTCom \tspace{dim} & leave gap of \emph{dim} before next level\\ \PSTComOpt \TC & tree node like \Lcs{Cnode} node\\ \PSTComOpt \TR{something} & tree node like \Lcs{Rnode} node\\ \PSTComOpt \Tcircle{something} & tree node like \Lcs{circlenode} node\\ \PSTComOpt \Tc{dim} & tree node like \Lcs{cnode} node\\ \PSTComOpt \Tdia{something} & tree node like \Lcs{dianode} node\\ \PSTComOpt \Tdot & tree node like \Lcs{dotnode} node\\ \PSTComOpt \Tf & tree node like \Lcs{fnode} node\\ \PSTComOpt \Tfan & draws a triangle with a top corner of the predecessor node\\ \PSTComOpt \Toval{something} & tree node like \Lcs{ovalnode} node\\ \PSTComOpt \Tp & tree node like \Lcs{pnode} node\\ \PSTComOpt \Tr{something} & tree node like \Lcs{rnode} node\\ \PSTComOpt \Ttri{something} & tree node like \Lcs{trinode} node\\ \PSTComOpt \skiplevel {nodes or subtrees} & miss out entire levels in a particular subtree\\ \PSTComOpt \skiplevels{n} {nodes or subtrees} & skip \emph{n} levels\\ \end{longtable} \end{small} \begin{small} \begin{longtable}{llH{10cm}} \caption{\protect\PST\ Graphical parameters for trees} \label{PSTtreeparms}\\[1mm] \emph{Parameter} & \emph{Default} & \emph{Explanation}\\ \hline \endfirsthead \protect\PST\ Graphical parameters for trees \emph{cont.}\\[1mm] \emph{Parameter} & \emph{Default} & \emph{Explanation}\\ \hline \endhead \mbox{}\\ \endfoot \Par{bbd=dim} () & set lower bounding box to \emph{dim}\\ \Par{bbh=dim} () & set upper bounding box to \emph{dim}\\ \Par{bbl=dim} () & set left bounding box to \emph{dim}\\ \Par{bbr=dim} () & set right bounding box to \emph{dim}\\ \Par{edge=command} (\ncline) & the node connector used to join tree nodes\\ \Par{fansize=dim} (1cm) &size of base for \Lcs{Tfan} tree node\\ \Par{levelsep=*dim} (2cm) & the distance between successive levels in a tree; the * makes the dimension be \emph{in addition} to the size of the nodes (levels are normally a fixed distance apart)\\ \Par{showbbox=true/false} (false) & draw a dotted frame showing the enclosing rectangle of trees\\ \Par{thislevelsep=*dim} () & like \emph{levelsep} but applies only to the current tree\\ \Par{thistreefit=tight/loose} () & like \emph{treefit} but applies only to the current tree\\ \Par{thistreenodesize=dim} () & like \emph{treenodesize} but applies only to the current tree\\ \Par{thistreesep=dim} () & like \emph{treesep} but applies only to the current tree\\ \Par{tndepth=dim} () & the minimum depth of tree node labels\\ \Par{tnheight=dim} () & the minimum height of tree node labels\\ \Par{tnpos=l/r/a/b} (b) & the position of tree node labels relative to the node (left, right, above, below) \\ \Par{tnsep=dim} () & the gap between tree node labels and the node (by default the same as \emph{labelsep} \\ \Par{treefit=tight/loose} (tight) & if tight, \emph{treesep} is the minimum distance between nodes on any level; i f loose, \emph{treesep} is the distance between the enclosing bounding boxes of subtrees\\ \Par{treeflip=true/false} (false) & does a mirror image of the free, flipping the nodes\\ \Par{treemode=R/L/U/D} (D) & the direction of tree growth (right, left, up and down)\\ \Par{treenodes=dim} ($-$1pt) & if positive, this sets a fixed size for tree nodes, regardless of content\\ \Par{treesep=dim} (0.75cm) & the distance between successive nodes in a tree\\ \Par{xbbd=dim} () & increase lower bounding box by \emph{dim}\\ \Par{xbbh=dim} () & increase upper bounding box by \emph{dim}\\ \Par{xbbl=dim} () & increase left bounding box by \emph{dim}\\ \Par{xbbr=dim} () & increase right bounding box by \emph{dim}\\ \end{longtable} \end{small} %\begin{multicols}{2} The fundamental concept in \PST\ trees is the \emph{nesting} of trees; a simple tree consists of a root, and one or more nodes: \begin{example*} \pstree{\TC}{\TC\TC} \end{example*} \noindent but each node can itself be a tree: \begin{example*} \pstree{\TC}{\pstree{\TC}{\TC \TC} \pstree{\TC}{\TC \TC}} \end{example*} This simple construct allows very complicated structures to be erected, as the examples below show. The following tree is a version of that shown in the \emph{\LaTeX\ Companion}, section 10.5.2, which was drawn using the \Lpack{ecltree} package; the ease of notation is roughly similar. As often in \LaTeX, the readability depends a great deal on how the code is laid out. The only change to the defaults is to lessen the vertical space between trees, and add some extra space around nodes. \begin{example*} \pstree[nodesep=2pt, levelsep=20pt]{\TR{grandfather}} { \pstree{\TR{uncle}}{\TR{cousin}} \pstree{\TR{father}} { \pstree{\TR{brother}}{\TR{nephew}} \pstree{\TR{Me}} { \pstree{\TR{son}}{\TR{grandson}} } } } \end{example*} If we now consider another tree drawing package described in the \emph{\LaTeX\ Companion}, Vanroose's \Lpack{trees}, the example in section 10.2.3 is a little harder to reproduce. The skeleton is trivial: \begin{example*} \pstree{\Tdot} { \Tdot \pstree{\Tdot} { \pstree{\Tdot} { \Tdot \Tdot \Tdot } \Tdot } } \end{example*} \noindent but when we come to add in all the node and connector labels, and change a few parameters to make the result nicer, the markup becomes a little complex, though the quantity is roughly similar to that of Vanroose: \begin{example*} \psset{labelsep=2pt,tnpos=a,radius=2pt} \pstree[treemode=R]{\TC*~{25}} { \TC*~{5}~[tnpos=r]{$L_a$} \taput{$a$} \pstree{\TC*~{20}\tbput{$b$}} { \pstree{\TC*~{15}\taput{$a$}} { \TC*~{7}~[tnpos=r]{$L_{baa}$}\taput{$a$} \TC*~{5}~[tnpos=r]{$L_{bab}$}\taput{$b$} \TC*~{3}~[tnpos=r]{$L_{bac}$}\tbput{$c$} } \TC*~{5}~[tnpos=r]{$L_{bb}$} \tbput{$b$} } } \end{example*} The node connectors in a tree are created by running the macro \Lcs{psedge} with the two nodes; the definition of \Lcs{psedge} can be overridden explicitly by a redefinition, or by using the \emph{edge} parameter. Here we redefine \Lcs{psedge} to be a curve, arrange the angles (bearing in mind that the tree is to grow upwards), and obtain a pleasing result. Note also the explicit links between named nodes, as well as the regular connections. %\end{multicols} \noindent\hrule \begin{example*} \footnotesize \def\psedge{\nccurve} \newcommand{\Female}[2][]{\TR[#1]{\emph{#2}}} \newcommand{\Male}[2][]{\TR[#1]{#2}} \psset{nodesep=2pt,angleA=90,angleB=-90,unit=.6cm} \pstree[treemode=U]{\Female{{\bfseries Matilde}}}{ \pstree{\Male{Sebastian}}{ \pstree{\Male[name=P]{Philip}}{\Male{Frederick}\Female{Ethel}} \pstree{\Female[name=W]{Mary}}{\Male{Lionel}\Female{Agnes}}} \pstree{\Female{Leonor}}{ \pstree{\Male[name=R]{Ra\'ul}}{\Male{Joaquim}\Female{J\'ulia}} \pstree{\Female[name=A]{Am\'elia}}{\Male{Melo}\Female{Augusta}}} } \psset{doubleline=true,linestyle=dotted} \ncline{P}{W}\nbput{1940} \ncline{R}{A}\nbput{1950} \end{example*} %\begin{multicols}{2} We said earlier that \PST\ does not always work out the extent of objects correctly, and this is illustrated by the connectors in the following example. Turning on \emph{showbbox}, we can see that without the use of \emph{xbbl} etc in the second incarnation, the bounding box is not correct: \begin{example*} \psset{angleB=-90,arrows=->,nrot=:U} \def\molesworth#1{% \pstree[#1]{\Tdia{ }} { \Tp[arrows=->,edge={\ncbar[angleA=180]}] \nbput{Gabbitas} {\psset{linestyle=dashed,arrows=-} \Tp } \Tp[arrows=->,edge={\ncbar}] \naput{Thring} } } \psset{showbbox=true} \begin{tabular}{l} \molesworth{}\\[10pt] \molesworth{xbbl=1cm,xbbr=1cm} \end{tabular} \end{example*} The technique of redefining edges is also necessary if we want right-angled joins, rather than straight lines. Again, we need to take care of the \emph{angleA} and \emph{angleB}, and ensure that in this left-right tree the nodes all line up on their left edges, using the \emph{ref} parameter. If this is not done, the \Lcs{ncangle} edges produce strange results. \begin{example*} \def\Item#1{\Tr[ref=l]{% \psframebox[linestyle=none]{#1}}} \def\psedge{\ncangle} \psset{xbbd=1.5cm,treemode=R, angleB=-180,angleA=0,levelsep=72pt} \pstree{\Item{langs}}{% \Item{german} \pstree{\Item{greek}}{% \Item{hamilton-kelly} \pstree{\Item{levy}}{% \Item{doc} \Item{src} } } \Item{italian} \pstree{\Item{portuguese}}{ \Item{hyphenation} } \pstree{\Item{turkish}}{% \Item{doc} \Item{hyphen} \Item{inputs} \Item{mf} \Item{misc} } \Item{xettex} } \end{example*} This allows us to remake the small family again, but this time with nicer connectors: \begin{example*} \def\XX#1{% \Tr{\psframebox{\rule{0pt}{9pt}#1}}% } \def\psedge{\ncangle} \psset{angleB=90,angleA=-90, levelsep=36pt,armB=14pt} \pstree{\XX{grandmother}} {% \pstree{\XX{aunt}}{\XX{cousin}} \pstree{\XX{mother}} { \pstree{\XX{sister}}{\XX{niece}} \pstree{\XX{Me}} { \pstree{\XX{daughter}} {\XX{granddaughter}} } } } \end{example*} The node connectors are, of course, standard \PST\ objects, so they obey all the normal parameters; here we draw the lower part of the tree with dashed lines, and each node content is set in math mode. \begin{example*} \footnotesize \psset{nodesep=2pt} \def\XX#1#2{% \TR{\ensuremath{#1_{\mbox{#2}}}}% } \pstree[xbbr=1.5cm]{\XX{R}{AMSU}} { \XX{S}{RawData} \pstree{\XX{S}{combine} \trput{\ensuremath{\oplus}} \tlput{\ensuremath{\oplus}}} { \psset{linestyle=dashed} \XX{R}{Modes} \XX{R}{Normal} \XX{R}{Vertical} \XX{R}{Latched} \XX{R}{Tripped} } \XX{S}{GenerateData} } \end{example*} If we want to hang distinct-looking trees off one node, the \emph{ncangle} connector, with some offsets, produces the right result. \begin{example*} \psset{framearc=.2,levelsep=4cm, armB=1cm,angleB=-180} \def\psedge{\ncangle} \def\TreeBox#1{\Tr{\psframebox{#1}}} \pstree[treemode=R]{\TreeBox{Monitor}} { \psset{offsetA=4pt} \TreeBox{Attitude Generator} \naput[npos=2.5]{{\small init}} \nbput[npos=2.5]{{\small stop}} \psset{offsetA=-4pt} \TreeBox{Normal Generator} } \end{example*} With simple connectors, we do not need to worry about the offsets or angles; what this example shows is how nested trees can change direction: \begin{example*} \psset{arrows=->,framearc=.2} \def\Treebox#1{% \Tr{\psframebox{#1}} } \pstree[treemode=R] {\Treebox{A$\rightarrow$B}}{ \pstree{ \Treebox{B$\rightarrow$C} }{ \Treebox{A$\rightarrow$D} \pstree[treemode=L] {\Treebox{B$\rightarrow$E}} {\Tn\TC[arrows=<-]} } } \end{example*} Finally, let us not forget the simple empty node: \begin{example*} \pstree{\Tp}{ \Tcircle{A} \Tcircle{B} } \end{example*} %\catcode`\<=12 \end{Article}