分别调整 tikz 矩阵左分隔符和右分隔符的顶部和底部

分别调整 tikz 矩阵左分隔符和右分隔符的顶部和底部

我正在使用解决方案形式使用 TiKZ 数学节点矩阵模拟 amsmath 矩阵的障碍创建一个tikz matrix样式为 的bmatrix。这个方法很好用,默认规范为

every delimiter/.style={yshift=-1pt}.

但有时我想手动分别调整左/右分隔符的顶部和左/右分隔符的底部,因此尝试找到一种tikz方法来实现这一点。我可以黑客可以通过放置phantom垂直线来实现,但如果有 tikz 样式就更好了。理想情况下,解决方案应具有以下样式:

left delimiter top y shift=
left delimiter bottom y shift=
right delimiter top y shift=
right delimiter bottom y shift=

顶部和底部分隔符的相关内容也类似(此处未使用)

top delimiter left x shift=
top delimiter right x shift=
bottom delimiter left x shift=
bottom delimiter right x shift=

需要明确的是,我并不期待自动化解决方案,而是根据需要手动调整分隔符。

下面是做作的例如(令我惊讶的是,bmatrix默认情况下会产生所需的结果,但不明白如何产生),其中两种情况下矩阵的第一行都是

\smash{1} &  \smash{4} \\ 

在此处输入图片描述

代码:

\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=\&,
    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
%\let\matamp=&
%
%\catcode`\&=13
%\makeatletter
%\def&{\iftikz@is@matrix
%  \pgfmatrixnextcell
%  \else
%  \matamp
%  \fi}
%\makeatother


\begin{document}
\hspace*{0.2em}
\begin{tikzpicture}[bmatrix]
\matrix (m) {
   \smash{1} &  \smash{4} \\ 
   7 & 10 \\ 
  13 & 16 \\
};
\end{tikzpicture}
%% ----------------
\hspace*{0.3em}
$\begin{bmatrix}
   \smash{1} &  \smash{4} \\ 
   7 & 10 \\ 
  13 & 16 \\
\end{bmatrix}$

tikz matrix \hspace*{0.6em} bmatrix

\end{document}

答案1

我只能用两个额外的键来重新实现分隔符:delim' topdelim' bot

不知道这种不对称方法(左右和上下有不同的值)是一个好主意还是只是让它变得有点复杂……

代码

\documentclass{article}
\usepackage{mathtools}% for amsmath {bmatrix}
\usepackage{tikz}
\usetikzlibrary{matrix}
\tikzset{% similar to axis_height of TikZ-CD
  vcenter/.code=\begingroup$\relax$\pgfmathreturn
                  \the\fontdimen22\textfont2\endgroup
                \pgfsetbaseline{-\pgfmathresult pt}}
\tikzset{
  delimiter' top/.code=\pgfmathparse{#1}% self-evaluating
    \pgfkeyssetevalue{/tikz/delimiter' top}{\pgfmathresult pt},
  delimiter' bot/.code=\pgfmathparse{#1}% self-evaluating
    \pgfkeyssetevalue{/tikz/delimiter' bot}{\pgfmathresult pt},
  delimiter' top=0pt, delimiter' bot=0pt}
\makeatletter
\tikzset{
  left delimiter'/.style={delimiter'={south east}{south west}
    {every delimiter,every left delimiter,every left delimiter'}
    {south}{north}{#1}{.}{\pgf@y}},
  right delimiter'/.style={delimiter'={south west}{south east}
    {every delimiter,every right delimiter,every right delimiter'}
    {south}{north}{.}{#1}{\pgf@y}},
  above delimiter'/.style={delimiter'={south east}{north west}
    {every delimiter,every above delimiter,every above delimiter',rotate=-90}
    {west}{east}{#1}{.}{\pgf@x}},
  below delimiter'/.style={delimiter'={south west}{south west}
    {every delimiter,every below delimiter,every below delimiter',rotate=-90}
    {west}{east}{.}{#1}{\pgf@x}},
  every delimiter'/.style={outer sep=+0pt,inner sep=+0pt,path only},
  delimiter'/.style n args={8}{append after command={
    \bgroup% similar to original delims
      \pgfextra{\let\tikz@save@last@fig@name\tikz@last@fig@name
                \tikz@node@is@a@labelfalse}
      node[every delimiter',anchor=#1,at=(\tikz@last@fig@name.#2),#3,%
        yshift=-\pgfkeysvalueof{/tikz/delimiter' bot}]{%
        {\nullfont\pgf@process{%
          \pgfpointdiff{\pgfpointanchor{\tikz@last@fig@name}{#4}}
                       {\pgfpointanchor{\tikz@last@fig@name}{#5}}}}%
        $\left#6\vcenter{%
          \hrule height\dimexpr.5#8+\pgfkeysvalueof{/tikz/delimiter' top}\relax
                  depth\dimexpr.5#8+\pgfkeysvalueof{/tikz/delimiter' bot}\relax
                  width0pt}\right#7$}
      \pgfextra{\global\let\tikz@last@fig@name\tikz@save@last@fig@name}
    \egroup}}}
\makeatother
\tikzset{
  every left delimiter'/.style={
    delimiter' top=  \pgfkeysvalueof{/tikz/left  delimiter top    yshift},
    delimiter' bot=-(\pgfkeysvalueof{/tikz/left  delimiter bottom yshift})},
  every right delimiter'/.style={
    delimiter' top=  \pgfkeysvalueof{/tikz/right delimiter top    yshift},
    delimiter' bot=-(\pgfkeysvalueof{/tikz/right delimiter bottom yshift})},
  every above delimiter'/.style={
    delimiter' top=  \pgfkeysvalueof{/tikz/above delimiter right  xshift},
    delimiter' bot=-(\pgfkeysvalueof{/tikz/above delimiter left   xshift})},
  every below delimiter'/.style={
    delimiter' top=  \pgfkeysvalueof{/tikz/below delimiter right  xshift},
    delimiter' bot=-(\pgfkeysvalueof{/tikz/below delimiter left   xshift})},
  left  delimiter top    yshift/.initial=0pt,
  left  delimiter bottom yshift/.initial=0pt,
  right delimiter top    yshift/.initial=0pt,
  right delimiter bottom yshift/.initial=0pt,
  above delimiter left   xshift/.initial=0pt,
  above delimiter right  xshift/.initial=0pt,
  below delimiter left   xshift/.initial=0pt,
  below delimiter right  xshift/.initial=0pt}

\tikzset{
  ams/.style={
    vcenter, inner sep=+0pt,
    every       delimiter/.style={yshift=+-1pt},
    every left  delimiter/.style={xshift=+ 2pt},
    every right delimiter/.style={xshift=+-2pt}},
  ams matrix/.style={
    every outer matrix/.append style={inner sep=+1pt},
    matrix anchor=center, matrix of math nodes,
    row sep=1.5ex, column sep=2\arraycolsep},
  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\|\|},
  ams delim' top/.style={
    left  delimiter top    yshift={#1}, right delimiter top    yshift={#1}},
  ams delim' bot/.style={
    left  delimiter bottom yshift={#1}, right delimiter bottom yshift={#1}}}
\begin{document}
\hspace*{0.2em}
\tikz[bmatrix, ams delim' top=2ex]
  \matrix {
     \smash{1} & \smash{4} \\
            7  &       10  \\
           13  &       16  \\
  };
%% ----------------
\hspace*{0.3em}
$\begin{bmatrix}
  \smash{1} & \smash{4} \\
         7  &       10  \\
        13  &       16
\end{bmatrix}$

tikz matrix \hspace*{0.6em} bmatrix
\bigskip

\noindent
\foreach \top in {-3, -2.5, ..., 3}{
  \tikz[bmatrix, ams delim' top=\top ex, ampersand replacement=\&]
    \matrix[label=below:\tiny\color{gray}$\top$ex]{
      \smash{1} \& \smash{4} \\ 7 \& 10 \\ 13 \& 16 \\};}
%
\tikz[
  vcenter,
  every below delimiter/.style={yshift=1.5ex},
  below delimiter left  xshift= 1ex,
  below delimiter right xshift=-1ex,
  above delimiter left  xshift= 1ex,
  above delimiter right xshift=-1ex,
]\matrix[
  matrix of math nodes, above delimiter'=[, below delimiter'={]},
]{\smash{1} & \smash{4} \\ 7 & 10 \\ 13 & 16 \\};
\end{document}

输出

在此处输入图片描述

相关内容