我正在使用解决方案形式使用 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' top
和delim' 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}