2

I am using the solution form Obstacles to simulating an amsmath matrix by a TiKZ matrix of math nodes to create a tikz matrix in the style of a bmatrix.

I would like to leave a little extra space after the last line and thought that using \\[1.5ex] should do the job:

\matrix (m) {
   1 &  4 \\ 
   7 & 10 \\ 
  13 & 16 \\[1.5ex]% <--- This seems to have no effect.
};

but that does not seem to have any effect. Using this optional parameter to any line but the last seems to work.

enter image description here

The bmatrix version behaves as desired.

Related Question

Code:

\documentclass{article}
\usepackage{mathtools}% for amsmath {bmatrix}
\usepackage{tikz}
\usetikzlibrary{matrix}

%% https://tex.stackexchange.com/questions/26866/obstacles-to-simulating-an-amsmath-matrix-by-a-tikz-matrix-of-math-nodes \newlength\mtxrowsep \setlength\mtxrowsep{1.5ex} \newlength\mtxcolsep \setlength\mtxcolsep{2\arraycolsep}

\tikzset{ ams/.style={ baseline=-.7ex, every delimiter/.style={yshift=-1pt}, every left delimiter/.style={xshift=2pt}, every right delimiter/.style={xshift=-2pt}, every node/.style={inner sep=0pt}, }, ams matrix/.style={ inner sep=1pt, column sep=\mtxcolsep, row sep=\mtxrowsep, % Following is also commented at https://tex.stackexchange.com/questions/26866 %ampersand replacement=&amp;, matrix of math nodes, }, bmatrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={[}, right delimiter={]}, } }, Bmatrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={\lbrace}, right delimiter={\rbrace}, } }, pmatrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={(}, right delimiter={)}, } }, vmatrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={|}, right delimiter={|}, } }, Vmatrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={|}, right delimiter={|}, } }, }

%% This does not seem to be necessary here %\let\matamp=& % %\catcode`&amp;=13 %\makeatletter %\def&{\iftikz@is@matrix % \pgfmatrixnextcell % \else % \matamp % \fi} %\makeatother

\begin{document} \hspace{0.2em} \begin{tikzpicture}[bmatrix] \matrix (m) { 1 & 4 \ 7 & 10 \ 13 & 16 \[1.5ex]% <--- This seems to have no effect. }; \end{tikzpicture} %% ---------------- \hspace{0.3em} $\begin{bmatrix} \smash{1} & \smash{4} \ 7 & 10 \ 13 & 16 \[1.5ex] \end{bmatrix}$

tikz matrix \hspace*{0.6em} bmatrix

\end{document}

Temporary Addendum:

I attempted to use Qrrbrbirlbel's solution, but ran into a problem : the coordinates of the nodes are no longer where tikz thinks they are. Using the preamble provided in the answer with the following code, it seems that the nodes (eg. m-1-1.north west) are shifted:

enter image description here

\newcommand{\FillMatrix}{%
\fill [rounded corners=3pt, fill opacity=.35, fill=green!80] 
           ([shift={(0pt, 2pt)}]m-1-1.north west) 
        -- ([shift={(0pt,-2pt)}]m-2-1.south west)
        -- ([shift={(2pt,-2pt)}]m-2-2.south east)
        -- ([shift={(2pt, 0pt)}]m-2-2.north east)
        -- cycle;
}%

\begin{document} \hspace{0.2em} \begin{tikzpicture}[bmatrix] \matrix (m) { 1 & 4 \ 7 & 10 \ 13 & 16 \[-2pt] }; \FillMatrix \end{tikzpicture} %% ---------------- \hspace{0.3em} \begin{tikzpicture}[bmatrix, matrix bottom crcr] \matrix (m) { 1 & 4 \ 7 & 10 \ 13 & 16 \[-2pt] }; \FillMatrix \end{tikzpicture}

\hspace{0.6em} default \hspace{0.6em} matrix bottom crcr

\end{document}

Peter Grill
  • 223,288
  • 1
    13 & 16 \\[0ex]\\ works, you can then adjust the length as required – David Carlisle Jan 03 '24 at 21:36
  • 1
    Seems like a duplicate of Q71328 unless you want a better solution (it will add another row sep if you use an extra \\) or a more automatic approach (like an add bottom space=1.5ex). – Qrrbrbirlbel Jan 03 '24 at 23:30
  • @DavidCarlisle: That sort of works, but difficult to add a small amount of space. Also the size seems to be quantized. See of instance the difference between \\[-1.14pt] \\ and \\[-1.15pt] \\. What is going on? – Peter Grill Jan 04 '24 at 05:05
  • @Qrrbrbirlbel: I would be ok with the another row sep as long as I could take it away with a negative amount. Perhaps that is the issues with the quantized jumps I am seeing. – Peter Grill Jan 04 '24 at 05:07
  • yes more of a quick workaround than an answer – David Carlisle Jan 04 '24 at 08:22

1 Answers1

3

The last [<vspace>] has no effect because PGF simply doesn't execute the same code as it would for a normal \\. It does evaluate it and save it so we can use it in the below patch. When that is done it checks whether a } (= \egroup) follows which indicates the end of the matrix content.

If it doesn't, after a \cr it will execute some \vskips according to the sizes of the rows as well whether between origins or between borders was used and then proceed with the next row.

If it does, it just ends the row (\cr) and ends the matrix (\pgf@end@matrix). We can patch in the same \vskip procedure, though.

(A PGF matrix is implemented via \halign which is why you see \crs and \noaligns in the code.)


For safety, I'll add a toggle matrix bottom crcr for this so that you can disable it in case something doesn't work properly with other matrices.

Code

\documentclass{article}
\usepackage{mathtools}% for amsmath {bmatrix}
\usepackage{tikz}
\usetikzlibrary{matrix}

%% https://tex.stackexchange.com/questions/26866/obstacles-to-simulating-an-amsmath-matrix-by-a-tikz-matrix-of-math-nodes \newlength\mtxrowsep \setlength\mtxrowsep{1.5ex} \newlength\mtxcolsep \setlength\mtxcolsep{2\arraycolsep}

\tikzset{ ams/.style={ baseline=-.7ex, every delimiter/.style={yshift=-1pt}, every left delimiter/.style={xshift=2pt}, every right delimiter/.style={xshift=-2pt}, every node/.style={inner sep=0pt}, }, ams matrix/.style={ inner sep=1pt, column sep=\mtxcolsep, row sep=\mtxrowsep, matrix of math nodes, }, create ams matrix/.style n args={3}{#1matrix/.style={ ams, every matrix/.style={ ams matrix, left delimiter={#2}, right delimiter={#3}}}}, create ams matrix/.list={b[], B\lbrace\rbrace, p(), v||, V||}, }

\makeatletter \let\pgf@matrix@finish@line@orig\pgf@matrix@finish@line \tikzset{ matrix bottom crcr/.is choice, matrix bottom crcr/.default=enabled, matrix bottom crcr/enabled/.code= \let\pgf@matrix@finish@line\qrr@pgf@matrix@finish@line \def\pgf@matrix@last@line@y{\ifpgf@matrix@noendrow@skip0pt\else\the\pgf@y\fi}, matrix bottom crcr/disabled/.code= \let\pgf@matrix@finish@line\pgf@matrix@finish@line@orig \def\pgf@matrix@last@line@y{0pt}} \def\qrr@pgf@matrix@finish@line{% \global\pgf@y=\pgf@y% \pgf@ya=-\pgf@y% \global\advance\pgf@ya by\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname% \expandafter\xdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{\the\pgf@ya}% \pgfutil@ifnextchar\egroup{\pgf@matrix@eom@found}{\pgf@matrix@no@eom@found}% Qrr: change }% \def\pgf@matrix@eom@found{% Qrr: overwrite (unused before) \cr \unless\ifpgf@matrix@noendrow@skip \noalign{% \vskip\pgf@y \ifpgf@matrix@fixed % Qrr: “between borders” \vskip\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname% unskip \vskip\pgf@y \pgf@y=-\pgf@y \expandafter\xdef\csname pgf@matrix@miny\the\pgfmatrixcurrentrow\endcsname{\the\pgf@y}% \fi }% \fi \pgf@end@matrix }%

\usepackage{etoolbox} \patchcmd\pgf@matrix@compute@origin{0pt}{\pgf@matrix@last@line@y}{}{\PatchFailed} \def\pgf@matrix@last@line@y{0pt} \newif\ifpgf@matrix@noendrow@skip \patchcmd\pgfmatrixendrow {\pgfutil@ifnextchar[{\pgfmatrixendrow@skip}{\pgf@matrix@finish@line}} {\pgfutil@ifnextchar[{\global\pgf@matrix@noendrow@skipfalse\pgfmatrixendrow@skip} {\global\pgf@matrix@noendrow@skiptrue\pgf@matrix@finish@line}} {}{\PatchFailed} \makeatother

\newcommand{\FillMatrix}{% \fill [rounded corners=3pt, fill opacity=.35, fill=green!80] ([shift={(0pt, 2pt)}]m-1-1.north west) -- ([shift={(0pt,-2pt)}]m-2-1.south west) -- ([shift={(2pt,-2pt)}]m-2-2.south east) -- ([shift={(2pt, 0pt)}]m-2-2.north east) -- cycle; }% \newcommand*\AMSMATH[1]{$\begin{bmatrix}\smash{1} & \smash{4} \ 7 & 10 \ 13 & 16 \#1\end{bmatrix}$} \begin{document} no patch, \verb|\|:\par \begin{tikzpicture}[bmatrix] \matrix (m) { 1 & 4 \ 7 & 10 \ 13 & 16 \ }; \FillMatrix \end{tikzpicture}\AMSMATH{}\medskip

no patch, \verb|\[1.5ex]|:\par \begin{tikzpicture}[bmatrix] \matrix (m) [row sep=0pt]{ 1 & 4 \ 7 & 10 \ 13 & 16 \[1.5ex] }; \FillMatrix \end{tikzpicture}\AMSMATH{[1.5ex]}\bigskip

patch, \verb|\|:\par \begin{tikzpicture}[bmatrix, matrix bottom crcr] \matrix (m) { 1 & 4 \ 7 & 10 \ 13 & 16 \ }; \FillMatrix \end{tikzpicture}\AMSMATH{}\medskip

patch, \verb|\[1.5ex]| (row sep + arg inserted) (\AmS: \verb|[3.0ex]|):\par \begin{tikzpicture}[bmatrix, matrix bottom crcr] \matrix (m) [row sep=0pt]{ 1 & 4 \ 7 & 10 \ 13 & 16 \[1.5ex] }; \FillMatrix \end{tikzpicture}\AMSMATH{[3ex]}\medskip

patch, \verb|\[-\pgfmatrixrowsep]| (row sep compensated):\par \begin{tikzpicture}[bmatrix, matrix bottom crcr] \matrix (m) [row sep=0pt]{ 1 & 4 \ 7 & 10 \ 13 & 16 \[-\pgfmatrixrowsep] }; \FillMatrix \end{tikzpicture} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • Looks promising, but noticed a slight problem with this solution -- edited the question to show it. Also, not sure why the jumps in the size of the bracket are hard to control. – Peter Grill Jan 17 '24 at 05:17
  • @PeterGrill Ugh, yeah, not surprising. I've digged a bit deeper and it's annoying. I believe, the matrix wasn't even placed correctly because there is some hard-coded 0pt in the end-matrix code which now is not correct anymore. I've added an etoolbox-powered patch for this. With the patch enabled, no [] doesn't change anything. Using [<val>] adds another row sep plus that <val>. It's weird, the code is not easy (and hasn't been really updated in the last 10 years). It might be better to create a node shape that has two inner y seps: … – Qrrbrbirlbel Jan 17 '24 at 18:18
  • … one for the bottom and one for the top. That way you could control the vertical dimension much better than with the extra <val> (though we could add another patch to my answer that automatically subtracts the row sep). After all, there is no way to control the top space in the same way without adjusting all nodes of row 1. – Qrrbrbirlbel Jan 17 '24 at 18:20