diff options
Diffstat (limited to 'Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-tutorial-chains.tex')
-rw-r--r-- | Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-tutorial-chains.tex | 772 |
1 files changed, 772 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-tutorial-chains.tex b/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-tutorial-chains.tex new file mode 100644 index 00000000000..f7b8d211110 --- /dev/null +++ b/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-tutorial-chains.tex @@ -0,0 +1,772 @@ +% Copyright 2006 by Till Tantau +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Free Documentation License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + + +\section{Tutorial: Putting a Diagram in Chains} + +In this tutorial we have a look at how chains and matrices can be used +to typeset a diagram. + +Ilka, who just got tenure for her professorship on Old and +Lovable Programming Languages, has recently dug up a technical report entitled +\emph{The Programming Language Pascal} in the dusty cellar of the +library of her university. Having been created in the good old times +using pens and rules, it looks like this\footnote{The shown diagram was not scanned, but + rather typeset using \tikzname. The jittering lines were created + using the |random steps| decoration.}: + +\tikzset{ + nonterminal/.style={ + % The shape: + rectangle, + % The size: + minimum size=6mm, + % The border: + very thick, + draw=red!50!black!50, % 50% red and 50% black, + % and that mixed with 50% white + % The filling: + top color=white, % a shading that is white at the top... + bottom color=red!50!black!20, % and something else at the bottom + % Font + font=\itshape + }, + terminal/.style={ + % The shape: + rounded rectangle, + minimum size=6mm, + % The rest + very thick,draw=black!50, + top color=white,bottom color=black!20, + font=\ttfamily}, + skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}} +} + +{ + \tikzset{terminal/.append style={text height=1.5ex,text depth=.25ex}} + \tikzset{nonterminal/.append style={text height=1.5ex,text depth=.25ex}} +\medskip +\noindent\begin{tikzpicture}[ + >=latex,thick, + /pgf/every decoration/.style={/tikz/sharp corners}, + fuzzy/.style={decorate,decoration={random steps,segment length=0.5mm,amplitude=0.15pt}}, + minimum size=6mm,line join=round,line cap=round, + terminal/.style={rectangle,draw,fill=white,fuzzy,rounded corners=3mm}, + nonterminal/.style={rectangle,draw,fill=white,fuzzy}, + node distance=4mm] + + \ttfamily + \begin{scope}[start chain, + every node/.style={on chain}, + terminal/.append style={join=by {->,shorten >=-1pt,fuzzy,decoration={post length=4pt}}}, + nonterminal/.append style={join=by {->,shorten >=-1pt,fuzzy,decoration={post length=4pt}}}, + support/.style={coordinate,join=by fuzzy}] + \node [support] (start) {}; + \node [nonterminal] {unsigned integer}; + \node [support] (after ui) {}; + \node [terminal] {.}; + \node [support] (after dot) {}; + \node [terminal] {digit}; + \node [support] (after digit) {}; + \node [support] (skip) {}; + \node [support] (before E) {}; + \node [terminal] {E}; + \node [support] (after E) {}; + \node [support,xshift=5mm] (between) {}; + \node [support,xshift=5mm] (before last) {}; + \node [nonterminal] {unsigned integer}; + \node [support] (after last) {}; + \node [coordinate,join=by ->] (end) {}; + \end{scope} + \node (plus) [terminal,above=of between] {+}; + \node (minus) [terminal,below=of between] {-}; + + \begin{scope}[->,decoration={post length=4pt},rounded corners=2mm,every path/.style=fuzzy] + \draw (after ui) -- +(0,.7) -| (skip); + \draw (after digit) -- +(0,-.7) -| (after dot); + \draw (before E) -- +(0,-1.2) -| (after last); + \draw (after E) |- (plus); + \draw (plus) -| (before last); + \draw (after E) |- (minus); + \draw (minus) -| (before last); + \end{scope} +\end{tikzpicture} +\medskip + +For her next lecture, Ilka decides to redo this diagram, but this time +perhaps a bit cleaner and perhaps also bit ``cooler.'' + + +\medskip +\noindent\begin{tikzpicture}[point/.style={coordinate},>=stealth',thick,draw=black!50, + tip/.style={->,shorten >=1pt},every join/.style={rounded corners}, + hv path/.style={to path={-| (\tikztotarget)}}, + vh path/.style={to path={|- (\tikztotarget)}}] + \matrix[column sep=4mm] { + % First row: + & & & & & & & & & & & \node (plus) [terminal] {+};\\ + % Second row: + \node (p1) [point] {}; & \node (ui1) [nonterminal] {unsigned integer}; & + \node (p2) [point] {}; & \node (dot) [terminal] {.}; & + \node (p3) [point] {}; & \node (digit) [terminal] {digit}; & + \node (p4) [point] {}; & \node (p5) [point] {}; & + \node (p6) [point] {}; & \node (e) [terminal] {E}; & + \node (p7) [point] {}; & & + \node (p8) [point] {}; & \node (ui2) [nonterminal] {unsigned integer}; & + \node (p9) [point] {}; & \node (p10) [point] {};\\ + % Third row: + & & & & & & & & & & & \node (minus)[terminal] {-};\\ + }; + + { [start chain] + \chainin (p1); + \chainin (ui1) [join=by tip]; + \chainin (p2) [join]; + \chainin (dot) [join=by tip]; + \chainin (p3) [join]; + \chainin (digit) [join=by tip]; + \chainin (p4) [join]; + { [start branch=digit loop] + \chainin (p3) [join=by {skip loop=-6mm,tip}]; + } + \chainin (p5) [join,join=with p2 by {skip loop=6mm,tip}]; + \chainin (p6) [join]; + \chainin (e) [join=by tip]; + \chainin (p7) [join]; + { [start branch=plus] + \chainin (plus) [join=by {vh path,tip}]; + \chainin (p8) [join=by {hv path,tip}]; + } + { [start branch=minus] + \chainin (minus) [join=by {vh path,tip}]; + \chainin (p8) [join=by {hv path,tip}]; + } + \chainin (p8) [join]; + \chainin (ui2) [join=by tip]; + \chainin (p9) [join,join=with p6 by {skip loop=-11mm,tip}]; + \chainin (p10) [join=by tip]; + } +\end{tikzpicture} +}\medskip + +Having read the previous tutorials, Ilka knows already how to setup +the environment for her diagram, namely using a |tikzpicture| +environment. She wonders which libraries she will need. She decides +that she will postpone the decision and add the necessary libraries as +needed as she constructs the picture. + + +\subsection{Styling the Nodes} + +The bulk of this tutorial will be about arranging the nodes and +connecting them using chains, but let us start with setting up styles +for the nodes. + +There are two kinds of nodes in the diagram, namely what theoreticians +like to call \emph{terminals} and \emph{nonterminals}. For the +terminals, Ilka decides to use a black color, which visually shows +that ``nothing needs to be done about them.'' The nonterminals, which +still need to be ``processed'' further, get a bit of red mixed in. + +Ilka starts with the simpler nonterminals, as there are no rounded +corners involved. Naturally, she sets up a style: + + +\begin{codeexample}[] +\begin{tikzpicture}[ + nonterminal/.style={ + % The shape: + rectangle, + % The size: + minimum size=6mm, + % The border: + very thick, + draw=red!50!black!50, % 50% red and 50% black, + % and that mixed with 50% white + % The filling: + top color=white, % a shading that is white at the top... + bottom color=red!50!black!20, % and something else at the bottom + % Font + font=\itshape + }] + \node [nonterminal] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} +Ilka is pretty proud of the use of the |minimum size| option: As the +name suggests, this option ensures that the node is at least 6mm by +6mm, but it will expand in size as necessary to accommodate longer +text. By giving this option to all nodes, they will all have the same +height of 6mm. + +Styling the terminals is a bit more difficult because of the round +corners. Ilka has several options how she can achieve them. Once way +is to use the |rounded corners| option. It gets a dimension as +parameter and causes all corners to be replaced by little arcs with +the given dimension as radius. By setting the radius to 3mm, she will +get exactly what she needs: circles, when the shapes are, indeed, +exactly 6mm by 6mm and otherwise half circles on the sides: + +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm, + terminal/.style={ + % The shape: + rectangle,minimum size=6mm,rounded corners=3mm, + % The rest + very thick,draw=black!50, + top color=white,bottom color=black!20, + font=\ttfamily}] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; +\end{tikzpicture} +\end{codeexample} + +Another possibility is to use a shape that is specially made for +typesetting rectangles with arcs on the sides (she has to use the +|shapes.misc| library to use it). This shape gives Ilka +much more control over the appearance. For instance, she could have an +arc only on the left side, but she will not need this. +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm, + terminal/.style={ + % The shape: + rounded rectangle, + minimum size=6mm, + % The rest + very thick,draw=black!50, + top color=white,bottom color=black!20, + font=\ttfamily}] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; +\end{tikzpicture} +\end{codeexample} +At this point, she notices a problem. The baseline of the text in the +nodes is not aligned: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; + + \draw [help lines] let \p1 = (dot.base), + \p2 = (digit.base), + \p3 = (E.base) + in (-.5,\y1) -- (3.5,\y1) + (-.5,\y2) -- (3.5,\y2) + (-.5,\y3) -- (3.5,\y3); +\end{tikzpicture} +\end{codeexample} +\noindent (Ilka has moved the style definition to the preamble by +saying |\tikzset{terminal/.style=...}|, so that she can use it in all +pictures.) + +For the |digit| and the |E| the difference in the baselines is almost +imperceptible, but for the dot the problem is quite severe: It looks +more like a multiplication dot than a period. + +Ilka toys with the idea of using the |base right=of...| option rather than +|right=of...| to align the nodes in such a way that the baselines +are all on the same line (the |base right| option places a node +right of something so that the baseline is right of the baseline of +the other object). However, this does not have the desired effect: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm] + \node (dot) [terminal] {.}; + \node (digit) [terminal,base right=of dot] {digit}; + \node (E) [terminal,base right=of digit] {E}; +\end{tikzpicture} +\end{codeexample} +The nodes suddenly ``dance around''! There is no hope of changing the +position of text inside a node using anchors. Instead, Ilka must use a +trick: The problem of mismatching baselines is caused by the fact that +|.| and |digit| and |E| all have different heights and depth. If they +all had the same, they would all be positioned vertically in the same +manner. So, all Ilka needs to do is to use the |text height| and +|text depth| options to explicitly specify a height and depth for the +nodes. +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm, + text height=1.5ex,text depth=.25ex] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; +\end{tikzpicture} +\end{codeexample} + + + +\subsection{Aligning the Nodes Using Positioning Options} + +Ilka now has the ``styling'' of the nodes ready. The next problem is +to place them in the right places. There are several ways to do +this. The most straightforward is to simply explicitly place the nodes +at certain coordinates ``calculated by hand.'' For very simple +graphics this is perfectly alright, but it has several disadvantages: +\begin{enumerate} +\item For more difficult graphics, the calculation may become + complicated. +\item Changing the text of the nodes may make it necessary to + recalculate the coordinates. +\item The source code of the graphic is not very clear since the + relationships between the positions of the nodes are not made + explicit. +\end{enumerate} + +For these reasons, Ilka decides to try out different ways of arranging +the nodes on the page. + +The first method is the use of \emph{positioning options}. To use +them, you need to load the |positioning| library. This gives you +access to advanced implementations of options like |above| or |left|, +since you can now say |above=of some node| in order to place a node +above of |some node|, with the borders separated by |node distance|. + +Ilka can use this to draw the place the nodes in a long row: +\tikzset{terminal/.append style={text height=1.5ex,text depth=.25ex}} +\tikzset{nonterminal/.append style={text height=1.5ex,text + depth=.25ex}} +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm] + \node (ui1) [nonterminal] {unsigned integer}; + \node (dot) [terminal,right=of ui1] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; + \node (plus) [terminal,above right=of E] {+}; + \node (minus) [terminal,below right=of E] {-}; + \node (ui2) [nonterminal,below right=of plus] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} + +For the plus and minus nodes, Ilka is a bit startled by their +placements. Shouldn't they be more to the right? The reason they are +placed in that manner is the following: The |north east| anchor of the +|E| node lies at the ``upper start of the right arc,'' which, a bit +unfortunately in this case, happens to be the top of the +node. Likewise, the |south west| anchor of the |+| node is actually at +its bottom and, indeed, the horizontal and vertical distances between +the top of the |E| node and the bottom of the |+| node are both 5mm. + +There are several ways of fixing this problem. The +easiest way is to simply add a little bit of horizontal shift by hand: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm] + \node (E) [terminal] {E}; + \node (plus) [terminal,above right=of E,xshift=5mm] {+}; + \node (minus) [terminal,below right=of E,xshift=5mm] {-}; + \node (ui2) [nonterminal,below right=of plus,xshift=5mm] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} + +A second way is to revert back to the idea of using a normal rectangle +for the terminals, but with rounded corners. Since corner rounding +does not affect anchors, she gets the following result: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm,terminal/.append style={rectangle,rounded corners=3mm}] + \node (E) [terminal] {E}; + \node (plus) [terminal,above right=of E] {+}; + \node (minus) [terminal,below right=of E] {-}; + \node (ui2) [nonterminal,below right=of plus] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} +A third way is to use matrices, which we will do later. + +Now that the nodes have been placed, Ilka needs to add +connections. Here, some connections are more difficult than +other. Consider for instance the ``repeat'' line around the +|digit|. One way of describing this line is to say ``it starts a +little to the right of |digit| than goes down and then goes to the +left and finally ends at a point a little to the left of |digit|.'' +Ilka can put this into code as follows: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; + + \path (dot) edge[->] (digit) % simple edges + (digit) edge[->] (E); + + \draw [->] + % start right of digit.east, that is, at the point that is the + % linear combination of digit.east and the vector (2mm,0pt). We + % use the ($ ... $) notation for computing linear combinations + ($ (digit.east) + (2mm,0) $) + % Now go down + -- ++(0,-.5) + % And back to the left of digit.west + -| ($ (digit.west) - (2mm,0) $); +\end{tikzpicture} +\end{codeexample} + +Since Ilka needs this ``go up/down then horizontally and than up/down +to a target'' several times, it seems sensible to define a special +\emph{to-path} for this. Whenever the |edge| command is used, it +simply adds the current value of |to path| to the path. So, Ilka can +setup a style that contains the correct path: +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm, + skip loop/.style={to path={-- ++(0,-.5) -| (\tikztotarget)}}] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; + + \path (dot) edge[->] (digit) % simple edges + (digit) edge[->] (E) + ($ (digit.east) + (2mm,0) $) + edge[->,skip loop] ($ (digit.west) - (2mm,0) $); +\end{tikzpicture} +\end{codeexample} + +Ilka can even go a step further and make her |skip look| style +parametrized. For this, the skip loop's vertical offset is passed as +parameter |#1|. Also, in the following code Ilka specifies the start +and targets differently, namely as the positions that are ``in the +middle between the nodes.'' +\begin{codeexample}[] +\begin{tikzpicture}[node distance=5mm and 5mm, + skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}}] + \node (dot) [terminal] {.}; + \node (digit) [terminal,right=of dot] {digit}; + \node (E) [terminal,right=of digit] {E}; + + \path (dot) edge[->] (digit) % simple edges + (digit) edge[->] (E) + ($ (digit.east)!.5!(E.west) $) + edge[->,skip loop=-5mm] ($ (digit.west)!.5!(dot.east) $); +\end{tikzpicture} +\end{codeexample} + + +\subsection{Aligning the Nodes Using Matrices} + +Ilka is still bothered a bit by the placement of the plus and minus +nodes. Somehow, having to add an explicit |xshift| seems too much like +cheating. + +A perhaps better way of positioning the nodes is to use a +\emph{matrix}. In \tikzname\ matrices can be used to align quite +arbitrary graphical objects in rows and columns. The syntax is very +similar to the use of arrays and tables in \TeX\ (indeed, internally +\TeX\ tables are used, but a lot of stuff is going on additionally). + +In Ilka's graphic, there will be three rows: One row containing only +the plus node, one row containing the main nodes and one row +containing only the minus node. +\begin{codeexample}[] +\begin{tikzpicture} + \matrix[row sep=1mm,column sep=5mm] { + % First row: + & & & & \node [terminal] {+}; & \\ + % Second row: + \node [nonterminal] {unsigned integer}; & + \node [terminal] {.}; & + \node [terminal] {digit}; & + \node [terminal] {E}; & + & + \node [nonterminal] {unsigned integer}; \\ + % Third row: + & & & & \node [terminal] {-}; & \\ + }; +\end{tikzpicture} +\end{codeexample} +That was easy! By toying around with the row and columns separations, +Ilka can achieve all sorts of pleasing arrangements of the nodes. + +Ilka now faces the same connecting problem as before. This time, she +has an idea: She adds small nodes (they will be turned into +coordinates later on and be invisible) at all the places +where she would like connections to start and end. +\begin{codeexample}[] +\begin{tikzpicture}[point/.style={circle,inner sep=0pt,minimum size=2pt,fill=red}, + skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}}] + \matrix[row sep=1mm,column sep=2mm] { + % First row: + & & & & & & & & & & & \node [terminal] {+};\\ + % Second row: + \node (p1) [point] {}; & \node [nonterminal] {unsigned integer}; & + \node (p2) [point] {}; & \node [terminal] {.}; & + \node (p3) [point] {}; & \node [terminal] {digit}; & + \node (p4) [point] {}; & \node (p5) [point] {}; & + \node (p6) [point] {}; & \node [terminal] {E}; & + \node (p7) [point] {}; & & + \node (p8) [point] {}; & \node [nonterminal] {unsigned integer}; & + \node (p9) [point] {}; \\ + % Third row: + & & & & & & & & & & & \node [terminal] {-};\\ + }; + + \path (p4) edge [->,skip loop=-5mm] (p3) + (p2) edge [->,skip loop=5mm] (p6); +\end{tikzpicture} +\end{codeexample} +Now, its only a small step to add all the missing edges. + + + +\subsection{Using Chains} + +Matrices allow Ilka to align the nodes nicely, but the connections are +not quite perfect. The problem is that the code does not really +reflect the paths that underlie the diagram. + + +For this reason, Ilka decides to try out \emph{chains} by including +the |chain| library. Basically, a chain is just a sequence of +(usually) connected nodes. The nodes can already have been constructed +or they can be constructed as the chain is constructed (or these +processes can be mixed). + +\subsubsection{Creating a Simple Chain} + + +Ilka starts with creating a chain from scratch. For this, she starts a +chain using the |start chain| option in a scope. Then, inside the +scope, she uses the |on chain| option on nodes to add them to the +chain. +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm] + \node [on chain,nonterminal] {unsigned integer}; + \node [on chain,terminal] {.}; + \node [on chain,terminal] {digit}; + \node [on chain,terminal] {E}; + \node [on chain,nonterminal] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} +(Ilka will add the plus and minus nodes later.) + +As can be seen, the nodes of a chain are placed in a row. This can be +changed, for instance by saying |start chain=going below| we get a +chain where each node is below the previous one. + +The next step is to \emph{join} the nodes of the chain. For this, we +add the |join| option to each node. This joins the node with the +previous node (for the first node nothing happens). +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm] + \node [on chain,join,nonterminal] {unsigned integer}; + \node [on chain,join,terminal] {.}; + \node [on chain,join,terminal] {digit}; + \node [on chain,join,terminal] {E}; + \node [on chain,join,nonterminal] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} +In order to get a arrow tip, we redefine the |every join| style. Also, +we move the |join| and |on chain| options to the |every node| +style so that we do not have to repeat them so often. +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm, every node/.style={on chain,join}, every join/.style={->}] + \node [nonterminal] {unsigned integer}; + \node [terminal] {.}; + \node [terminal] {digit}; + \node [terminal] {E}; + \node [nonterminal] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} + + +\subsubsection{Branching and Joining a Chain} + +It is now time to add the plus and minus signs. They obviously +\emph{branch off} the main chain. For this reason, we start a branch +for them using the |start branch| option. +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm, every node/.style={on chain,join}, every join/.style={->}] + \node [nonterminal] {unsigned integer}; + \node [terminal] {.}; + \node [terminal] {digit}; + \node [terminal] {E}; + \begin{scope}[start branch=plus] + \node (plus) [terminal,on chain=going above right] {+}; + \end{scope} + \begin{scope}[start branch=minus] + \node (minus) [terminal,on chain=going below right] {-}; + \end{scope} + \node [nonterminal,join=with plus,join=with minus] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} + +Let us see, what is going on here. First, the |start branch| begins a +branch, starting with the node last created on the current chain, +which is the |E| node in our case. This is implicitly also the first +node on this branch. A branch is nothing different from a chain, which +is why the plus node is put on this branch using the |on chain| +option. However, this time we specify the placement of the node +explicitly using |going |\meta{direction}. This causes the plus sign +to be placed above and right of the |E| node. It is automatically +joined to its predecessor on the branch by the implicit |join| +option. + +When the first branch ends, only the plus node has been added and the +current chain is the original chain once more and we are back to the +|E| node. Now we start a new branch for the minus node. After this +branch, the current chain ens at |E| node once more. + +Finally, the rightmost unsigned integer is added to the (main) chain, +which is why it is joined correctly with the |E| node. The two +additional |join| options get a special |with| parameter. This allows +you to join a node with a node other than the predecessor on the +chain. The |with| should be followed by the name of a node. + +Since Ilka will need scopes more often in the following, she includes +the |scopes| library. This allows her to replace |\begin{scope}| + simply by an opening brace and |\end{scope}| by the corresponding +closing brace. Also, in the following example we reference +the nodes |plus| and |minus| using +their automatic name: The $i$th node on a chain is called +|chain-|\meta{i}. For a branch \meta{branch}, the $i$th node is called +|chain/|\meta{branch}|-|\meta{i}. The \meta{i} can be replaced by +|begin| and |end| to reference the first and (currently) last node on +the chain. + +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm, every on chain/.style={join}, every join/.style={->}] + \node [on chain,nonterminal] {unsigned integer}; + \node [on chain,terminal] {.}; + \node [on chain,terminal] {digit}; + \node [on chain,terminal] {E}; + { [start branch=plus] + \node (plus) [terminal,on chain=going above right] {+}; + } + { [start branch=minus] + \node (minus) [terminal,on chain=going below right] {-}; + } + \node [nonterminal,on chain,join=with chain/plus-end,join=with chain/minus-end] {unsigned integer}; +\end{tikzpicture} +\end{codeexample} + + +The next step is to add intermediate coordinate nodes in the same +manner as Ilka did for the matrix. For them, we change the |join| +style slightly, namely for these nodes we do not want an arrow +tip. This can be achieved either by (locally) changing the +|every join| style or, which is what is done in the below example, by +giving the desired style using |join=by ...|, where |...| is the style +to be used for the join. + +\begin{codeexample}[] +\begin{tikzpicture}[start chain,node distance=5mm and 2mm, + every node/.style={on chain}, + nonterminal/.append style={join=by ->}, + terminal/.append style={join=by ->}, + point/.style={join=by -,circle,fill=red,minimum size=2pt,inner sep=0pt}] + \node [point] {}; \node [nonterminal] {unsigned integer}; + \node [point] {}; \node [terminal] {.}; + \node [point] {}; \node [terminal] {digit}; + \node [point] {}; \node [point] {}; + \node [point] {}; \node [terminal] {E}; + \node [point] {}; + { [node distance=5mm and 1cm] % local change in horizontal distance + { [start branch=plus] + \node (plus) [terminal,on chain=going above right] {+}; + } + { [start branch=minus] + \node (minus) [terminal,on chain=going below right] {-}; + } + \node [point,below right=of plus,join=with chain/plus-end by ->,join=with chain/minus-end by ->] {}; + } + \node [nonterminal] {unsigned integer}; + \node [point] {}; +\end{tikzpicture} +\end{codeexample} + + +\subsubsection{Chaining Together Already Positioned Nodes} + +The final step is to add the missing arrows. We can also use branches +for them (even though we do not have to, but it is good practice and +they exhibit the structure of the diagram in the code). + +Let us start with the repeat loop around the |digit|. This can be +thought of as a branch that starts at the point after the digit and +that ends at the point before the digit. However, we have already +constructed the point before the digit! In such cases, it is possible +to ``chain in'' an already positioned node, using the |\chainin| +command. This command must be followed by a coordinate that contains a +node name and optionally some options. The effect is that the named +node is made part of the current chain. + +\begin{codeexample}[pre={\tikzset{node distance=5mm and 2mm, + every node/.style={on chain}, + terminal/.append style={join=by ->}, + point/.style={join=by -,circle,fill=red,minimum size=2pt,inner sep=0pt}}}] +\begin{tikzpicture}[start chain] % plus some styles that are not shown + \node [point] {}; + \node (before digit) [point] {}; + \node [terminal] {digit}; + \node [point] {}; + { [start branch=digit loop] + \chainin (before digit) [join=by {->,skip loop=-5mm}]; + } + \node [point] {}; +\end{tikzpicture} +\end{codeexample} + + +\subsubsection{Combined Use of Matrices and Chains} + +Ilka's final idea is to combine matrices and chains in the following +manner: She will use a matrix to position the nodes. However, to show +the logical ``flow structure'' inside the diagram, she will create +chains and branches that show what is going on. + +Ilka starts with the matrix we had earlier, only with slightly adapted +styles. Then she writes down the main chain and its branches: + +\begin{codeexample}[] +\begin{tikzpicture}[point/.style={coordinate},>=stealth',thick,draw=black!50, + tip/.style={->,shorten >=1pt},every join/.style={rounded corners}, + hv path/.style={to path={-| (\tikztotarget)}}, + vh path/.style={to path={|- (\tikztotarget)}}] + \matrix[column sep=4mm] { + % First row: + & & & & & & & & & & & \node (plus) [terminal] {+};\\ + % Second row: + \node (p1) [point] {}; & \node (ui1) [nonterminal] {unsigned integer}; & + \node (p2) [point] {}; & \node (dot) [terminal] {.}; & + \node (p3) [point] {}; & \node (digit) [terminal] {digit}; & + \node (p4) [point] {}; & \node (p5) [point] {}; & + \node (p6) [point] {}; & \node (e) [terminal] {E}; & + \node (p7) [point] {}; & & + \node (p8) [point] {}; & \node (ui2) [nonterminal] {unsigned integer}; & + \node (p9) [point] {}; & \node (p10) [point] {};\\ + % Third row: + & & & & & & & & & & & \node (minus)[terminal] {-};\\ + }; + + { [start chain] + \chainin (p1); + \chainin (ui1) [join=by tip]; + \chainin (p2) [join]; + \chainin (dot) [join=by tip]; + \chainin (p3) [join]; + \chainin (digit) [join=by tip]; + \chainin (p4) [join]; + { [start branch=digit loop] + \chainin (p3) [join=by {skip loop=-6mm,tip}]; + } + \chainin (p5) [join,join=with p2 by {skip loop=6mm,tip}]; + \chainin (p6) [join]; + \chainin (e) [join=by tip]; + \chainin (p7) [join]; + { [start branch=plus] + \chainin (plus) [join=by {vh path,tip}]; + \chainin (p8) [join=by {hv path,tip}]; + } + { [start branch=minus] + \chainin (minus) [join=by {vh path,tip}]; + \chainin (p8) [join=by {hv path,tip}]; + } + \chainin (p8) [join]; + \chainin (ui2) [join=by tip]; + \chainin (p9) [join,join=with p6 by {skip loop=-11mm,tip}]; + \chainin (p10) [join=by tip]; + } +\end{tikzpicture} +\end{codeexample} |