% 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: