summaryrefslogtreecommitdiff
path: root/graphics/pgf/base/doc/text-en/pgfmanual-en-base-matrices.tex
blob: c35a345753d3081f8a7f17ab294544a95ce26d54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
% Copyright 2019 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{Matrices}
\label{section-base-matrices}

\begin{pgfmodule}{matrix}
The present section documents the commands of this module.
\end{pgfmodule}

\subsection{Overview}

Matrices are a mechanism for aligning several so-called cell pictures
horizontally and vertically. The resulting alignment is placed in a normal node
and the command for creating matrices, |\pgfmatrix|, takes options very similar
to the |\pgfnode| command.

In the following, the basic idea behind the alignment mechanism is explained
first. Then the command |\pgfmatrix| is explained. At the end of the section,
additional ways of modifying the width of columns and rows are discussed.


\subsection{Cell Pictures and Their Alignment}

A matrix consists of rows of \emph{cells}. Cells are separated using the
special command |\pgfmatrixnextcell|, rows are ended using the command
|\pgfmatrixendrow| (the command |\\| is set up to mean the same as
|\pgfmatrixendrow| by default). Each cell contains a \emph{cell picture},
although cell pictures are not complete pictures as they lack layers. However,
each cell picture has its own bounding box like a normal picture does. These
bounding boxes are important for the alignment as explained in the following.

Each cell picture will have an origin somewhere in the picture (or even outside
the picture). The position of these origins are important for the alignment: On
each row the origins will be on the same horizontal line and for each column
the origins will also be on the same vertical line. These two requirements mean
that the cell pictures may need to be shifted around so that the origins wind
up on the same lines. The top of a row is given by the top of the cell picture
whose bounding box's maximum $y$-position is largest. Similarly, the bottom of
a row is given by the bottom of the cell picture whose bounding box's minimum
$y$-position is the most negative. Similarly, the left end of a column is given
by the left end of the cell whose bounding box's $x$-position is the most
negative; and similarly for the right end of a column.
%
\begin{codeexample}[]
\begin{tikzpicture}[x=3mm,y=3mm,fill=blue!50]
  \def\atorig#1{\node[black] at (0,0) {\tiny #1};}

  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{}
    {
      \fill (0,-3)  rectangle (1,1);\atorig1 \pgfmatrixnextcell
      \fill (-1,0)  rectangle (1,1);\atorig2 \pgfmatrixnextcell
      \fill (-1,-2) rectangle (0,0);\atorig3 \pgfmatrixnextcell
      \fill (-1,-1) rectangle (0,3);\atorig4 \\
      \fill (-1,0)  rectangle (4,1);\atorig5 \pgfmatrixnextcell
      \fill (0,-1)  rectangle (1,1);\atorig6 \pgfmatrixnextcell
      \fill (0,0)   rectangle (1,4);\atorig7 \pgfmatrixnextcell
      \fill (-1,-1) rectangle (0,0);\atorig8 \\
    }
\end{tikzpicture}
\end{codeexample}


\subsection{The Matrix Command}

All matrices are typeset using the following command:

\begin{command}{\pgfmatrix\marg{shape}\marg{anchor}\marg{name}\marg{usage}\marg{shift}\marg{pre-code}\marg{matrix cells}}
    This command creates a node that contains a matrix. The name of the node is
    \meta{name}, its shape is \meta{shape} and the node is anchored at
    \meta{anchor}.

    The \meta{matrix cell} parameter contains the cells of the matrix. In each
    cell drawing commands may be given, which create a so-called cell picture.
    For each cell picture a bounding box is computed and the cells are aligned
    according to the rules outlined in the previous section.

    The resulting matrix is used as the |text| box of the node. As for a normal
    node, the \meta{usage} commands are applied, so that the path(s) of the
    resulting node is (are) stroked or filled or whatever.


    \medskip
    \textbf{Specifying the cells and rows.\ }
    Even though this command uses |\halign| internally, there are two special
    rules for indicating cells:
    %
    \begin{enumerate}
        \item Cells in the same row must be separated using the macro
            |\pgfmatrixnextcell| rather than |&|. Using |&| will result in an
            error message.

            However, you can make |&| an active character and have it expand to
            |\pgfmatrixnextcell|. This way, it will ``look'' as if |&| is used.
        \item Rows are ended using the command |\pgfmatrixendrow|, but |\\| is
            set up to mean the same by default. However, some environments like
            |{minipage}| redefine |\\|, so it is good to have
            |\pgfmatrixendrow| as a ``fallback''.
        \item Every row \emph{including the last row} must be ended using the
            command |\\| or |\pgfmatrixendrow|.
    \end{enumerate}

    Both |\pgfmatrixnextcell| and |\pgfmatrixendrow| (and, thus, also |\\|)
    take an optional argument as explained in the
    Section~\ref{section-matrix-spacing}
    %
