3

I am drawing a matrix using tikz-cd. I would like to draw some vertical and horizontal lines on it too to indicate particular submatrices but I don't understand the syntax. This is my M(N)WE:

\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}[column sep=3pt, row sep=5pt,nodes={inner sep=0pt,align=center,
text width={width("20")}}]
&&0&0&0&0&0&0&0&0&0&0\\
&0&1&2&3&4&5&6&7&8&9&10\\
0&1&0&1&2&3&4&5&6&7&8&9\\
0&2&1&0&1&2&3&4&5&6&7&8\\
0&3&2&1&0&1&2&3&4&5&6&7\\
0&4&3&2&1&0&1&2&3&4&5&6
\foreach \x in {1,3}
{
    \draw 
    ([yshift=-3,xshift=-.125\pgflinewidth]mat-\x-1.south west) --   
    ([yshift=-3,xshift=-.125\pgflinewidth]mat-\x-12.south east);
}
\foreach \y in {2}
{
    \draw 
    ([yshift=.5\pgflinewidth]mat-1-\y.north east) -- 
    ([yshift=.5\pgflinewidth]mat-14-\y.south east);
}
\end{tikzcd}

\end{document}

This is syntactically incorrect but works if you remove the \foreach loops. How can I use the \foreach...\draw commands with a tikz-cd drawn matrix?

Simd
  • 6,785
  • You seem to be mixing two things. Yes, tikz-cd is using a tikz matrix, but the tikzcd environment does not give you a tikzpicture environment in which you can just use \draw. –  Mar 27 '19 at 15:12
  • @marmot Yes I am definitely confused. Is there some way to use tikz-cd to make the matrix and also use \draw to draw on it? Or alternatively some other way to draw horizontal and vertical lines to separate submatrices? – Simd Mar 27 '19 at 15:14
  • Yes: https://tex.stackexchange.com/a/405152/121799 –  Mar 27 '19 at 15:15
  • @marmot Ah. I tried just now https://bpaste.net/show/db6d4ebda072 but this doesn't work because mat doesn't exist. I need some pure tikz-cd solution it seems. – Simd Mar 27 '19 at 15:18

2 Answers2

5

Are you looking for this?

\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}[column sep=3pt, row sep=5pt,nodes={inner sep=0pt,align=center,
text width={width("20")}},nodes in empty cells,
execute at end picture={
\foreach \x in {1,3}
{
    \draw 
    ([yshift=-3,xshift=-.125\pgflinewidth]\tikzcdmatrixname-\x-1.south west) --   
    ([yshift=-3,xshift=-.125\pgflinewidth]\tikzcdmatrixname-\x-12.south east);
}
\foreach \y in {3}
{
    \draw 
    ([yshift=.5\pgflinewidth]\tikzcdmatrixname-1-\y.north west) -- 
    ([yshift=.5\pgflinewidth]\tikzcdmatrixname-6-\y.south west);
}}]
&&0&0&0&0&0&0&0&0&0&0\\
&0&1&2&3&4&5&6&7&8&9&10\\
0&1&0&1&2&3&4&5&6&7&8&9\\
0&2&1&0&1&2&3&4&5&6&7&8\\
0&3&2&1&0&1&2&3&4&5&6&7\\
0&4&3&2&1&0&1&2&3&4&5&6
\end{tikzcd}
\end{document}

enter image description here

Here I was employing Henri Menke's nice answer and added nodes in empty cells and changed some numbers to only use existing nodes.

ADDENDUM: If you want to the lines right in the middle between the cells without having to add all the shifts by fractions of the line width, you could use the calc library.

\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzcd}[column sep=3pt, row sep=5pt,nodes={inner sep=0pt,align=center,
text width={width("20")}},nodes in empty cells,
execute at end picture={
\foreach \x [evaluate=\x as \xp using {int(\x+1)}] in {1,3}
{
    \draw ($(\tikzcdmatrixname-\x-2.south)!0.5!(\tikzcdmatrixname-\xp-2.north)$)
    coordinate (aux)
    ([xshift=-.1em]\tikzcdmatrixname.west|-aux) --   
    ([xshift=.1em]\tikzcdmatrixname.east|-aux);
}
\foreach \y [evaluate=\y as \ym using {int(\y-1)}] in {3}
{
    \draw ($(\tikzcdmatrixname-1-\y.west)!0.5!(\tikzcdmatrixname-1-\ym.east)$)
    coordinate (aux)
    ([yshift=0.1ex]\tikzcdmatrixname.north-|aux) -- 
    ([yshift=0.1ex]\tikzcdmatrixname.south-|aux);
}}]
&&0&0&0&0&0&0&0&0&0&0\\
&0&1&2&3&4&5&6&7&8&9&10\\
0&1&0&1&2&3&4&5&6&7&8&9\\
0&2&1&0&1&2&3&4&5&6&7&8\\
0&3&2&1&0&1&2&3&4&5&6&7\\
0&4&3&2&1&0&1&2&3&4&5&6
\end{tikzcd}
\end{document}

As for the question what this might be good for: there are certain things that are somewhat harder to achieve with a table like e.g.

