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?

  • 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. – user121799 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? – Anush Mar 27 '19 at 15:14
  • Yes: tex.stackexchange.com/a/405152/121799 – user121799 Mar 27 '19 at 15:15
  • @marmot Ah. I tried just now bpaste.net/show/db6d4ebda072 but this doesn't work because mat doesn't exist. I need some pure tikz-cd solution it seems. – Anush Mar 27 '19 at 15:18
4

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.

| improve this answer | |
  • Yes, exactly! Thank you so much. – Anush Mar 27 '19 at 15:23
  • The calc addition is very educational. Thank you. – Anush Mar 27 '19 at 16:47
  • 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 :) – user156344 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 . – user121799 Mar 27 '19 at 17:05
4

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 :)

| improve this answer | |
  • I will also add arrows in the table and color some of the elements. – Anush Mar 27 '19 at 15:27
  • 2
    And: most users load tikz anyway for the tikzlings. ;-) – user121799 Mar 27 '19 at 15:27
  • Can you color an entire submatrix of a table out of interest? Say rows 1-2 and columns 4-6? – Anush Mar 27 '19 at 15:30
  • 3
    @Anush To color, you have \cellcolor. To make arrows, you can have a look at this nice answer. – user156344 Mar 27 '19 at 15:31
  • 2
    @Anush I edited my answer: I added some ways to add arrows, color columns and rows. – user156344 Mar 27 '19 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.