\begin{codeexample}[]
\begin{tikzpicture}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{}
    {
      \node {a}; \pgfmatrixnextcell \node {b}; \pgfmatrixendrow
      \node {c}; \pgfmatrixnextcell \node {d}; \pgfmatrixendrow
    }
\end{tikzpicture}
\end{codeexample}


    \medskip
    \textbf{Anchoring matrices at nodes inside the matrix.\ }
    The parameter \meta{shift} is an additional negative shift for the node.
    Normally, such a shift could be given beforehand (that is, the shift could
    be preapplied to the current transformation matrix). However, when
    \meta{shift} is evaluated, you can refer to \emph{temporary} positions of
    nodes inside the matrix. In detail, the following happens: When the matrix
    has been typeset, all nodes in the matrix temporarily get assigned their
    positions in the matrix box. The origin of this coordinate system is at the
    left baseline end of the matrix box, which corresponds to the |text|
    anchor. The position \meta{shift} is then interpreted inside this
    coordinate system and then used for shifting.

    This allows you to use the parameter \meta{shift} in the following way: If
    you use |text| as the \meta{anchor} and specify
    |\pgfpointanchor{inner node}{some anchor}| for the parameter \meta{shift},
    where |inner node| is a node that is created in the matrix, then the whole
    matrix will be shifted such that |inner node.some anchor| lies at the
    origin of the whole picture.


    \medskip
    \textbf{Rotations and scaling.\ }
    The matrix node is never rotated or scaled, because the current coordinate
    transformation matrix is reset (except for the translational part) at the
    beginning of |\pgfmatrix|. This is intentional and will not change in the
    future. If you need to rotate or scale the matrix, you must install an
    appropriate canvas transformation yourself.

    However, nodes and stuff inside the cell pictures can be rotated and scaled
    normally.


    \medskip
    \textbf{Callbacks.\ }
    At the beginning and at the end of each cell the special macros
    |\pgfmatrixbegincode|, |\pgfmatrixendcode| and possibly
    |\pgfmatrixemptycode| are called. The effect is explained in
    Section~\ref{section-matrix-callbacks}.


    \medskip
    \textbf{Executing extra code.\ }
    The parameter \meta{pre-code} is executed at the beginning of the outermost
    \TeX-group enclosing the matrix node. It is inside this \TeX-group, but
    outside the matrix itself. It can be used for different purposes:
    %
    \begin{enumerate}
        \item It can be used to simplify the next cell macro. For example,
            saying |\let\&=\pgfmatrixnextcell| allows you to use |\&| instead
            of |\pgfmatrixnextcell|. You can also set the catcode of |&| to
            active.
        \item It can be used to issue an |\aftergroup| command. This allows you
            to regain control after the |\pgfmatrix| command. (If you do not
            know the |\aftergroup| command, you are probably blessed with a
            simple and happy life.)
    \end{enumerate}


    \medskip
    \textbf{Special considerations concerning macro expansion.\ }
    As said before, the matrix is typeset using |\halign| internally. This
    command does a lot of strange and magic things like expanding the first
    macro of every cell in a most unusual manner. Here are some effects you may
    wish to be aware of:
    %
    \begin{itemize}
        \item It is not necessary to actually mention |\pgfmatrixnextcell| or
            |\pgfmatrixendrow| inside the \meta{matrix cells}. It suffices that
            the  macros inside \meta{matrix cells} expand to these macros
            sooner or later.
        \item In particular, you can define clever macros that insert columns
            and rows as needed for special effects.
    \end{itemize}
\end{command}


\subsection{Row and Column Spacing}
\label{section-matrix-spacing}

It is possible to control the space between columns and rows rather detailedly.
Two commands are important for the row spacing and two commands for the column
spacing.

\begin{command}{\pgfsetmatrixcolumnsep\marg{sep list}}
    This macro sets the default separation list for columns. The details of the
    format of this list are explained in the description of the next command.
\end{command}

\begin{command}{\pgfmatrixnextcell\opt{\oarg{additional sep list}}}
    This command has two purposes: First, it is used to separate cells. Second,
    by providing the optional argument \meta{additional sep list} you can
    modify the spacing between the columns that are separated by this command.

    The optional \meta{additional sep list} may only be provided when the
    |\pgfmatrixnextcell| command starts a new column. Normally, this will only
    be the case in the first row, but sometimes a later row has more elements
    than the first row. In this case, the |\pgfmatrixnextcell| commands that
    start the new columns in the later row may also have the optional argument.
    Once a column has been started, subsequent uses of this optional argument
    for the column have no effect.

    To determine the space between the two columns that are separated by
    |\pgfmatrixnextcell|, the following algorithm is executed:
    %
    \begin{enumerate}
        \item Both the default separation list (as set up by
            |\pgfsetmatrixcolumnsep|) and the \meta{additional sep list} are
            processed, in this order. If the \meta{additional sep list}
            argument is missing, only the default separation list is processed.
        \item Both lists may contain dimensions, separated by commas, as well
            as occurrences of the keywords |between origins| and 
            |between borders|.
        \item All dimensions occurring in either list are added together to
            arrive at a dimension $d$.
        \item The last occurrence of either of the keywords is located. If
            neither keyword is present, we proceed as if |between borders| were
            present.
    \end{enumerate}
    %
    At the end of the algorithm, a dimension $d$ has been computed and one of
    the two \emph{modes} |between borders| and |between origins| has been
    determined. Depending on which mode has been determined, the following
    happens:
    %
    \begin{itemize}
        \item For the |between borders| mode, an additional horizontal space of
            $d$ is added between the two columns. Note that $d$ may be
            negative.
        \item For the |between origins| mode, the spacing between the two
            columns is computed differently: Recall that the origins of the
            cell pictures in both pictures lie on two vertical lines. The
            spacing between the two columns is set up such that the horizontal
            distance between these two lines is exactly $d$.

            This mode may only be used between columns \emph{already introduced
            in the first row}.
    \end{itemize}
    %
    All of the above rules boil down to the following effects:
    %
    \begin{itemize}
        \item A default spacing between columns should be set up using
            |\pgfsetmatrixcolumnsep|. For example, you might say
            |\pgfsetmatrixcolumnsep{5pt}| to have columns spaced apart by
            |5pt|. You could say
            %
\begin{verbatim}
\pgfsetmatrixcolumnsep{1cm,between origins}
\end{verbatim}
            %
            to specify that horizontal space between the origins of cell
            pictures in adjacent columns should be 1cm by default -- regardless
            of the actual size of the cell pictures.
        \item You can now use the optional argument of |\pgfmatrixnextcell| to
            locally overrule the spacing between two columns. By saying
            |\pgfmatrixnextcell[5pt]| you \emph{add} 5pt to the space between
            of the two columns, regardless of the mode.

            You can also (locally) change the spacing mode for these two
            columns. For example, even if the normal spacing mode is
            |between origins|, you can say
            %
\begin{verbatim}
\pgfmatrixnextcell[5pt,between borders]
\end{verbatim}
            %
            to locally change the mode for these columns to |between borders|.
    \end{itemize}
    %
\begin{codeexample}[]
\begin{tikzpicture}[every node/.style=draw]
  \pgfsetmatrixcolumnsep{1mm}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{\let\&=\pgfmatrixnextcell}
  {
    \node {8}; \&[2mm] \node{1}; \&[-1mm] \node {6}; \\
    \node {3}; \&      \node{5}; \&       \node {7}; \\
    \node {4}; \&      \node{9}; \&       \node {2}; \\
  }
\end{tikzpicture}
\end{codeexample}
    %
\begin{codeexample}[]
\begin{tikzpicture}[every node/.style=draw]
  \pgfsetmatrixcolumnsep{1mm}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{\let\&=\pgfmatrixnextcell}
  {
    \node {8}; \&[2mm] \node(a){1}; \&[1cm,between origins] \node(b){6}; \\
    \node {3}; \&      \node   {5}; \&                      \node   {7}; \\
    \node {4}; \&      \node   {9}; \&                      \node   {2}; \\
  }
  \draw [<->,red,thick,every node/.style=] (a.center) -- (b.center)
        node [above,midway] {11mm};
