diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /usergrps/uktug/baskervi/6_2/pstrix2.tex |
Initial commit
Diffstat (limited to 'usergrps/uktug/baskervi/6_2/pstrix2.tex')
-rw-r--r-- | usergrps/uktug/baskervi/6_2/pstrix2.tex | 1091 |
1 files changed, 1091 insertions, 0 deletions
diff --git a/usergrps/uktug/baskervi/6_2/pstrix2.tex b/usergrps/uktug/baskervi/6_2/pstrix2.tex new file mode 100644 index 0000000000..44192db4aa --- /dev/null +++ b/usergrps/uktug/baskervi/6_2/pstrix2.tex @@ -0,0 +1,1091 @@ +\newpsobject{usergrid}{psgrid}{subgriddiv=1,griddots=10,gridlabels=7pt} +\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 2} +\begin{Article} +\section{Introduction} +In the first part of this description of \PST, we looked at +the basic concepts of the package, a series of low-level building +blocks, and the useful commands for dealing with text and the third +dimension. Now it is time to look at the higher-level packages built +in \PST, for drawing trees and graphs. There are a wide variety of +applications, as I hope the examples show. This part of the package +is, unfortunately, extremely rich, and readers should not be surprised +if they find the plethora of new commands rather confusing. + +%--------------------------- +\section{Nodes and their connections, and trees} +\PST\ offers sophisticated macros for setting up named nodes +and joining them together in complicated ways, complete with labels. + +The nodes can be created in three ways: +\begin{enumerate} +\item By placing them at arbitrary coordinates +\item By placing them on a regular grid or matrix +\item By using higher-level tree macros +\end{enumerate} +The sort of effect we will create is like this: + +\begin{GridPSExample}(0,0)(5,5) +\rput(1,1){\rnode{A}{Dog}} +\rput(2,4){\rnode{B}{Cat}} +\rput(4,2){\rnode{C}{Mouse}} +\ncline{A}{B} +\nccurve[linestyle=dotted]{A}{B} +\ncarc[linestyle=dashed]{A}{B} +\end{GridPSExample} + +Every node is given a symbolic name, which is used for +node connectors (lines, curves and so on), and for node labels. The +fact that nodes can occur \emph{anywhere} (such as in running text), +makes it possible to use them for surprising effects like linking two +words \rnode{n1}{one} to \rnode{n2}{another}\nccurve{n1}{n2}. When +considering connectors, we have to distinguish between the position of +the node they are pointing \emph{towards} (the node reference point), +and the actual extent of the connector. Most node creators have an +invisible box around them, which determines the end of connector lines. +We will first list all the commands, and then give practical examples. + +Table~\ref{PSTnode} lists all the node creation commands and node +connector commands, Table~\ref{PSTnodelab} lists the commands to label +connectors and nodes, and Table~\ref{PSTnodeparm} lists the extra +graphical parameters which apply to node connectors. + +%\end{multicols} +\begin{longtable}{lH{8.5cm}} +\caption{\protect\PST\ node drawing commands\label{PSTnode}}\\ +\hline +\endfirsthead +\protect\PST\ node drawing commands \emph{cont.}\\ +\hline +\endhead +\multicolumn{2}{l}{\bfseries\itshape Node creators} +\\ +\PSTCom \rnode`[refpoint]'{name}{text} +& create a node called \emph{name}, consisting of \emph{text}; +connectors point to the \emph{refpoint} +\\ +\PSTCom \Rnode`\c~'{name}{text} +& the same as \Lcs{rnode}, but the reference point is the middle of +the box's baseline, plus \c~{} +\\ +\PSTCom \pnode`\c~'{name} +& create a node at \c, which takes up no space +\\ +\PSTComOpt \cnode`\c~'{radius}{name} +& create a node consisting of circle of \emph{radius} +\\ +\PSTComOpt \Cnode`\c~'{name} +& create a node consisting of circle, using the +radius set by the \emph{radius} graphical parameter (it is sometimes +useful to set the radius for many circles) +\\ +\PSTComOpt \cnodeput`{angle}\c~'{name}{text} +\\ +\PSTComOpt \circlenode{name}{text} +& like \Lcs{pscirclebox}, but makes a node +\\ +\PSTComOpt \ovalnode{name}{text} +& like \Lcs{psovalbox}, but makes a node +\\ +\PSTComOpt \dianode{name}{text} +& like \Lcs{diabox}, but makes a node +\\ +\PSTComOpt \dotnode`\c~'{name}{text} +& like \Lcs{psdot}, but makes a node +\\ +\PSTComOpt \fnode`\c~'{name}{text} +& like \Lcs{psframe}, but makes a node +\\ +\PSTComOpt \trinode{name}{text} +& like \Lcs{tribox}, but makes a node +\\ +[6pt] +\multicolumn{2}{l}{\bfseries\itshape Node connectors} +\\ +\PSTComOpt \ncline`{arrows}'{firstnode}{secondnode} +& straight line between nodes +\\ +\PSTComOpt \ncLine`{arrows}'{firstnode}{secondnode} +& straight line between nodes, but labels are placed as if the line +went right to the center of the nodes +\\ +\PSTComOpt \ncarc`{arrows}'{firstnode}{secondnode} +& arc between nodes; uses parameter \emph{arcangle} +\\ +\PSTComOpt \ncdiag`{arrows}'{firstnode}{secondnode} +& using the \emph{arm} and \emph{angle} parameters, `arms' start out +from each node and are then joined by a line; corner shape is +controlled by the \emph{linearc} parameter +\\ +\PSTComOpt \ncdiagg`{arrows}'{firstnode}{secondnode} +& as \Lcs{ncdiag}, but the second arm is not drawn +\\ +\PSTComOpt \ncbar`{arrows}'{firstnode}{secondnode} +& a line is drawn with arms coming off at a right angle to the nodes, +at an angle of \emph{angleA}; the arm length is adjusted if necessary +\\ +\PSTComOpt \ncangle`{arrows}'{firstnode}{secondnode} +& draws a connect line \Lcs{ncdiag}, but the angle between arm A and +the connector line is forced to a right angle +\\ +\PSTComOpt \ncangles`{arrows}'{firstnode}{secondnode} +& like \Lcs{ncangle}, but arm A is joined to arm B by two line +segments that meet at a right angle +\\ +\PSTComOpt \ncloop`{arrows}'{firstnode}{secondnode} +& like \Lcs{ncangles} but 5 line segments are used, the second and +forth being \emph{loopsize} long +\\ +\PSTComOpt \nccurve`{arrows}'{firstnode}{secondnode} +& bezier curve between nodes, using the \emph{ncurv} parameters to +determine the control point positions +\\ +\PSTComOpt \nccircle`{arrows}'{node}{radius} +& draws a circle or part circle of radius \emph{radius} +connecting the node to itself +\\[6pt] +\multicolumn{2}{l}{\bfseries\itshape Coil and zigzag node connectors} +\\ +\PSTCom \nccoil`*[settings]{arrows}'{firstnode}{secondnode} +\\ +\PSTCom \nczigzag`*[settings]{arrows}'{firstnode}{secondnode} +\end{longtable} + +\begin{longtable}{llH{.4\textwidth}} +\caption{\protect\PST\ Graphical parameters for node connectors} +\label{PSTnodeparm}\\[1mm] +\emph{Parameter} & \emph{Default} & \emph{Explanation}\\ +\hline +\endfirsthead +\protect\PST\ Graphical parameters for node connectors \emph{cont.}\\[1mm] +\emph{Parameter} & \emph{Default} & \emph{Explanation}\\ +\hline +\endhead +\mbox{}\\ +\endfoot +\Par{offset=dim} (0pt) +& the offset of the connection point to a node\\ +\Par{nodesep=dim} (0pt) +&the border around nodes at which connectors stop +\\ +\Par{nodesepA=dim} (0pt) +&the border around the first node +\\ +\Par{nodesepB=dim} (0pt) +&the border around the second node + \\ +\Par{arcangle=angle} (8) +&in \Lcs{ncarc}, the angle between the arc and a straight line drawn between the nodes + \\ +\Par{angle=angle} (0) +&the angle at which connectors hit the nodes + \\ +\Par{angleA=angle} (0) +&the angle at which a connector hits the first node + \\ +\Par{angleB=angle} (0) +&the angle at which a connector hits the second node + \\ +\Par{arm=dim} (10pt) +&the length of the line segment where the connector joins the nodes + \\ +\Par{armA=dim} (10pt) +&the length of the line segment where the connector joins the first node + \\ +\Par{armB=dim} (10pt) +&the length of the line segment where the connector joins the second node + \\ +\Par{loopsize=dim} (1cm) +& the length of line segments for \Lcs{ncloop} +\\ +\Par{ncurv=num} (0.67) +& the distance to Bezier control points in \Lcs{nccurve}; lower values +give tighter curves; the distance from the node to the first control +point is half \emph{ncurv} $\times$ the distance between the two end points\\ +\Par{ncurvA=num} (0.67) +& as \emph{ncurv} but for first node only +\\ +\Par{ncurvB=num} (0.67) +& as \emph{ncurv} but for second node only +\\ +\Par{boxsize=dim} (0.4cm) +& half the width of the enclosing box of \Lcs{ncbox} and \Lcs{ncarcbox} +\\[6pt] +\multicolumn{3}{l}{\bfseries\itshape Parameters for node labels}\\ +\Par{ref=ref} (c) +& sets the reference point for labels\\ +\Par{nrot=rot} (0) +& the rotation of label text; if the angle is preceded by :, it is +measured with respect to the connector line; the letter abbreviations +we have already seen are available, so :U is commonly used to +align text on the connector line\\ +\Par{npos=num} () +& the position along the length of the connector line where a label is +placed; each connector line has one or more segments, and the value of +\emph{npos}+1 determines the segment on which the label is set; the +default values for this parameter are given in the \protect\PST\ +manual, but can also be seen in the examples below\\ +\Par{shortput=none/nab/tablr/tab} (none) +& determines whether short codes are available for labelling +connectors; see page~\pageref{shortput}.\\ +\Par{tpos=num} (0.5) +& the proportion of the distance between nodes at which labels are +placed on a connector\\ +\Par{mnode=type} (R) +& (for matrices) the default node type; possibilities are +R (\Lcs{Rnode}), r (\Lcs{rnode}), C (\Lcs{Cnode}), f (\Lcs{fnode}), p +(\Lcs{pnode}), circle (\Lcs{circlenode}), oval (\Lcs{ovalnode}), dia +(\Lcs{dianode}), tri (\Lcs{trinode}), dot (\Lcs{dotnote}), and none\\ +\Par{emnode=type} (none) +& (for matrices) the type of node created for empty cells in a matrix\\ +\Par{name=name} () +& (for matrices) the name of a node; parameters like this can set in +square brackets in the cell\\ +\Par{nodealign=true/false} (false) +& (for matrices) whether baselines of nodes pass through the centre of +nodes\\ +\Par{mcol=l/r/c} (c) +& (for matrices) the alignment of a node within a matrix cell\\ +\Par{mnodesize=dim} ($-1$pt) +& (for matrices) is positive, nodes are forced to be this size\\ +\Par{rowsep=dim} (1.5cm) +& (for matrices) the gap between rows \\ +\Par{colsep=dim} (1.5cm) +& (for matrices) the gap between columns \\ +\end{longtable} + +\begin{longtable}{lH{10cm}} +\caption{\protect\PST\ node connection + labelling commands}\label{PSTnodelab}\\ +\hline +\endfirsthead +\protect\PST\ node connection labelling commands \emph{cont.}\\ +\hline +\endhead +\multicolumn{2}{l}{\bfseries\itshape Labelling based on connector length}\\ +\PSTComOpt \ncput {something} +& place \emph{something} on the connector line\\ +\PSTComOpt \naput {something} +& place \emph{something} above the connector line\\ +\PSTComOpt \nbput {something} +& place \emph{something} under the connector line\\[6pt] +\multicolumn{2}{l}{\bfseries\itshape Labelling based on distance +between nodes}\\ +\PSTComOpt \tvput {something} +& working on the vertical distance between nodes, place \emph{something} in the middle of the line\\ +\PSTComOpt \tlput {something} +& working on the vertical distance between nodes, place \emph{something} +to the left of the line\\ +\PSTComOpt \trput {something} +& working on the vertical distance between nodes, +place \emph{something} to the right of the line\\ +\PSTComOpt \thput{something} +& working on the horizontal distance between nodes, +place \emph{something} in the middle of the line\\ +\PSTComOpt \taput{something} +& working on the horizontal distance between nodes, +place \emph{something} above the line\\ +\PSTComOpt \tbput{something} +& working on the horizontal distance between nodes, +place \emph{something} below the line\\[6pt] +\multicolumn{2}{l}{\bfseries\itshape Labelling nodes}\\ +\PSTCom`[par]'{angle}{name}{something} +& place \emph{something} next to the node, at a distance of +\emph{nodesep}, in the direction \emph{angle} from the centre of the node +\end{longtable} +%\begin{multicols}{2} +\begin{table*} +\caption{\protect\PST\ drawing commands comparable to node connectors} +\label{PSTcondraw} +\begin{tabular}{l} +\PSTComOpt \pcline`{arrows}'\c1\c2 +\\ +\PSTComOpt \pccurve`{arrows}'\c1\c2 +\\ +\PSTComOpt \pcarc`{arrows}'\c1\c2 +\\ +\PSTComOpt \pcbar`{arrows}'\c1\c2 +\\ +\PSTComOpt \pcdiag`{arrows}'\c1\c2 +\\ +\PSTComOpt \pcangle`{arrows}'\c1\c2 +\\ +\PSTComOpt \pcloop`{arrows}'\c1\c2 +\\ +\PSTCom \pczigzag`*[settings]{arrows}'\c1\c2 +\\ +\PSTCom \pccoil`*[settings]{arrows}'\c1\c2 +\end{tabular} +\end{table*} +There are several important concepts we need to bear in mind when +looking at the myriad of node and connector commands: +\begin{enumerate} +\item When joining two nodes with something like a curve, the +connectors comes in by default on the right hand side of the object +(at 0 degrees). If we have two boxes side by side, the \emph{angleB} +parameter has to be set to 180 if we want the connector to come into +the second box on its left side. This may seem cumbersome at first, +but it makes for a flexible system; +\item the connector labelling commands all place the label +some proportion of the way along the connector, but they distinguish +between the distance between nodes, and the length of the line. The +former situation applies to constructions like matrices, where we +want the label positions to be constant, regardless of the size of the +nodes. +\item The node connectors are not drawn directly in \TeX, but are done +at the PostScript level; this means that \TeX\ is not always quite +sure how much space will be taken up by the object. Particularly when +curving connectors are drawn, you might find that they protrude +outside the area allowed by \TeX --- adjust by hand. +\end{enumerate} +\label{shortput} +Because labelling node connectors is a very common thing to do, a +short cut is provided to save all the \Lcs{naput} commands etc. If the +parameter \emph{shortput} is set to \texttt{nab}, the \verb|^| is used +instead of \Lcs{naput} and \verb|_| instead of \Lcs{nbput}. If it is +set to \texttt{tablr}, the \verb|^| stands for \Lcs{taput}, +\verb|_| for \Lcs{tbput}, +\verb|<| for \Lcs{tlput} and +\verb|>| for \Lcs{trput}. + +If all this were not enough, all the node connectors can also be used as +ordinary drawing tools, by using the commands listed in +Table~\ref{PSTcondraw}, where the `pc' version corresponds to the `nc' +node connector. + +Let us first demonstrate the effects of these basic building blocks: +%\end{multicols} +\begin{longtable}{l} +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\rnode{A}{Cat}} +\rput(2.5,.5){\rnode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\Rnode{A}{Cat}} +\rput(2.5,.5){\Rnode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\pnode(.5,.5){A} +\pnode(2.5,.5){B} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\cnode(.5,.5){.2}{A} +\cnode(2.5,.5){.2}{B} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\psset{radius=.3} +\Cnode(.5,.5){A} +\Cnode(2.5,.5){B} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\circlenode{A}{Cat}} +\rput(2.5,.5){\circlenode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\ovalnode{A}{Cat}} +\rput(2.5,.5){\ovalnode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\trinode{A}{Cat}} +\rput(2.5,.5){\trinode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\dotnode(.5,.5){A} +\dotnode(2.5,.5){B} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\fnode(.5,.5){A} +\fnode(2.5,.5){B} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\dianode{A}{Cat}} +\rput(2.5,.5){\dianode{B}{Dog}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,.5){\rnode{B}{\psframebox{Dog}}} +\ncline{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\nccurve[angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,.5){\rnode{B}{\psframebox{Dog}}} +\ncarc{->}{A}{B} +\ncarc{->}{B}{A} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncbar{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncdiag[angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncdiagg[angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncangle[angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncangles[angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,1.5){\rnode{B}{\psframebox{Dog}}} +\ncloop[loopsize=.25,angleB=180]{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,2) +\rput(1,.5){\rnode{A}{\psframebox{Cat}}} +\nccircle{->}{A}{.5} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,.5){\rnode{B}{\psframebox{Dog}}} +\psset{coilarm=.01,coilwidth=.3} +\nccoil{A}{B} +\end{PSTInlineExample} +\\ +\begin{PSTInlineExample}(3,1) +\rput(.5,.5){\rnode{A}{\psframebox{Cat}}} +\rput(2.5,.5){\rnode{B}{\psframebox{Dog}}} +\psset{coilarm=.01,coilwidth=.3} +\nczigzag{A}{B} +\end{PSTInlineExample} +\\ +\end{longtable} +%\begin{multicols}{2} +The effect of node connectors is demonstrated in the +following, which uses the \Lcs{multido} macro (we will look at that in +a future article) to place objects at +regular intervals around a circle, and join them up +%\end{multicols} +\begin{example*} +\newcount\CtA +\newcount\CtB +\newcommand{\Wheel}[3]{{% +\pspicture(-1,-1)(1,1) +\SpecialCoor +\degrees[#1] +\multido{\ia=1+1}{#1}{% + \CtA=\ia + \advance\CtA by 1 + \CtB=#1 + \advance\CtB by -\ia + \multido{\ib=\CtA+1} + {\CtB}{#3(1;\ia)(1;\ib)}} +\multido{\i=1+1}{#1}{% + \rput(1;\i){% + \pscirclebox[fillstyle=solid, + fillcolor=white]% + {\footnotesize\i}}} +\endpspicture}} +\makebox[\columnwidth][s]{% +\psset{unit=2cm} +\Wheel{3}{1.8}{\psline} +\Wheel{5}{1.8}{\psline} +\psset{arcangle=10} +\Wheel{12}{3}{\pcarc[linecolor=blue]}} +\end{example*} +%\begin{multicols}{2} +It should be clear that we can draw arbitrary diagrams, trees etc +simply by working out the coordinates of each node; however, in +practice, there are two higher-level environments for easier creation +of nodes --- matrices and trees. + +\subsection{Matrices --- grid-based nodes} +The existing \LaTeX\ \Lenv{tabular} or AMS \LaTeX\ \Lenv{matrix} can be +used to place nodes, but \PST\ provides its own environment, +\Lenv{psmatrix}. This is like an easy +form of table, since the number of columns does not have to be +specified --- we simply separate column items by \verb|&| and rows by +\verb|\\| as normal, and \PST\ makes each cell a node, named as +\emph{rownumber},\emph{columnumber}. Thus the first node in the first +row is named \texttt{1,1} and the third node in the fourth row is +\texttt{4,3}, and these are used by the node connectors. + +\Lcs{psmatrix} has an optional parameter in which we can set +\emph{rowsep} and \emph{colsep}, determining the gap between +nodes. The parameter \emph{shortput} is set to \emph{tab} inside +\Lcs{psmatrix} by default, so we can adopt a quite succinct notation: + +\begin{PSExample}(0,0)(2.5,5) +\begin{psmatrix}[rowsep=1.5cm] +&City&\\ +{\tiny Shack} & House & {\Large Hotel} +\psset{arrows=<<-} +\ncline{1,2}{2,1}<{a} +\ncline{1,2}{2,2}>{b} +\ncline{1,2}{2,3}>{b} +\psset{arrows=-,linestyle=dotted} +\ncline{2,1}{2,2} +\ncline{2,2}{2,3} +\end{psmatrix} +\end{PSExample} + +Notice in this example that the shorthand `>' stands for \Lcs{trput}, +which places labels according to the distance between node centres, +not the connection length, which allows for the difference in sizes +of nodes in the second row. Nodes can span multiple columns by using +the \Lcs{psspan} command at the end of the cell, with a parameter of +the number of columns to span. + +A simple example of a square matrix can be created as: +\begin{example*} +\begin{psmatrix} +A & B \\ +$\sqrt{\frac{x + y}{z}}$ & D +\ncline{->}{1,1}{1,2} +\ncline{->}{1,2}{2,2} +\ncline{->}{2,2}{2,1} +\ncline{->}{2,1}{1,1} +\end{psmatrix} +\end{example*} +\noindent but by changing a few initial parameter settings, we can +present a `fancier' result, with nodes encircled, arrows on +connectors, and a better spacing. The connector labels are added with +the short-hand forms, which are those which are positioned in relation +to node centres. +In the second version, we redo the labels with +the label types which relate to line length, which in this case gives +a better result. The outer looping connector is an example of a +construct whose extent \TeX\ will probably guess incorrectly. +\begin{example*} +\psset{arrows=->,labelsep=3pt, +linecolor=gray,mnode=circle,shortput=nab} +\begin{psmatrix}[rowsep=20pt,colsep=28pt] +A & B \\ +$\sqrt{\frac{x + y}{z}}$ & D +\psset{linestyle=dotted} +\ncline{1,1}{1,2}^{\emph{firstly}} +\ncline{1,2}{2,2}>{\emph{next}} +\ncline{2,2}{2,1}_{\emph{then}} +\ncline{2,1}{1,1}<{\emph{lastly}} +\end{psmatrix} +\end{example*} +\begin{example*} +\psset{arrows=->,labelsep=3pt, +linecolor=gray,mnode=circle} +\begin{psmatrix}[rowsep=20pt,colsep=28pt] +A & B \\ +$\sqrt{\frac{x + y}{z}}$ & D +\psset{linestyle=dotted} +\ncline{1,1}{1,2}\naput{\emph{firstly}} +\ncline{1,2}{2,2}\naput{\emph{next}} +\ncline{2,2}{2,1}\naput{\emph{then}} +\ncline{2,1}{1,1}\naput{\emph{lastly}} +\nccurve[ncurv=2,linestyle=solid,angleA=90] + {1,1}{2,2} +\end{psmatrix} +\end{example*} + +Matrices can be nested, and it is possible to link nodes from two +different matrices, if the nodes are given explicit names. Each +\Lcs{psmatrix} wipes out the current set of \emph{row,column} names. + +\begin{example*} +\psset{linearc=.2} +\begin{psmatrix}[rowsep=3pt,colsep=-10pt] +[name=A]\psframebox{requirements}\\ +&[name=B]\psframebox{design}\\ +&&[name=C]\psframebox{coding}\\ +&&&[name=D]\psframebox{testing}\\ +&&&&[name=E]\psframebox{operations} +\psset{linearc=0,arrows=->,armA=0pt,angleB=90} +\ncangle{A}{B} +\ncangle{B}{C} +\ncangle{C}{D} +\ncangle{D}{E} +\psset{angleB=-90,angleA=180} +\ncangle{B}{A} +\ncangle{C}{B} +\ncangle{D}{C} +\ncangle{E}{D} +\end{psmatrix} +\end{example*} + +A normal low-level \PST\ +command, like \Lcs{framebox}, can be applied to a whole matrix. +We have to take some care in this example with alignment to make +the connecting line horizontal, so we place the single node on the +left in its own matrix. +%\end{multicols} +\begin{example*} +\psset{fillcolor=white,fillstyle=solid} +\def\Show#1{\psshadowbox{#1}} +\psset{arrows=->} +\begin{psmatrix} + [mnode=r,ref=t] + \psframebox[linestyle=none,framesep=.75]{% + \psset{ref=c} + \begin{psmatrix} + [name=A]\Show{Stakeholder} + \end{psmatrix} + } & + [mnode=r,ref=t] + \psframebox[fillstyle=solid,framesep=.75,fillcolor=gray]{% + \psset{ref=c} + \rule{1cm}{0pt} + \begin{psmatrix} + [name=B]\Show{Goal} &\Show{Criteria}\\ + \Show{Sub-goal} & \Show{Justification} + \ncline{1,1}{1,2} + \ncline{1,1}{2,2} + \ncline{1,1}{2,1}\tlput{Strategy} + \ncline{2,1}{2,2} + \end{psmatrix} + } +\ncline[angleB=-180]{A}{B}\naput[npos=.7]{Model} +\end{psmatrix} +\end{example*} +%\begin{multicols}{2} +In addition, \PST\ has an extremely rich environment for drawing trees, +permitting complex structures and presentation. This will form the +subject of the next part of this series. +\end{Article} +\endinput +%\begin{multicols}{2} +\subsection{Tree diagrams} +\PST\ has an extremely rich environment for drawing trees, which +allow 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}{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; if 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{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{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 constructs 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} +\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} +%\end{document} |