\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{tikz-cd}
\usetikzlibrary{calc,through,backgrounds} 
\tikzset{circle through 3 points/.style n args={3}{% 
insert path={let \p1=($(#1)!0.5!(#2)$), 
\p2=($(#1)!0.5!(#3)$), 
\p3=($(#1)!0.5!(#2)!1!-90:(#2)$), 
\p4=($(#1)!0.5!(#3)!1!90:(#3)$), 
\p5=(intersection of \p1--\p3 and \p2--\p4) 
in }, 
at={(\p5)}, 
circle through= {(#1)} 
}} 
\begin{document}
\begin{tikzcd}[column sep=3pt, row sep=5pt,nodes={inner sep=0pt,align=center,
text width={width("20")}},nodes in empty cells,
execute at end picture={
\foreach \x [evaluate=\x as \xp using {int(\x+1)}] in {1,3}
{
    \draw ($(\tikzcdmatrixname-\x-2.south)!0.5!(\tikzcdmatrixname-\xp-2.north)$)
    coordinate (aux)
    ([xshift=-.1em]\tikzcdmatrixname.west|-aux) --   
    ([xshift=.1em]\tikzcdmatrixname.east|-aux);
}
\foreach \y [evaluate=\y as \ym using {int(\y-1)}] in {3}
{
    \draw ($(\tikzcdmatrixname-1-\y.west)!0.5!(\tikzcdmatrixname-1-\ym.east)$)
    coordinate (aux)
    ([yshift=0.1ex]\tikzcdmatrixname.north-|aux) -- 
    ([yshift=0.1ex]\tikzcdmatrixname.south-|aux);
}
\begin{scope}[on background layer]
 \node[circle through 3
 points={\tikzcdmatrixname-2-2}{\tikzcdmatrixname-3-1}{\tikzcdmatrixname-3-3},
 fill=blue!20]{}; 
\end{scope}
}]
&&0&0&0&0&0&0&0&0&0&0\\
&0&1&2&3&4&5&6&7&8&9&10\\
0&1&0&1&2&3&4&5&6&7&8&9\\
0&2&1&0&1&2&3&4&5&6&7&8\\
0&3&2&1&0&1&2&3&4&5&6&7\\
0&4&3&2&1&0&1&2&3&4&5&6
\end{tikzcd}
\end{document}

enter image description here

Yet for many purposes, the table approach suggested by Joule V is just fine or even better. It really depends on what you want to do in the end.

  • I'm not aiming to make a war but I do think the last figure is still not difficult ;) We just need some help of a remember picture, overlay TikZ picture :) –  Mar 27 '19 at 17:01
  • 1
    @JouleV This meant to be really friendly. AFAIK you cannot achieve this with remember picture easily because you cannot draw it on the background after the table is "done" unless you use atbegshi or something like this, or do something with blend mode . –  Mar 27 '19 at 17:05
5

Just for fun: if you want to make that matrix, why don't use a table? The code is much shorter:

\documentclass{article}
\begin{document}
\renewcommand{\arraystretch}{1.3}
\begin{tabular}{cc|cccccccccc}
    &&0&0&0&0&0&0&0&0&0&0\\\hline
    &0&1&2&3&4&5&6&7&8&9&10\\
    0&1&0&1&2&3&4&5&6&7&8&9\\\hline
    0&2&1&0&1&2&3&4&5&6&7&8\\
    0&3&2&1&0&1&2&3&4&5&6&7\\
    0&4&3&2&1&0&1&2&3&4&5&6
\end{tabular}
\end{document}

enter image description here

Coloring the text is not difficult, isn't it? If you want to draw some arrows, \tikzmark may be an option. Anyway, if I were you, I would use a simple table. :)


Add an arrow

\documentclass{article}
\usepackage{tikz}
\begin{document}
\renewcommand{\arraystretch}{1.3}
\begin{tabular}{cc|cccccccccc}
    &&0&0&0&0&0&0&0&0&0&0\\\hline
    &0&1&2&3&4&5&6&7&8&9&10\\
    0&\tikz[baseline,remember picture]\node[anchor=base,inner sep=0pt] (node1) {1};&0&1&2&3&4&5&6&7&8&9\\\hline
    0&2&1&0&1&2&3&4&5&6&7&8\\
    0&3&2&1&0&1&2&\tikz[baseline,remember picture]\node[anchor=base,inner sep=0pt] (node2) {3};&4&5&6&7\\
    0&4&3&2&1&0&1&2&3&4&5&6
\end{tabular}

\begin{tikzpicture}[remember picture,overlay]
\draw[red,very thick,-latex] (node1) -- (node2);
\end{tikzpicture}
\end{document}

enter image description here


Color row(s)

\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor,colortbl}
\begin{document}
\renewcommand{\arraystretch}{1.3}
\begin{tabular}{cc|cccccccccc}
    \rowcolor{red!20}&&0&0&0&0&0&0&0&0&0&0\\\hline
    \rowcolor{red!20}&0&1&2&3&4&5&6&7&8&9&10\\
    0&1&0&1&2&3&4&5&6&7&8&9\\\hline
    0&2&1&0&1&2&3&4&5&6&7&8\\
    0&3&2&1&0&1&2&3&4&5&6&7\\
    0&4&3&2&1&0&1&2&3&4&5&6
\end{tabular}
\end{document}

enter image description here


Color column(s)

\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor,colortbl}
\begin{document}
\renewcommand{\arraystretch}{1.3}
\begin{tabular}{cc|ccc>{\columncolor{yellow!50}}cc>{\columncolor{green!20}}ccccc}
    &&0&0&0&0&0&0&0&0&0&0\\\hline
    &0&1&2&3&4&5&6&7&8&9&10\\
    0&1&0&1&2&3&4&5&6&7&8&9\\\hline
    0&2&1&0&1&2&3&4&5&6&7&8\\
    0&3&2&1&0&1&2&3&4&5&6&7\\
    0&4&3&2&1&0&1&2&3&4&5&6
\end{tabular}
\end{document}

enter image description here


It is never impossible to work with tables using table commands :)