编辑

编辑

回答如何突出显示矩阵的某些部分是一种很好的技术,它不是侵入性的,但需要手动对节点进行编号。我稍微概括了一下:

\documentclass{article}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\usetikzlibrary{calc}

%----------------------------------------------------------------------------------------
% 
% https://tex.stackexchange.com/questions/40028/highlight-elements-in-the-matrix/40059#40059
%
% The following two macros allow marking left/upper, right/lower node positions for box drawing, and then drawing the box.
% unique node numbers must be passed to these.
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\newcommand{\DrawNodeBox}[3][]{%
    \tikz[overlay,remember picture]{%
    \draw[DarkOliveGreen,#1]%
      ($(#2)+(-0.4em,0.9em)$) rectangle%
      ($(#3)+(0.5em,-0.3em)$);}%
}

% here's some logic to allow for three boxes to be drawn with preceding marks, with counter increments after
% the boxes are drawn.
\newcounter{FirstBoxCounter}
\newcounter{SecondBoxCounter}
\newcounter{ThirdBoxCounter}

\newcommand{\tikzLeftMark}[0]{\tikzmark{tbFirstLeft\theFirstBoxCounter}}
\newcommand{\tikzLeftMarkSecond}[0]{\tikzmark{tbSecondLeft\theSecondBoxCounter}}
\newcommand{\tikzLeftMarkThird}[0]{\tikzmark{tbThirdLeft\theThirdBoxCounter}}

\newcommand{\tikzRightMark}[0]{\tikzmark{tbFirstRight\theFirstBoxCounter}}
\newcommand{\tikzRightMarkSecond}[0]{\tikzmark{tbSecondRight\theSecondBoxCounter}}
\newcommand{\tikzRightMarkThird}[0]{\tikzmark{tbThirdRight\theThirdBoxCounter}}

\newcommand{\DrawFirstBox}[0]{%
   \DrawNodeBox[thick]{tbFirstLeft\theFirstBoxCounter}{tbFirstRight\theFirstBoxCounter}%
   \stepcounter{FirstBoxCounter}%
}
\newcommand{\DrawSecondBox}[0]{%
   \DrawNodeBox[thick]{tbSecondLeft\theSecondBoxCounter}{tbSecondRight\theSecondBoxCounter}%
   \stepcounter{SecondBoxCounter}%
}
\newcommand{\DrawThirdBox}[0]{%
   \DrawNodeBox[thick]{tbThirdLeft\theThirdBoxCounter}{tbThirdRight\theThirdBoxCounter}%
   \stepcounter{ThirdBoxCounter}%
}
%------------------------------------------------------------------------------------------------------

\begin{document}
\[
  M = \left[\begin{array}{*{13}{c}}
    \tikzLeftMarkSecond{}0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 & 0\tikzRightMarkSecond{} & 1 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \tikzLeftMark{}1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 \tikzRightMark{} & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \tikzLeftMarkThird{}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\tikzRightMarkThird{} & 0 & 1 \\
  \end{array}\right]
\]

\DrawFirstBox{}
\DrawSecondBox{}
\DrawThirdBox{}

\[
  M = \left[\begin{array}{*{13}{c}}
    0 & 0 & 0 & \tikzLeftMarkSecond{}-1 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0\tikzRightMarkSecond{} & 1 & 0 & 0 & 0 & 1 & 1 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \tikzLeftMark{}-1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 \tikzRightMark{} & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \tikzLeftMarkThird{}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\tikzRightMarkThird{} & 0 & 1 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0
  \end{array}\right]
\]

\DrawFirstBox{}
\DrawSecondBox{}
\DrawThirdBox{}


\end{document}

这使我能够一次绘制最多三个框(在矩阵中,或者大概在一般方程中),每次执行绘制时,标记的计数器都会递增,并且运行良好:

突出显示子矩阵

(Peter 的方法中的边缘检测存在问题,我不得不稍微修改一下硬编码的数字,这样可以生成更好但不完美的框边界)

有没有办法拥有一个计数器数组,而不是我使用的一组三个手动命名的计数器?我希望能够使用带有节点计数器数组数字索引的 DrawNodeBox,而不是使用明确传递节点名称的此函数的包装器方法(这样我就可以直接使用 DrawNodeBox 的可选参数)。

即我想要一个可以使用如下方式的界面:

\[
  M = \left[\begin{array}{*{13}{c}}
    \tikzmark{left}{1}0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 & 0\tikzmark{right}{1} & 1 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \tikzmark{left}{2}1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 \tikzmark{right}{2} & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \tikzmark{left}{3}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\tikzmark{right}{3} & 0 & 1 \\
  \end{array}\right]
\]

\DrawNodeBox[thick]{1}
\DrawNodeBox[thick]{2}
\DrawNodeBox[thick]{3}

\[
  M = \left[\begin{array}{*{13}{c}}
    0 & 0 & 0 & \tikzmark{left}{2}-1 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0\tikzmark{right}{2} & 1 & 0 & 0 & 0 & 1 & 1 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \tikzmark{left}{3}-1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 \tikzmark{right}{3} & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \tikzmark{left}{1}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\tikzmark{right}{1} & 0 & 1 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0
  \end{array}\right]
\]

\DrawNodeBox[thick]{1}
\DrawNodeBox[thick]{2}
\DrawNodeBox[thick]{3}

其中 \DrawNodeBox 会增加节点号的索引计数器并绘制框,而 \tikzmark 将使用相同的索引计数器,并使用该计数器自动生成左节点号和右节点号。

答案1

我认为这可以满足您的要求,并且应该比您当前的解决方案更简洁。语法与您要求的语法类似,只是使用了不同的宏名,因为不可能同时对两个不同的宏使用相同的命令名 ;)。

\documentclass{article}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\usetikzlibrary{calc,tikzmark}

\newcommand{\DrawNodeBox}[3][]{%
  \tikz[overlay,remember picture]{%
    \draw[DarkOliveGreen,#1]%
    ($({pic cs:#2})+(-0.4em,0.9em)$) rectangle%
    ($({pic cs:#3})+(0.5em,-0.3em)$);}%
}

\newcounter{MyBoxCounter}
\setcounter{MyBoxCounter}{0}

\gdef\MyStepBoxCounter{\stepcounter{MyBoxCounter}}

\newcommand\DrawMyBox[2][]{%
  \DrawNodeBox[#1]{tbleft#2\theMyBoxCounter}{tbright#2\theMyBoxCounter}%
  \gdef\MyStepBoxCounter{\stepcounter{MyBoxCounter}}%
}

\newcommand\mytikzmark[2]{%
  \MyStepBoxCounter%
  \global\let\MyStepBoxCounter\relax%
  \tikzmark{tb#1#2\theMyBoxCounter}%
}

\begin{document}

\[
  M = \left[\begin{array}{*{13}{c}}
    \mytikzmark{left}{1}0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 & 0\mytikzmark{right}{1} & 1 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \mytikzmark{left}{2}1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 1 \mytikzmark{right}{2} & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \mytikzmark{left}{3}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\mytikzmark{right}{3} & 0 & 1 \\
  \end{array}\right]
\]

\DrawMyBox[thick, blue]{1}
\DrawMyBox[thick, red]{2}
\DrawMyBox[thick, green]{3}

\[
  M = \left[\begin{array}{*{13}{c}}
    0 & 0 & 0 & \mytikzmark{left}{2}-1 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0\mytikzmark{right}{2} & 1 & 0 & 0 & 0 & 1 & 1 & 1 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    \mytikzmark{left}{3}-1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
    0 \mytikzmark{right}{3} & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
    0 & 0 & 0 & 0 & 1 & 0 & \mytikzmark{left}{1}0 & 0 & 0 & 0 & 0 & 1 & 0 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\mytikzmark{right}{1} & 0 & 1 \\
    0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0
  \end{array}\right]
\]

\DrawMyBox[thick, magenta]{1}
\DrawMyBox[thick, orange]{2}
\DrawMyBox[thick, cyan]{3}

\end{document}

花式矩阵标记

编辑

如果每个矩阵需要超过 9 个框(并且您认为读者可以应付!),您可以使用,例如:

\newcommand\DrawMyBox[2][]{%
  \DrawNodeBox[#1]{tbleft-#2-\theMyBoxCounter}{tbright-#2-\theMyBoxCounter}%
  \gdef\MyStepBoxCounter{\stepcounter{MyBoxCounter}}%
}

\newcommand\mytikzmark[2]{%
  \MyStepBoxCounter%
  \global\let\MyStepBoxCounter\relax%
  \tikzmark{tb#1-#2-\theMyBoxCounter}%
}

消除坐标名称的歧义。

答案2

我意识到这会失去很多好的默认数学矩阵排版,并且需要一些手动操作,但像下面这样的东西不会有点(可能不会太多)不那么笨重:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit}
\begin{document}
\[
M=\left[\;
\begin{tikzpicture}[baseline=(0:0), y=\baselineskip,x=2em]
\foreach \row [count=\i] in {%
  { 0, 1, 0, 0, 0, 0},
  { 0, 1, 0, 1, 0, 0},
  { 0, 0, 1,-1, 0, 0},
  { 1, 1, 0, 0, 0, 0},
  { 0, 1, 1, 0, 0, 0},
  { 0, 0, 0, 0,-1, 0}}
  \foreach \col [count=\j] in \row
    \node [inner ysep=0pt, inner xsep=2pt] 
      (m-\i-\j) at (\j,-\i+3.666) {\ensuremath{\col}};
\node [fit=(m-1-1) (m-2-3), draw, thick]{};
\node [fit=(m-3-5) (m-6-6), draw, thick]{};
\end{tikzpicture}
\;\right] 
\]
\end{document}

在此处输入图片描述

相关内容