如何为 TikZ 矩阵创建诸如“列...到...”之类的键

如何为 TikZ 矩阵创建诸如“列...到...”之类的键

我有一个节点样式,我想将其应用于节点矩阵的许多(但不是全部)单元格/列/行。目前,对于我想要应用样式的每一列或单元格,我将样式声明为:

column 2/.style={column sep=-0.4pt},
column 3/.style={column sep=-0.4pt},
column 4/.style={column sep=-0.4pt},
column 5/.style={column sep=-0.4pt},
row 3 column 2/.style={my node style},
row 3 column 3/.style={my node style},
row 3 column 4/.style={my node style},
row 3 column 5/.style={my node style},
row 3 column 6/.style={my node style},

如果我可以写类似的东西,那就更方便了

column 2 to 5/.style={column sep=-0.4pt},
row 3 column 2 to 5/.style={my node style},
row 4 column 2 to 5/.style={my node style},

甚至更好(最后两个)

cell 3 2 to cell 4 5/.style={my node style},

这是一个 MWE,其中这样的键可以提高代码的可读性

\documentclass[border=6pt]{standalone}

\usepackage{amsmath}
\newcommand\abs[1]{\lvert#1\rvert}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{matrix}
\usetikzlibrary{arrows.meta}

\tikzset{%%
  >=Stealth,
  my node style/.style={%%
    minimum width=\dimexpr0.60in+12pt\relax,
    minimum height=\dimexpr0.30cm+12pt\relax,
    outer sep=0pt,
    draw},
  }

\begin{document}

\begin{tikzpicture}

  \matrix (TBL) [%%
                 matrix of nodes,
                 nodes={%%
                   align=center,
                   inner sep=0pt,
                   anchor=center},
                 column 2/.style={column sep=-0.4pt},
                 column 3/.style={column sep=-0.4pt},
                 column 4/.style={column sep=-0.4pt},
                 column 5/.style={column sep=-0.4pt},
                 row 3 column 2/.style={my node style},
                 row 3 column 3/.style={my node style},
                 row 3 column 4/.style={my node style},
                 row 3 column 5/.style={my node style},
                 row 3 column 6/.style={my node style},
                ]
  {
                        & {$(-\infty,-2)$}               & {$(-2,-1)$}                     & {$(-1,1)$}                    & {$(1,2)$}                       & {$(2,\infty)$}                 \\[2pt]
   {$\abs{x^{2}-1}=\,$} & |[my node style]| {$x^{2}-1 $} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$1-x^{2}$} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$x^{2}-1$}  \\[-0.4pt]
   {$\abs{x^{2}-4}=\,$} &                   {$x^{2}-4 $} &                   {$4-x^{2}$}   &                   {$4-x^{2}$} &                   {$4-x^{2}$}   &                   {$x^{2}-4$}  \\[2pt]
   {$g(x) =$}           & |[my node style]| {$ 3 $ }     & |[my node style]| {$ 2x^{2}-5$} & |[my node style]| {$ -3 $}    & |[my node style]| { $2x^{2}-5$} & |[my node style]| {$ 3 $}      \\
  };

\end{tikzpicture}

\end{document}

在此处输入图片描述

注意:我还试图避免必须在想要应用样式的每个单元格中明确声明样式,如上例中的第 2 行和第 4 行。

更新

我尝试将以下内容添加到我的序言中

\tikzset{%%
    column \the\pgfmatrixcurrentcolumn\space to \the\pgfmatrixcurrentcolumn/.try,
  }

但是当我尝试这样调用它时:

\begin{tikzpicture}

  \matrix (TBL) [%%
                 matrix of nodes,
                 nodes={%%
                   align=center,
                   inner sep=0pt,
                   anchor=center},
                 column 2/.style={column sep=-0.4pt},
                 column 3/.style={column sep=-0.4pt},
                 column 4/.style={column sep=-0.4pt},
                 column 5/.style={column sep=-0.4pt},
                 row 3 column 2/.style={my node style},
                 row 3 column 3/.style={my node style},
                 row 3 column 4/.style={my node style},
                 row 3 column 5/.style={my node style},
                 row 3 column 6/.style={my node style},
                 column 2 to 5/.style={red},
                ]
  {
                        & {$(-\infty,-2)$}               & {$(-2,-1)$}                     & {$(-1,1)$}                    & {$(1,2)$}                       & {$(2,\infty)$}                 \\[2pt]
   {$\abs{x^{2}-1}=\,$} & |[my node style]| {$x^{2}-1 $} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$1-x^{2}$} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$x^{2}-1$}  \\[-0.4pt]
   {$\abs{x^{2}-4}=\,$} &                   {$x^{2}-4 $} &                   {$4-x^{2}$}   &                   {$4-x^{2}$} &                   {$4-x^{2}$}   &                   {$x^{2}-4$}  \\[2pt]
   {$g(x) =$}           & |[my node style]| {$ 3 $ }     & |[my node style]| {$ 2x^{2}-5$} & |[my node style]| {$ -3 $}    & |[my node style]| { $2x^{2}-5$} & |[my node style]| {$ 3 $}      \\
  };

\end{tikzpicture}

没有明显的效果。

答案1

您可以使用/.list处理程序进行重复设置。您也可以将它们包装起来以应对更复杂的情况,但这里有两个操作供简单使用。在此处输入图片描述

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc,matrix,arrows.meta}

\def\abs#1{|#1|}
\tikzset{
  foo1/.style={column #1/.style={column sep=-0.4pt}},
  foo2/.style={row 3 column #1/.style={nodes=my node style}},
  >=Stealth,
  my node style/.style={%%
    minimum width=0.60in+12pt,
    minimum height=0.30cm+12pt,
    outer sep=0pt,
    draw},
  }


\begin{document}
\begin{tikzpicture}

  \matrix (TBL) [%%
                 matrix of nodes,
                 nodes={%%
                   align=center,
                   inner sep=0pt,
                   anchor=center},
  foo1/.list={2,...,5},
  foo2/.list={3,...,5}
                ]
  {
                        & {$(-\infty,-2)$}               & {$(-2,-1)$}                     & {$(-1,1)$}                    & {$(1,2)$}                       & {$(2,\infty)$}                 \\[2pt]
   {$\abs{x^{2}-1}=\,$} & |[my node style]| {$x^{2}-1 $} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$1-x^{2}$} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$x^{2}-1$}  \\[-0.4pt]
   {$\abs{x^{2}-4}=\,$} &                   {$x^{2}-4 $} &                   {$4-x^{2}$}   &                   {$4-x^{2}$} &                   {$4-x^{2}$}   &                   {$x^{2}-4$}  \\[2pt]
   {$g(x) =$}           & {$ 3 $ }                       & {$ 2x^{2}-5$}                   & {$ -3 $}                      & { $2x^{2}-5$}                   & {$ 3 $}      \\
  };
\end{tikzpicture}
\end{document}

答案2

这不是我想要的解决方案,但它确实有点儿达到我想要的效果。

使用该etoolbox包,我定义了两个宏:\foreachcell\foreachcolumn

\usepackage{etoolbox}
\makeatletter
\newcommand\foreachcell{\ae@foreach@cell}
\def\ae@foreach@cell from (#1,#2) to (#3,#4) do #5{%%
  \def\aecol{#2}%%
  \def\aerow{#1}%%
  \whileboolexpr{ not ( test { \ifnumcomp{\aecol}{=}{#4}} and test{\ifnumcomp{\aerow}{=}{#3}} ) }
  {
    #5
    \edef\aecol{\number\numexpr\aecol+1\relax}
    \ifnum\aecol>#4\relax
      \edef\aerow{\number\numexpr\aerow+1\relax}
      \edef\aecol{#2}
    \fi
  }
}
\newcommand\foreachcolumn{\ae@foreach@col}
\def\ae@foreach@col from #1 to #2 do #3{%%
  \def\aecol{#1}%%
  \whileboolexpr{ test {\ifnumcomp{\aecol}{<}{#2}} or test{\ifnumcomp{\aecol}{=}{#2}} }
  { #3
    \edef\aecol{\number\numexpr\aecol+1\relax}
  }}
\makeatother

然后在 MWE 中:

\documentclass[border=6pt]{standalone}

\usepackage{amsmath}
\newcommand\abs[1]{\lvert#1\rvert}

\usepackage{etoolbox}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{matrix}
\usetikzlibrary{arrows.meta}

\makeatletter
\newcommand\foreachcell{\ae@foreach@cell}
\def\ae@foreach@cell from (#1,#2) to (#3,#4) do #5{%%
  \def\aecol{#2}%%
  \def\aerow{#1}%%
  \whileboolexpr{ not ( test { \ifnumcomp{\aecol}{=}{#4}} and test{\ifnumcomp{\aerow}{=}{#3}} ) }
  {
    #5
    \edef\aecol{\number\numexpr\aecol+1\relax}
    \ifnum\aecol>#4\relax
      \edef\aerow{\number\numexpr\aerow+1\relax}
      \edef\aecol{#2}
    \fi
  }
}
\newcommand\foreachcolumn{\ae@foreach@col}
\def\ae@foreach@col from #1 to #2 do #3{%%
  \def\aecol{#1}%%
  \whileboolexpr{ test {\ifnumcomp{\aecol}{<}{#2}} or test{\ifnumcomp{\aecol}{=}{#2}} }
  { #3
    \edef\aecol{\number\numexpr\aecol+1\relax}
  }}
\makeatother

\foreachcell from (2,2) to (4,6) do
{\tikzset{row \aerow\space column \aecol/.style={my node style}}}

\foreachcolumn from 2 to 5 do 
{\tikzset{column \aecol/.style={column sep=4pt}}}

\tikzset{%%
  >=Stealth,
  my node style/.style={%%
    minimum width=\dimexpr0.60in+12pt\relax,
    minimum height=\dimexpr0.30cm+12pt\relax,
    outer sep=0pt,
    draw},
  }

\begin{document}

\begin{tikzpicture}

  \matrix (TBL) [%%
                 matrix of nodes,
                 nodes={%%
                   align=center,
                   inner sep=0pt,
                   anchor=center},
                ]
  {
                        & {$(-\infty,-2)$}               & {$(-2,-1)$}                     & {$(-1,1)$}                    & {$(1,2)$}                       & {$(2,\infty)$}                 \\[2pt]
   {$\abs{x^{2}-1}=\,$} & |[my node style]| {$x^{2}-1 $} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$1-x^{2}$} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$x^{2}-1$}  \\[-0.4pt]
   {$\abs{x^{2}-4}=\,$} &                   {$x^{2}-4 $} &                   {$4-x^{2}$}   &                   {$4-x^{2}$} &                   {$4-x^{2}$}   &                   {$x^{2}-4$}  \\[2pt]
   {$g(x) =$}           & |[my node style]| {$ 3 $ }     & |[my node style]| {$ 2x^{2}-5$} & |[my node style]| {$ -3 $}    & |[my node style]| { $2x^{2}-5$} & |[my node style]| {$ 3 $}      \\
  };

\end{tikzpicture}

\end{document}

我得到了期望的输出(除了draw没有像我希望的那样生效)。

将其作为密钥来做会很好。因此,除非有人展示如何有效地创建所需的密钥,否则我不会接受自己的解决方案。

定义键的问题(正如我在更新问题时尝试做的那样)在于,这需要在 中初始化(至少在我看来是这样)\def\tikz@common@matrix@code\tikz@do@matrix我不想重写所有这些。而且我对修补不够精通,无法理解如何修补它以嵌入我想要的在那里。

答案3

这是一个基本上按照您建议的方式工作的解决方案。为了避免必须破解 tikz 矩阵代码的定义以使其响应额外的样式,我定义了一个自定义处理程序,称为.matrix style使用方式:row 2 to 3 column 2 to 4/.matrix style={blue}。行和列可以按任意顺序排列,可以省略,并且可以只有一个数字而不是一个范围。例如,以下都是有效的:

row 2 to 3 column 2 to 4/.matrix style={...}
row 2 to 3 column 2/.matrix style={...}
column 2 to 3 row 3/.matrix style={...}
row 2 to 3/.matrix style={...}
column 4 row 2/.matrix style={...}

因为我显然有太多空闲时间,所以我编写了一个纯 tex 版本和一个 expl3 版本。

首先是纯文本版本:

\makeatletter
\def\matrixstyle@ifempty#1{\ifx$#1$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}

\def\matrixstyle@expectword#1#2{\matrixstyle@expectword@#1\nill{#2}}
\def\matrixstyle@expectword@#1#2\nill#3{%
    \@ifnextchar{#1}{%
        \matrixstyle@ifempty{#2}{%
            \def\next{#3}%
        }{%
            \def\next{\matrixstyle@expectword@#2\nill{#3}}%
        }%
        \expandafter\next\@gobble
    }{%
        \matrixstyle@expectword@fail
    }%
}

\def\matrixstyle@expectword@fail#1.{\PackageError{matrix style}{Unexpected row/column specifier "\pgfkeyscurrentname"}{}}


\pgfkeys{/handlers/.matrix style/.code={\pgfkeys{\pgfkeyscurrentpath/.matrix code=\pgfkeysalso{#1}}}}

\pgfkeys{/handlers/.matrix code/.code={
        \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}%
        \pgfkeys@split@path
        \edef\matrixstyle@thepath{\pgfkeyscurrentpath}%
        \def\matrixstyle@thestyle{#1}%
        \edef\temp{\noexpand\matrixstyle@parse\pgfkeyscurrentname.}%
        \temp
    }
}

\def\matrixstyle@parse{%
    \let\matrixstyle@columnmin\empty%
    \let\matrixstyle@rowmin\empty%
    \matrixstyle@parse@
}

\def\matrixstyle@parse@{%
    \@ifnextchar.{%
        \expandafter\matrixstyle@finish@rows\@gobble
    }{%
        \@ifnextchar{c}{%
            \matrixstyle@expectword{column}{\def\type{column}\matrixstyle@parse@range@grab{\matrixstyle@parse@range@min}}%
        }{%
            \matrixstyle@expectword{row}{\def\type{row}\matrixstyle@parse@range@grab{\matrixstyle@parse@range@min}}%
        }%
    }
}

\newcount\tempcount
\newcount\tempcountb
\def\matrixstyle@parse@range@grab#1{\afterassignment#1\tempcount=\numexpr}
\def\matrixstyle@parse@range@min{%
    \expandafter\edef\csname matrixstyle@\type min\endcsname{\the\tempcount}%
    \expandafter\edef\csname matrixstyle@\type max\endcsname{\the\tempcount}%
    \@ifnextchar{t}{%
        \matrixstyle@expectword{to}{\matrixstyle@parse@range@grab{\matrixstyle@parse@range@max}}%
    }{%
        \matrixstyle@parse@
    }
}

\def\matrixstyle@parse@range@max{%
    \expandafter\edef\csname matrixstyle@\type max\endcsname{\the\tempcount}%
    \matrixstyle@parse@
}

\def\matrixstyle@finish@rows{%
    \let\matrixstyle@possiblespace\space
    \ifx\matrixstyle@rowmin\empty
        \let\matrixstyle@possiblespace\empty
        \let\matrixstyle@rowtext\empty
        \matrixstyle@finish@columns
    \else
        \tempcount=\matrixstyle@rowmin\relax
        \loop
            \edef\matrixstyle@rowtext{row \the\tempcount}%
            % Loops don't nest correctly because they both use the same \iterate command
            % either the inner loop needs to be in a scope, which won't work for us
            % or we need to save the value of \iterate
            \let\matrixstyle@saveiterate\iterate
            \matrixstyle@finish@columns
            \let\iterate\matrixstyle@saveiterate
            \advance\tempcount1\relax
        \unless\ifnum\tempcount>\matrixstyle@rowmax\repeat
    \fi
}

\def\matrixstyle@finish@columns{%
    \ifx\matrixstyle@columnmin\empty
        \let\matrixstyle@possiblespace\empty
        \let\matrixstyle@columntext\empty
        \matrixstyle@finish@key
    \else
        \tempcountb=\matrixstyle@columnmin\relax
        \loop
            \edef\matrixstyle@columntext{column \the\tempcountb}%
            \matrixstyle@finish@key
            \advance\tempcountb1\relax
        \unless\ifnum\tempcountb>\matrixstyle@columnmax\repeat
    \fi
}

\def\matrixstyle@finish@key{%
    \edef\temp{
        \matrixstyle@thepath/%
           \matrixstyle@rowtext \matrixstyle@possiblespace \matrixstyle@columntext
              /.code={\unexpanded\expandafter{\matrixstyle@thestyle}}%
    }%
    \expandafter\pgfkeys\expandafter{\temp}
}

这是 expl3 版本。

\usepackage{expl3}

\makeatletter
\pgfkeys{/handlers/.matrix style/.code={\pgfkeys{\pgfkeyscurrentpath/.matrix code=\pgfkeysalso{#1}}}}

\pgfkeys{/handlers/.matrix code/.code={
        \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}%
        \pgfkeys@split@path
        \matrixstyle@parse{#1}
    }
}
\makeatother

\ExplSyntaxOn
\makeatletter
\def \matrixstyle@parse { \matrixstyle_parse:n }
\makeatother

\tl_new:N \l_matrixstyle_path_tl
\tl_new:N \l_matrixstyle_style_tl
\tl_new:N \l_matrixstyle_type_tl
\tl_new:N \l_matrixstyle_possible_space_tl

\tl_new:N \l_matrixstyle_columntext_tl
\tl_new:N \l_matrixstyle_columnmin_tl
\tl_new:N \l_matrixstyle_columnmax_tl

\tl_new:N \l_matrixstyle_rowtext_tl
\tl_new:N \l_matrixstyle_rowmin_tl
\tl_new:N \l_matrixstyle_rowmax_tl

\cs_new:Nn \matrixstyle_expectword:nn {
    \matrixstyle_expectword_aux:wn #1 \q_stop { #2 }
}

\cs_gset:Npn \use_i_delimit_by_period:nw #1 #2 . { #1 } 

\cs_new:Npn \matrixstyle_expectword_aux:wn #1 #2 \q_stop #3 {
    \peek_meaning_remove_ignore_spaces:NTF { #1 } {
        \tl_if_empty:nTF { #2 } {
            #3
        }{
            \matrixstyle_expectword_aux:wn #2 \q_stop { #3 }
        }
    }{ % An error. Escape out and throw an error.
        \use_i_delimit_by_period:nw { \PackageError{matrix style}{Unexpected row/column specifier "\pgfkeyscurrentname"}{} }
    }
}


\cs_new:Nn \matrixstyle_parse:n {
    \tl_clear:N \l_matrixstyle_columnmin_tl
    \tl_clear:N \l_matrixstyle_rowmin_tl
    \tl_set:Nn \l_matrixstyle_style_tl { #1 }%
    \tl_set:Nx \l_matrixstyle_path_tl { \pgfkeyscurrentpath }%
    \use:x { \exp_not:N \matrixstyle_parse_aux: \pgfkeyscurrentname . }
}

\cs_new:Npn \matrixstyle_parse_aux: {
    \peek_meaning_remove_ignore_spaces:NTF . {
        \matrixstyle_finish_rows:
    }{
        \peek_meaning_ignore_spaces:NTF { c }{
            \matrixstyle_expectword:nn { column } {
                \tl_set:Nn \l_matrixstyle_type_tl {column}
                \matrixstyle_parse_rangegrab:nw { \matrixstyle_parse_rangemin: }
            }%
        }{%
            \matrixstyle_expectword:nn { row }{
                \tl_set:Nn \l_matrixstyle_type_tl {row}
                \matrixstyle_parse_rangegrab:nw { \matrixstyle_parse_rangemin: }
            }%
        }%
    }
}

\newcount\tempcount
\cs_new:Npn \matrixstyle_parse_rangegrab:nw #1 {
    \afterassignment #1
    \tempcount = \int_eval:w
}

\cs_new:Nn \matrixstyle_parse_rangemin: {
    \tl_set:co { l_matrixstyle_ \tl_use:N \l_matrixstyle_type_tl min_tl }{ \the\tempcount }%
    \tl_set:co { l_matrixstyle_ \tl_use:N \l_matrixstyle_type_tl max_tl }{ \the\tempcount }
    \peek_meaning_ignore_spaces:NTF { t }{
        \matrixstyle_expectword:nn { to }{
            \matrixstyle_parse_rangegrab:nw { \matrixstyle_parse_rangemax: }
        }%
    }{%
        \matrixstyle_parse_aux:
    }
}

\cs_new:Nn \matrixstyle_parse_rangemax: {
    \tl_set:co { l_matrixstyle_ \tl_use:N \l_matrixstyle_type_tl max_tl }{ \the\tempcount }
    \matrixstyle_parse_aux:
}

\cs_new:Nn \matrixstyle_finish_rows: {%
    \tl_set_eq:NN \l_matrixstyle_possible_space_tl \c_space_tl
    \tl_if_empty:NTF \l_matrixstyle_rowmin_tl {
        \tl_clear:N \l_matrixstyle_possible_space_tl
        \tl_clear:N \l_matrixstyle_rowtext_tl
        \matrixstyle_finish_columns:
    } {
        \int_step_inline:nnn
            { \tl_use:N \l_matrixstyle_rowmin_tl }
            { \tl_use:N \l_matrixstyle_rowmax_tl }
            {
                \tl_set:Nn \l_matrixstyle_rowtext_tl { row ~ ##1 }
                \matrixstyle_finish_columns:
            }
    }
}

\cs_new:Nn \matrixstyle_finish_columns: {%
    \tl_if_empty:NTF  \l_matrixstyle_columnmin_tl {
        \tl_clear:N \l_matrixstyle_possible_space_tl
        \tl_clear:N \l_matrixstyle_columntext_tl
        \matrixstyle_finish_key:
    } {
        \int_step_inline:nnn
            { \tl_use:N \l_matrixstyle_columnmin_tl }
            { \tl_use:N \l_matrixstyle_columnmax_tl }
            {
                \tl_set:Nn \l_matrixstyle_columntext_tl { column ~ ##1 }
                \matrixstyle_finish_key:
            }
    }
}

\makeatletter
\cs_new:Nn \matrixstyle_finish_key: {
    \exp_args:Nx \pgfkeys
        {   \tl_use:N \l_matrixstyle_path_tl /
            \tl_use:N \l_matrixstyle_rowtext_tl
            \tl_use:N \l_matrixstyle_possible_space_tl
            \tl_use:N \l_matrixstyle_columntext_tl
        /. code = { \exp_not:o { \l_matrixstyle_style_tl } } } 
}
\makeatother
\ExplSyntaxOff

正在使用的纯文本版本:

\documentclass[border=6pt]{standalone}

\usepackage{amsmath}
\newcommand\abs[1]{\lvert#1\rvert}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{matrix}
\usetikzlibrary{arrows.meta}


\makeatletter
\def\matrixstyle@ifempty#1{\ifx$#1$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}

\def\matrixstyle@expectword#1#2{\matrixstyle@expectword@#1\nill{#2}}
\def\matrixstyle@expectword@#1#2\nill#3{%
    \@ifnextchar{#1}{%
        \matrixstyle@ifempty{#2}{%
            \def\next{#3}%
        }{%
            \def\next{\matrixstyle@expectword@#2\nill{#3}}%
        }%
        \expandafter\next\@gobble
    }{%
        \matrixstyle@expectword@fail
    }%
}

\def\matrixstyle@expectword@fail#1.{\PackageError{matrix style}{Unexpected row/column specifier "\pgfkeyscurrentname"}{}}


\pgfkeys{/handlers/.matrix style/.code={\pgfkeys{\pgfkeyscurrentpath/.matrix code=\pgfkeysalso{#1}}}}

\pgfkeys{/handlers/.matrix code/.code={
        \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}%
        \pgfkeys@split@path
        \edef\matrixstyle@thepath{\pgfkeyscurrentpath}%
        \def\matrixstyle@thestyle{#1}%
        \edef\temp{\noexpand\matrixstyle@parse\pgfkeyscurrentname.}%
        \temp
    }
}

\def\matrixstyle@parse{%
    \let\matrixstyle@columnmin\empty%
    \let\matrixstyle@rowmin\empty%
    \matrixstyle@parse@
}

\def\matrixstyle@parse@{%
    \@ifnextchar.{%
        \expandafter\matrixstyle@finish@rows\@gobble
    }{%
        \@ifnextchar{c}{%
            \matrixstyle@expectword{column}{\def\type{column}\matrixstyle@parse@range@grab{\matrixstyle@parse@range@min}}%
        }{%
            \matrixstyle@expectword{row}{\def\type{row}\matrixstyle@parse@range@grab{\matrixstyle@parse@range@min}}%
        }%
    }
}

\newcount\tempcount
\newcount\tempcountb
\def\matrixstyle@parse@range@grab#1{\afterassignment#1\tempcount=\numexpr}
\def\matrixstyle@parse@range@min{%
    \expandafter\edef\csname matrixstyle@\type min\endcsname{\the\tempcount}%
    \expandafter\edef\csname matrixstyle@\type max\endcsname{\the\tempcount}%
    \@ifnextchar{t}{%
        \matrixstyle@expectword{to}{\matrixstyle@parse@range@grab{\matrixstyle@parse@range@max}}%
    }{%
        \matrixstyle@parse@
    }
}

\def\matrixstyle@parse@range@max{%
    \expandafter\edef\csname matrixstyle@\type max\endcsname{\the\tempcount}%
    \matrixstyle@parse@
}

\def\matrixstyle@finish@rows{%
    \let\matrixstyle@possiblespace\space
    \ifx\matrixstyle@rowmin\empty
        \let\matrixstyle@possiblespace\empty
        \let\matrixstyle@rowtext\empty
        \matrixstyle@finish@columns
    \else
        \tempcount=\matrixstyle@rowmin\relax
        \loop
            \edef\matrixstyle@rowtext{row \the\tempcount}%
            % Loops don't nest correctly because they both use the same \iterate command
            % either the inner loop needs to be in a scope, which won't work for us
            % or we need to save the value of \iterate
            \let\matrixstyle@saveiterate\iterate
            \matrixstyle@finish@columns
            \let\iterate\matrixstyle@saveiterate
            \advance\tempcount1\relax
        \unless\ifnum\tempcount>\matrixstyle@rowmax\repeat
    \fi
}

\def\matrixstyle@finish@columns{%
    \ifx\matrixstyle@columnmin\empty
        \let\matrixstyle@possiblespace\empty
        \let\matrixstyle@columntext\empty
        \matrixstyle@finish@key
    \else
        \tempcountb=\matrixstyle@columnmin\relax
        \loop
            \edef\matrixstyle@columntext{column \the\tempcountb}%
            \matrixstyle@finish@key
            \advance\tempcountb1\relax
        \unless\ifnum\tempcountb>\matrixstyle@columnmax\repeat
    \fi
}

\def\matrixstyle@finish@key{%
    \edef\temp{
        \matrixstyle@thepath/%
           \matrixstyle@rowtext \matrixstyle@possiblespace \matrixstyle@columntext
              /.code={\unexpanded\expandafter{\matrixstyle@thestyle}}%
    }%
    \expandafter\pgfkeys\expandafter{\temp}
}


\begin{document}

\tikzset{%%
  my node style/.style={%%
    minimum width=\dimexpr0.60in+12pt\relax,
    minimum height=\dimexpr0.30cm+12pt\relax,
    outer sep=0pt,
    draw},
  }

\begin{tikzpicture}

  \matrix (TBL) [%%
                 matrix of nodes,
                 nodes={%%
                   align=center,
                   inner sep=0pt,
                   anchor=center},
                     column 2 to 3 row 2 to 3/.matrix style={blue}
                ]
  {
                        & {$(-\infty,-2)$}               & {$(-2,-1)$}                     & {$(-1,1)$}                    & {$(1,2)$}                       & {$(2,\infty)$}                 \\[2pt]
   {$\abs{x^{2}-1}=\,$} & |[my node style]| {$x^{2}-1 $} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$1-x^{2}$} & |[my node style]| {$x^{2}-1$}   & |[my node style]| {$x^{2}-1$}  \\[-0.4pt]
   {$\abs{x^{2}-4}=\,$} &                   {$x^{2}-4 $} &                   {$4-x^{2}$}   &                   {$4-x^{2}$} &                   {$4-x^{2}$}   &                   {$x^{2}-4$}  \\[2pt]
   {$g(x) =$}           & |[my node style]| {$ 3 $ }     & |[my node style]| {$ 2x^{2}-5$} & |[my node style]| {$ -3 $}    & |[my node style]| { $2x^{2}-5$} & |[my node style]| {$ 3 $}      \\
  };

\end{tikzpicture}

\end{document} 

答案4

对于语法,row <r1> to <r2> columns <c1> to <c2> = <style>您需要扩展.unknown键,/tikz以便它也能检查这一点。

但这已经检查了很多东西(它是 pgf 键吗?它是颜色吗?它是箭头规范吗?它是形状吗?)


row <r1> to <r2> columns <c1> to <c2>/.handler = <style>提供给您。


使用几个键和.list处理程序,这很容易实现(我在这里使用了很多),而无需深入研究 TikZ 或 PGFkeys 的内部结构。

关键是

  • 对于普通的列和行
    • columns = {<foreach list of columns>}{<style>}
      将该样式附加<style>到列表中的column <i>样式 中。<i>
    • rows = {<foreach list of rows>}{<style>}
      将该样式附加<style>到列表中的rows <i>样式中。<i>
    • columns*/rows*与上述相同但附加nodes = {<style>}
  • 对于连接区域
    • range = {<r1> - <c1> to <r2> - <c2> = <style>}
      将样式附加<style>到所提供范围内的单元格。
    • range lists = {rows <foreach list of rows> columns <foreach list of column> = <style>
      将样式附加<style>到指定范围内的单元格。
    • range*/range lists*与上述相同但附加nodes = {<style>}
  • 获取各种单元格的列表
    • rows cols = {r<r1>c<r1>, r<r2>c<c2>, …, r<rn>c<rn>}{<style>}
      将样式附加<style>到指定的单元格。

      这仍然由解析\foreach,并且应该能够执行rows cols = {r1c2, r1c..., r1c7}{<style>} 当然,您可以根据需要更改参数。由于一切都已完成.list(即\foreach在后台),因此空格无关紧要。

    • rows cols*如上。

通过一些数学知识,我们还可以实现if matrix/ if matrix*(可嵌套),其中我们可以使用 PGFmath 函数rowcol评估任何条件,然后

if matrix* = {iseven(row + col)}{<style A>}{<style B>}

<style A>和交替应用<style B>

例子

下面的矩阵只是使用

matrix of math nodes,
columns      = {1}      {anchor=base east},
columns      = {2,...,5}{column sep = -.4pt},
range lists* = {rows 2, 4 columns 2, ..., 6 = my node style},
checkers     = {1}{1}{fill=green!35}{fill=blue!25}

其中 checkers 正在使用if matrix

代码

\documentclass[border=6pt, tikz]{standalone}
\usepackage{amsmath}
\newcommand\abs[1]{\lvert#1\rvert}
\usetikzlibrary{matrix}
\makeatletter
\pgfqkeys{/utils}{
  if matrix/.code n args=3{%
    \begingroup
      \pgfmathdeclarefunction{row}{0}{\edef\pgfmathresult{\the\pgfmatrixcurrentrow}}%
      \pgfmathdeclarefunction{col}{0}{\edef\pgfmathresult{\the\pgfmatrixcurrentcolumn}}%
      \pgfmathparse{#1}%
    \expandafter\endgroup\expandafter
    \ifdim\pgfmathresult pt=0pt
      \expandafter\pgfutil@firstoftwo
    \else
      \expandafter\pgfutil@secondoftwo
    \fi
    {\pgfkeysalso{#3}}{\pgfkeysalso{#2}}}}
\makeatother
\tikzset{
  % columns = { <list> }{ <style> }
  columns/.style 2 args={
   /utils/tempa/.style={column ##1/.append style={#2}},
   /utils/tempa/.list={#1}},
  columns*/.style 2 args={columns={#1}{nodes={#2}}},
  %
  % rows = { <list> }{ <style> }
  rows/.style 2 args={
   /utils/tempa/.style={row ##1/.append style={#2}},
   /utils/tempa/.list={#1}},
  rows*/.style 2 args={rows={#1}{nodes={#2}}},
  %
  % rows cols = {r<r1>c<r1>, r<r2>c<c2>, …, r<rn>c<rn>}{ <style> }
  rows cols/.style 2 args={
   /utils/tempa/.style args={r##1c##2}{row ##1 column ##2/.append style={#2}},
   /utils/tempa/.list={#1}},
  rows cols*/.style 2 args={rows cols={#1}{nodes={#2}}},
  %
  % range = <r1> - <c1> to <r2> - <c2> = <style>
  range/.style args={#1-#2to#3-#4=#5}{
    range lists={rows#1,...,#3columns#2,...,#4={#5}}},
  range*/.style args={#1=#2}{range={#1=nodes={#2}}},
  %
  % range lists = { rows <list> columns <list> = <style> }
  range lists/.style args={rows#1columns#2=#3}{
   /utils/tempa/.style={
     /utils/tempb/.style={row ##1 column ####1/.append style={#3}},
     /utils/tempb/.list={#2}},
   /utils/tempa/.list={#1}},
  range lists*/.style args={#1=#2}{range lists={#1=nodes={#2}}},
  %
  % matrix math
  cells={
    if matrix/.style n args={3}{/utils/if matrix={##1}{##2}{##3}},
    if matrix*/.style n args={3}{/utils/if matrix={##1}{nodes={##2}}{nodes={##3}}},
    nodes={if matrix*/.style n args={3}{if matrix={####1}{####2}{####3}}}},
  if matrix/.style n args={3}{cells={/utils/if matrix={#1}{#2}{#3}}},
  if matrix*/.style n args={3}{if matrix={#1}{nodes={#2}}{nodes={#3}}},
}
\begin{document}
\begin{tikzpicture}[
  my node style/.style={
    minimum width=.60in+12pt,
    minimum height=.30cm+12pt,
    text depth=+0pt,
    font=\vphantom{$()0+-x^2$},
    draw
  },
  checkers/.style n args = {4}{
    if matrix*   = {and(row > #1, col > #2)}{
      if matrix  =   {iseven(row+col)}
                     {#3}{#4}}{}}
]
\matrix (TBL) [%%
  matrix of math nodes,
  columns      = {1}      {anchor=base east},
  columns      = {2,...,5}{column sep = -.4pt},
  range lists* = {rows 2, 4 columns 2, ..., 6 = my node style},
  % or:
  % columns    = {2, ..., 6}{rows* = {2, 4}{my node style}},
  % or:
  % rows cols* = {r2c2,r2c...,r2c6,r4c2,r4c...,r4c6}{my node style},
  checkers     = {1}{1}{fill=green!35}{fill=blue!25}
] {
                   & (-\infty,-2) & (-2,-1)  & (-1,1)  & (1,2)    & (2,\infty) \\[2pt]
  \abs{x^{2}-1}={} & x^{2}-1      & x^{2}-1  & 1-x^{2} &  x^{2}-1 & x^{2}-1    \\
  \abs{x^{2}-4}={} & x^{2}-4      & 4-x^{2}  & 4-x^{2} & 4-x^{2}  & x^{2}-4    \\[2pt]
           g(x)={} &  3           & 2x^{2}-5 &  -3     & 2x^{2}-5 & 3          \\
};
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容