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 | 746 |
1 files changed, 491 insertions, 255 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 index 725702513fb..e6b05fd6bd7 100644 --- 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 @@ -8,9 +8,9 @@ % See the file doc/generic/pgf/licenses/LICENSE for more details. -\section{Tutorial: Putting a Diagram in Chains} +\section{Tutorial: Diagrams as Simple Graphs} -In this tutorial we have a look at how chains and matrices can be used +In this tutorial we have a look at how graphs and matrices can be used to typeset a diagram. Ilka, who just got tenure for her professorship on Old and @@ -155,7 +155,7 @@ perhaps a bit cleaner and perhaps also bit ``cooler.'' \end{tikzpicture} }\medskip -Having read the previous tutorials, Ilka knows already how to setup +Having read the previous tutorials, Ilka knows already how to set up 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 @@ -205,7 +205,7 @@ 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 +corners. Ilka has several options how she can achieve them. One 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 @@ -379,7 +379,7 @@ 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 +others. 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|.'' @@ -405,11 +405,11 @@ Ilka can put this into code as follows: \end{tikzpicture} \end{codeexample} -Since Ilka needs this ``go up/down then horizontally and than up/down +Since Ilka needs this ``go up/down then horizontally and then 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: +set up a style that contains the correct path: \begin{codeexample}[] \begin{tikzpicture}[node distance=5mm and 5mm, skip loop/.style={to path={-- ++(0,-.5) -| (\tikztotarget)}}] @@ -488,285 +488,521 @@ where she would like connections to start and end. skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}}] \matrix[row sep=1mm,column sep=2mm] { % First row: - & & & & & & & & & & & \node [terminal] {+};\\ + & & & & & & & & & & & \node (plus) [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] {}; \\ + \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 [terminal] {-};\\ + & & & & & & & & & & & \node (minus)[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. +Now, it's only a small step to add all the missing edges. -\subsection{Using Chains} +\subsection{The Diagram as a Graph} 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}; +reflect the paths that underlie the diagram. For this, it seems +natural enough to Ilka to use the |graph| library since, after all, +connecting nodes by edges is exactly what happens in a graph. +The |graph| library can both be used to connect nodes that have +already been created, but it can also be used to create nodes ``on the +fly'' and these processes can also be mixed. + + +\subsubsection{Connecting Already Positioned Nodes} + +Ilka has already a fine method for positioning her nodes (using a +|matrix|), so all that she needs is an easy way of specifying the +edges. For this, she uses the |\graph| command (which is actually just +a shorthand for |\path graph|). It allows her to write down edges +between them in a simple way (the macro |\matrixcontent| contains +exactly the matrix content from the previous example; no need to +repeat it here): +\def\matrixcontent{ + % 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] {-};\\ +} +\begin{codeexample}[pre={\tikzset{ampersand replacement=\&,point/.style={coordinate}}}] +\begin{tikzpicture}[skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}}, + hv path/.style={to path={-| (\tikztotarget)}}, + vh path/.style={to path={|- (\tikztotarget)}}] + \matrix[row sep=1mm,column sep=2mm] { \matrixcontent }; + + \graph { + (p1) -> (ui1) -- (p2) -> (dot) -- (p3) -> (digit) -- (p4) + -- (p5) -- (p6) -> (e) -- (p7) -- (p8) -> (ui2) -- (p9) -> (p10); + (p4) ->[skip loop=-5mm] (p3); + (p2) ->[skip loop=5mm] (p5); + (p6) ->[skip loop=-11mm] (p9); + (p7) ->[vh path] (plus) -> [hv path] (p8); + (p7) ->[vh path] (minus) -> [hv path] (p8); + }; \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}; +This is already pretty near to the desired result, just a few +``finishing touches'' are needed to style the edges more nicely. + +However, Ilka does not have the feeling that the |graph| command is +all that hot in the example. It certainly does cut down on the number +of characters she has to write, but the overall graph structure is not +that much clear -- it is still mainly a list of paths through the +graph. It would be nice to specify that, say, there the path from +|(p7)| sort of splits to |(plus)| and |(minus)| and then merges once +more at |(p8)|. Also, all these parentheses are bit hard to type. + +It turns out that edges from a node to a whole group of nodes are +quite easy to specify, as shown in the next example. Additionally, by +using the |use existing nodes| option, Ilka can also leave out all the +parentheses (again, some options have been moved outside to keep the +examples shorter): + +\begin{codeexample}[pre={\tikzset{ampersand replacement=\&,point/.style={coordinate}, + skip loop/.style={to path={-- ++(0,##1) -| (\tikztotarget)}}, + hv path/.style={to path={-| (\tikztotarget)}}, + vh path/.style={to path={|- (\tikztotarget)}}}}] +\begin{tikzpicture}[,>=stealth',thick,black!50,text=black, + every new ->/.style={shorten >=1pt}, + graphs/every graph/.style={edges=rounded corners}] + \matrix[column sep=4mm] { \matrixcontent }; + + \graph [use existing nodes] { + p1 -> ui1 -- p2 -> dot -- p3 -> digit -- p4 -- p5 -- p6 -> e -- p7 -- p8 -> ui2 -- p9 -> p10; + p4 ->[skip loop=-5mm] p3; + p2 ->[skip loop=5mm] p5; + p6 ->[skip loop=-11mm] p9; + p7 ->[vh path] { plus, minus } -> [hv path] p8; + }; \end{tikzpicture} \end{codeexample} -\subsubsection{Branching and Joining a Chain} +\subsubsection{Creating Nodes Using the Graph Command} -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. +Ilka has heard that the |graph| command is also supposed to make it +easy to create nodes, not only to connect them. This is, indeed, +correct: When the |use existing node| option is not used and when a +node name is not surrounded by parentheses, then \tikzname\ will +actually create a node whose name and text is the node name: \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} +\tikz \graph [grow right=2cm] { unsigned integer -> d -> digit -> E }; \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 ends 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. - +Not quite perfect, but we are getting somewhere. First, let us change +the positioning algorithm by saying |grow right sep|, which causes new +nodes to be placed to the right of the previous nodes with a certain +fixed separation (|1em| by default). Second, we add some options to +make the node ``look nice''. Third, note the funny |d| node above: Ilka +tried writing just |.| there first, but got some error messages. The +reason is that a node cannot be called |.| in \tikzname, so she had to +choose a different name -- which is not good, since she wants a dot to +be shown! The trick is to put the dot in quotation marks, this allows +you to use ``quite arbitrary text'' as a node name: \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} +\tikz \graph [grow right sep] { + unsigned integer[nonterminal] -> "."[terminal] -> digit[terminal] -> E[terminal] +}; \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. - +Now comes the fork to the plus and minus signs. Here, Ilka can use the +grouping mechanism of the |graph| command to create a split: \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} +\tikz \graph [grow right sep] { + unsigned integer [nonterminal] -> + "." [terminal] -> + digit [terminal] -> + E [terminal] -> + { + "+" [terminal], + "" [coordinate], + "-" [terminal] + } -> + ui2/unsigned integer [nonterminal] +}; \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] {}; +Let us see, what is happening here. We want two |unsigned integer| +nodes, but if we just were to use this text twice, then \tikzname\ +would have noticed that the same name was used already in the current +graph and, being smart (actually too smart in this case), would have +created an edge back to the already-created node. Thus, a fresh name +is needed here. However, Ilka also cannot just write +|unsigned integer2|, because she wants the original text to be shown, +after all! The trick is to use a slash inside the node name: In +order to ``render'' the node, the text following the slash +is used instead of the node name, which is the text before the +slash. Alternatively, the |as| option can be used, which also +allows you to specify how a node should be rendered. + +It turns out that Ilka does not need to invent a name like +|ui2| for a node that she will not reference again +anyway. In this case, she can just leave out the name (write nothing +before |/|), which always stands for a ``fresh, anonymous'' node name. + +Next, Ilka needs to add some coordinates in between of some nodes +where the back-loops should got and she needs to shift the nodes a +bit: +\begin{codeexample}[pre={\tikzset{ + skip loop/.style={to path={-- ++(0,##1) -| (\tikztotarget)}}, + hv path/.style={to path={-| (\tikztotarget)}}, + vh path/.style={to path={|- (\tikztotarget)}}}}] +\begin{tikzpicture}[>=stealth', thick, black!50, text=black, + every new ->/.style={shorten >=1pt}, + graphs/every graph/.style={edges=rounded corners}] + \graph [grow right sep, branch down=7mm] { + / [coordinate] -> + unsigned integer [nonterminal] -- + p1 [coordinate] -> + "." [terminal] -- + p2 [coordinate] -> + digit [terminal] -- + p3 [coordinate] -- + p4 [coordinate] -- + p5 [coordinate] -> + E [terminal] -- + q1 [coordinate] ->[vh path] + { [nodes={yshift=7mm}] + "+" [terminal], + q2/ [coordinate], + "-" [terminal] + } -> [hv path] + q3 [coordinate] -- + /unsigned integer [nonterminal] -- + p6 [coordinate] -> + / [coordinate]; + + p1 ->[skip loop=5mm] p4; + p3 ->[skip loop=-5mm] p2; + p5 ->[skip loop=-11mm] p6; + }; \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: - +All that remains to be done is to somehow get rid of the strange +curves between the |E| and the unsigned integer. They are caused by +\tikzname's attempt at creating an edge that first goes vertical and +then horizontal but is actually just horizontal. Additionally, the +edge should not really be pointed; but it seems difficult to get rid +of this since the \emph{other} edges from |q1|, namely to |plus| and +|minus| should be pointed. + +It turns out that there is a nice way of solving this problem: You can +specify that a graph is |simple|. This means that there can be at most +one edge between any two nodes. Now, if you specify an edge twice, the +options of the second specification ``win.'' Thus, by adding two more +lines that ``correct'' these edges, we get the final diagram with its +complete code: \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] {-};\\ +\tikz [>=stealth', black!50, text=black, thick, + every new ->/.style = {shorten >=1pt}, + graphs/every graph/.style = {edges=rounded corners}, + skip loop/.style = {to path={-- ++(0,#1) -| (\tikztotarget)}}, + hv path/.style = {to path={-| (\tikztotarget)}}, + vh path/.style = {to path={|- (\tikztotarget)}}, + nonterminal/.style = { + rectangle, minimum size=6mm, very thick, draw=red!50!black!50, top color=white, + bottom color=red!50!black!20, font=\itshape, text height=1.5ex,text depth=.25ex}, + terminal/.style = { + rounded rectangle, minimum size=6mm, very thick, draw=black!50, top color=white, + bottom color=black!20, font=\ttfamily, text height=1.5ex, text depth=.25ex}, + shape = coordinate + ] + \graph [grow right sep, branch down=7mm, simple] { + / -> unsigned integer[nonterminal] -- p1 -> "." [terminal] -- p2 -> digit[terminal] -- + p3 -- p4 -- p5 -> E[terminal] -- q1 ->[vh path] + {[nodes={yshift=7mm}] + "+"[terminal], q2, "-"[terminal] + } -> [hv path] + q3 -- /unsigned integer [nonterminal] -- p6 -> /; + + p1 ->[skip loop=5mm] p4; + p3 ->[skip loop=-5mm] p2; + p5 ->[skip loop=-11mm] p6; + + q1 -- q2 -- q3; % make these edges plain }; - - { [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} + + + +% \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 ends 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} |