\end{tikzpicture}
\end{codeexample}
    %
\begin{codeexample}[]
\begin{tikzpicture}[every node/.style=draw]
  \pgfsetmatrixcolumnsep{1cm,between origins}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{\let\&=\pgfmatrixnextcell}
  {
    \node (a) {8}; \& \node (b) {1}; \&[between borders] \node (c) {6}; \\
    \node     {3}; \& \node     {5}; \&                  \node     {7}; \\
    \node     {4}; \& \node     {9}; \&                  \node     {2}; \\
  }
  \begin{scope}[every node/.style=]
    \draw [<->,red,thick] (a.center) -- (b.center) node [above,midway] {10mm};
    \draw [<->,red,thick] (b.east) -- (c.west) node [above,midway]
    {10mm};
  \end{scope}
\end{tikzpicture}
\end{codeexample}
    %
\end{command}

The mechanism for the between-row-spacing is the same, only the commands are
called differently.

\begin{command}{\pgfsetmatrixrowsep\marg{sep list}}
    This macro sets the default separation list for rows.
\end{command}

\begin{command}{\pgfmatrixendrow\opt{\oarg{additional sep list}}}
    This command ends a line. The optional \meta{additional sep list} is used
    to determine the spacing between the row being ended and the next row. The
    modes and the computation of $d$ is done in the same way as for columns.
    For the last row the optional argument has no effect.

    Inside matrices (and only there) the command |\\| is set up to mean the
    same as this command.
\end{command}


\subsection{Callbacks}
\label{section-matrix-callbacks}

There are three macros that get called at the beginning and end of cells. By
redefining these macros, which are empty by default, you can change the
appearance of cells in a very general manner.

\begin{command}{\pgfmatrixemptycode}
    This macro is executed for empty cells. This means that \pgfname\ uses some
    macro magic to determine whether a cell is empty (it immediately ends with
    |\pgfmatrixemptycode| or |\pgfmatrixendrow|) and, if so, put this macro
    inside the cell.
    %
\begin{codeexample}[]
\begin{tikzpicture}
  \def\pgfmatrixemptycode{\node{empty};}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{\let\&=\pgfmatrixnextcell}
  {
    \node {a}; \&           \& \node {b}; \\
               \& \node{c}; \& \node {d}; \& \\
  }
\end{tikzpicture}
\end{codeexample}
    %
    As can be seen, the macro is not executed for empty cells at the end of row
    when columns are added only later on.
\end{command}

\begin{command}{\pgfmatrixbegincode}
    This macro is executed at the beginning of non-empty cells.
    Correspondingly, |\pgfmatrixendcode| is added at the end of every non-empty
    cell.
    %
\begin{codeexample}[]
\begin{tikzpicture}
  \def\pgfmatrixbegincode{\node[draw]\bgroup}
  \def\pgfmatrixendcode{\egroup;}
  \pgfmatrix{rectangle}{center}{mymatrix}
    {\pgfusepath{}}{\pgfpointorigin}{\let\&=\pgfmatrixnextcell}
  {
    a \& b \& c \\
    d \&   \& e \\
  }
\end{tikzpicture}
\end{codeexample}
    %
    Note that between |\pgfmatrixbegincode| and |\pgfmatrixendcode| there will
    \emph{not} only be the contents of the cell. Rather, \pgfname\ will add
    some (invisible) commands for book-keeping purposes that involve |\let| and
    |\gdef|. In particular, it is not a good idea to have |\pgfmatrixbegincode|
    end with |\csname| and |\pgfmatrixendcode| start with |\endcsname|.
\end{command}

\begin{command}{\pgfmatrixendcode}
    See the explanation above.
\end{command}

The following two counters allow you to access the current row and current
column in a callback:

\begin{command}{\pgfmatrixcurrentrow}
    This counter stores the current row of the current cell of the matrix. Do
    not even think about changing this counter.
\end{command}

\begin{command}{\pgfmatrixcurrentcolumn}
    This counter stores the current column of the current cell of the matrix.
\end{command}


%%% Local Variables:
%%% mode: latex
%%% TeX-master: "pgfmanual"
%%% End: