13

I have a 3x3 eqnarray. Is there a way to highlight the diagonal with background color, perhaps using tikz? I was using tikz ellipse to highlight equation terms, though stretching the ellipse to the whole diagonal makes it too thin at ends; I also don't know how to rotate it without trial-and-error angle value.

2

5 Answers 5

8

Something with nicematrix:

\documentclass{article}
\usepackage{nicematrix,tikz}
\usetikzlibrary{fit}

\begin{document}
\[
\begin{bNiceArray}{>{\strut}cccc}[margin,extra-margin = 1pt]
1 & 2 & 3 & 4 \\
1 & 2 & 3 & 4 \\
1 & 2 & 3 & 4 \\
1 & 2 & 3 & 4 \\
\CodeAfter
  \begin{tikzpicture}
  \node [draw=red, rounded corners=2pt, inner ysep = 0pt,
       rotate fit=-38, fit = (1-1) (4-4) ] {} ;
  \end{tikzpicture}
\end{bNiceArray}
\]
\end{document}

You need several compilations (because nicematrix uses PGF/Tikz nodes under the hood).

Output of the above code

11

You can use the following but I have to admit that I did not quite get your question.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
%\usetikzlibrary{shapes} %Uncomment if you want additional shapes
\begin{document}
\begin{tikzpicture}
\matrix (m) [matrix of math nodes]{
| [draw,fill= yellow] | a=b     & b                                  &c\\
d                               &|[draw,fill= yellow]| e^2=m^2c^4 &f\\
g                               &h          &|[draw,fill= yellow]|F = \frac{d}{dt}{(m\vec{v})}\\
};
\end{tikzpicture}
\end{document}

This results in

enter image description here

I hope it helps.

EDIT: if you also include the shapes library, you can change the shape of the highlighting to ellipse etc.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,shapes}
\begin{document}
\begin{tikzpicture}
\matrix (m) [matrix of math nodes,inner sep=0cm]{
| [draw,regular polygon,regular polygon sides=3,fill= yellow] | a=b&F(i\omega) = \int^{\infty}_{-\infty}f(t)e^{-i\omega t}dt &c\\
%Second row
d&|[draw,regular polygon,fill= red]| e^2=m^2c^4 &f\\
%Third row
\nabla^2(\vec{r}\times \nabla\psi)  - \frac{1}{c^2}\frac{\partial^2 (\vec{r}\times \nabla\psi)}{\partial t^2}&h&|[diamond,fill= blue!20]|F = \frac{d}{dt}{(m\vec{v})}\\
};
\end{tikzpicture}
\end{document}

which gives

enter image description here

By the way, sorry for the lame matrix entries.

10

It's not clear from your question whether you want a single stripe that goes over the whole diagonal, or each diagonal term to be individually highlighted. The latter, which percusse goes for, can be simplified from percusse's answer by using some code from Obstacles to simulating an amsmath matrix by a TiKZ matrix of math nodes. This replaces the amsmath matrix commands by TikZ versions. It effectively does the same as percusse's code, but hides a lot of the messy bits. One change in the implementation is that we apply the style by testing the row and column numbers, rather than specifying it on every cell. The preamble may seem a bit daunting, so I'll put the result first:

TikZ matrix with highlighted diagonal terms

The code itself is:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/26866/86}
\usepackage{tikz}
\usetikzlibrary{matrix}

\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,
%    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={\|},
    }
  },
  highlight diagonal/.style={
    nodes={highlight diagonal nodes}
  },
  highlight diagonal nodes/.code={
    \ifnum\pgfmatrixcurrentrow=\pgfmatrixcurrentcolumn
    \tikzset{fill=yellow}
    \fi
  }
}

\let\matamp=&

\catcode`\&=13
\makeatletter
\def&{\iftikz@is@matrix
  \pgfmatrixnextcell
  \else
  \matamp
  \fi}
\makeatother

\newenvironment{tikzbmatrix}[1][]{%
  \begin{tikzpicture}[bmatrix]
  \matrix[#1] \bgroup}
{\\\egroup;\end{tikzpicture}}

\begin{document}
  \begin{tikzbmatrix}[highlight diagonal,nodes={inner sep=2pt}]
  a=b & b          & c\\
  d   & e^2=m^2c^4 & f\\
  g   & h          & F = \frac{d}{dt}{(m\vec{v})}
  \end{tikzbmatrix}
\end{document}

You have to imagine all of that mess hidden away in a nice neat package! (Actually it's longer than necessary because it has code for every one of the AMS matrix types.)

To get the other interpretation, we need a way to draw a line underneath the text. Fortunately, there's already something that can draw underneath it: the matrix node shape. So we simply find a shape that draws a line from the top left to the bottom right. As there isn't one, we define one. (The strike out is close, but not close enough.) We want the highlighter stroke to be wide, but setting the line width for the matrix also sets it for the cells which we don't want so we have to override that. Other than that, it's straightforward.

TikZ matrix with highlighted diagonal

(It's not positioned perfectly, but that might be as much to do with the elongated shape of the cells. That's something that could be corrected, but would need maybe a little tweaking on a per-case basis.)

Here's the code. Again, think of the preamble as a nice package.

\documentclass[border=10]{standalone}
%\url{https://tex.stackexchange.com/q/26866/86}
\usepackage{tikz}
\usetikzlibrary{matrix,shapes.misc}

\newlength\mtxrowsep   \setlength\mtxrowsep{1.5ex}
\newlength\mtxcolsep   \setlength\mtxcolsep{2\arraycolsep}

\makeatletter
\pgfdeclareshape{strike under}
{
 \inheritsavedanchors[from=rectangle] % this is nearly a rectangle
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}
  \backgroundpath{
    \pgfpathmoveto{\northeast}
    \pgfpathmoveto{\southwest}
    \southwest
    \pgf@xa=\pgf@x
    \northeast
    \pgf@ya=\pgf@y
    \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
    \southwest
    \pgf@ya=\pgf@y
    \northeast
    \pgf@xa=\pgf@x
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
 }
}
\makeatother
\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,
%    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={\|},
    }
  },
  highlight diagonal/.style={
    nodes={highlight diagonal nodes}
  },
  highlight diagonal nodes/.code={
    \ifnum\pgfmatrixcurrentrow=\pgfmatrixcurrentcolumn
    \tikzset{fill=yellow}
    \fi
  },
  highlighter width/.initial={5mm}
}

\let\matamp=&

\catcode`\&=13
\makeatletter
\def&{\iftikz@is@matrix
  \pgfmatrixnextcell
  \else
  \matamp
  \fi}

\makeatother

\newenvironment{tikzbmatrix}[1][]{%
  \begin{tikzpicture}[bmatrix]
  \matrix[#1] \bgroup}
{\\\egroup;\end{tikzpicture}}

\begin{document}
  \begin{tikzbmatrix}[draw=yellow,strike under,line width=1cm,nodes={thin}]
  a=b & b          & c\\
  d   & e^2=m^2c^4 & f\\
  g   & h          & F = \frac{d}{dt}{(m\vec{v})}
  \end{tikzbmatrix}
\end{document}
2
  • 2
    Wow, you have saved a huge amount of time and effort of mine, by giving away that preamble. Thanks a lot.Looking forward to have this on CTAN ;)
    – percusse
    Sep 30, 2011 at 13:06
  • 1
    @percusse: If you like it and want to see it on CTAN, you should add it to the list: meta.tex.stackexchange.com/q/1220/86 Sep 30, 2011 at 13:08
4

APPROACH 1

Best I could do was a bowtie highlight. Features: you can set the column gap and row baselineskips as shown. It forces all column widths equal and all rows of fixed baselineskip, so that the highlight need not bend for extra-wide columns or extra-deep rows.

The optional argument to \diaghighlight is a scaling parameter for the highlight width (default .7).

For the equal-width matrix columns, I use tabstackengine's \fixTABwidth{T} directive. For the highlights, I use Bruno's \slantbox (Shear transform a "box") to create two overlaid sheared rectangles

\documentclass{article}
\usepackage{tabstackengine,xcolor,fp,rotating}
\TABstackMath
\newsavebox\foobox
\newcommand{\slantbox}[2][.5]{\mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}
\setstacktabbedgap{6pt}
\def\blfac{.7}% <--- DEFAULT FACTOR FOR WIDTH OF HIGHLIGHT
\fixTABwidth{T}
\newsavebox\ziv
\makeatletter
\newcommand\diaghighlight[2][\blfac]{%
  \sbox\ziv{\Matrixstack{#2}}%
  \sbox2{\textcolor{yellow}{\rule{#1\normalbaselineskip}%
    {\dimexpr\ht\ziv+\dp\ziv}}}%
  \sbox4{{\textcolor{yellow}{\rule{#1\normalbaselineskip}%
    {\wd\ziv}}}}%
  \edef\tmpH{\strip@pt\dimexpr\ht\ziv+\dp\ziv}%
  \edef\tmpWa{\strip@pt\dimexpr\wd\ziv-\wd2}%
  \edef\tmpHa{\strip@pt\dimexpr\ht\ziv+\dp\ziv-\wd4}%
  \edef\tmpW{\strip@pt\dimexpr\wd\ziv}%
  \FPdiv\zz{\tmpWa}{-\tmpH}%
  \FPdiv\zzz{\tmpHa}{\tmpW}%
  \ensuremath{\vcenter{\hbox{%
  \sbox2{\stackinset{r}{}{t}{}{\rotatebox[origin=l]{-90}{%
    \slantbox[\zzz]{\copy4}}}{\slantbox[\zz]{\copy2}}}%
  \dp2=0pt\relax%
  \makebox[\wd\ziv][r]{%
  \stackinset{r}{}{t}{}{\copy\ziv}{\copy2}}%
  }}}%
}
\makeatother
\begin{document}
1) \fbox{\diaghighlight{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}}

\medskip
\setstacktabbedgap{22pt}
2) $\left(\diaghighlight[.8]{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}\right)$

\medskip
\setstacktabbedgap{3pt}
\setstackgap{L}{28pt}
3) $\left[\diaghighlight[1]{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}\right]$

\medskip
4) $\left[\diaghighlight{a & bb & c\\12 & 4 & 56\\ x & y4 & z}\right]$

\end{document}

enter image description here


APPROACH 2

I managed to get rid of the bow tie and create a proper highlight strip!

\documentclass{article}
\usepackage{tabstackengine,xcolor,fp,rotating,trimclip}
\TABstackMath
\setstacktabbedgap{6pt}
\def\blfac{.7}% <--- DEFAULT FACTOR FOR WIDTH OF HIGHLIGHT
\fixTABwidth{T}
\newsavebox\ziv
\newlength\colbar
\makeatletter
\newcommand\diaghighlight[2][\blfac]{%
  \sbox\ziv{\Matrixstack{#2}}%
  \colbar=\dimexpr\ht\ziv+\dp\ziv+\wd\ziv\relax
  \sbox2{\textcolor{yellow}{\rule[-.5\colbar]{#1\normalbaselineskip}%
    {\colbar}}}%
  \edef\tmpH{\strip@pt\dimexpr\ht\ziv+\dp\ziv}%
  \edef\tmpW{\strip@pt\dimexpr\wd\ziv}%
  \FPdiv\zz{\tmpW}{\tmpH}%
  \FParctan\zz\zz%
  \FPmul\zz{\zz}{180}%
  \FPdiv\zz{\zz}{3.1415926}%
  \sbox2{\stackinset{c}{}{c}{}{\copy\ziv}{\rotatebox[origin=c]{\zz}{%
    \ensuremath{\vcenter{\hbox{\copy2}}}}}}%
  \@tempdima=.5\dimexpr\wd2-\tmpW pt\relax
  \@tempdimb=.5\dimexpr\ht2+\dp2-\tmpH pt\relax
  \clipbox{\@tempdima{} \@tempdimb{} \@tempdima{} \@tempdimb}{\copy2}%
}
\makeatother
\begin{document}
1) \fbox{\diaghighlight{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}}

\medskip
\setstacktabbedgap{22pt}
2) $\left(\diaghighlight[.9]{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}\right)$

\medskip
\setstacktabbedgap{3pt}
\setstackgap{L}{28pt}
3) $\left[\diaghighlight[1]{a & bb & c\\12 & 4 & 5644\\ x & y450 & z}\right]$

\medskip
4) $\left[\diaghighlight{a & bb & c\\12 & 4 & 56\\ x & y4 & z}\right]$
\end{document}

enter image description here

0

Perhaps by using a matrix of math nodes, like here. (an answer to one of my own questions).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .