# TikZ matrix of objects in LaTeX

I want to make a TikZ matrix of objects, and then draw some vertical and horizontal lines. For instance, I would like to put the elements of the Polygon division example inside a tabular environment. So far, I checked more than 20 similar questions and none of them could really help me.

I created the following minimal working example of what I want. The idea is to create all the possible simple networks of 3 vertices, and draw them in big rows according to their edge numbers (m), and grouped in columns depending on the degrees of the vertices of the top (k's). In every row, I put at the top the cases where the horizontal thicker edge exist and at the bottom where it doesn't. Every big column is defined by the degree of the vertex at the top left, and every smaller individual subcolumn has the degree pair of the top left and top right vertices, respectively.

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}

\def\side{0.5} % Define the size of the triangle's side

\newcommand{\slice}[1]{% Inverted triangle network
\filldraw (-\side/2, {sqrt(3)*\side/2}) circle (1pt) (\side/2, {sqrt(3)*\side/2}) circle (1pt) (0, 0) circle (1pt);
\filldraw \foreach \x/\y in {#1} {(\x) -- (\y)};
}

\begin{tikzpicture}
% Define the inverted triangle coordinates
\coordinate (A) at (-\side/2, {sqrt(3)*\side/2});
\coordinate (B) at (\side/2, {sqrt(3)*\side/2});
\coordinate (C) at (0, 0);

% Start the matrix
\matrix (M) [matrix of nodes, nodes={text width=7mm}, row sep=\side*0.3cm]
{
{} & 0 & {} & {} & 1 & {} & {} & 2 & $k_i$ \\
{} & $[0,0]$ & $[0,1]$ & $[1,0]$ & $[1,1]$ & $[1,2]$ & $[2,1]$ & $[2,2]$ & $[k_i,k_j]$ \\
0 & \slice{} & {} & {} & {} & {} & {} & {} & {} \\
{} & {} & {} & {} & \slice{A/B} \draw[ultra thick] (A) -- (B); & {} & {} & {} & {} \\
1 & {} & \slice{B/C} & \slice{A/C} & {} & {} & {} & {} & {} \\
{} & {} & {} & {} & {} & \slice{A/B, B/C} \draw[ultra thick] (A) -- (B); & \slice{A/B, A/C} \draw[ultra thick] (A) -- (B);  & {} & {} & {} \\
2 & {} & {} & {} & \slice{A/C, B/C} & {} & {} & {} & {} \\
3 & {} & {} & {} & {} & {} & {} & \slice{A/B, A/C, B/C} \draw[ultra thick] (A) -- (B); & {} \\
{} & {} & {} & {} & {} & {} & {} & {} & {} \\
$m$ & {} & {} & {} & {} & {} & {} & {} & {} \\
};
% vertical lines
\foreach \i in {2,...,9}{
\draw (M-2-\i.north west) -- (M-9-\i.south west);
}
\draw[ultra thick]
(M-1-2.north west) -- (M-9-2.south west)
(M-1-4.north west) -- (M-9-4.south west)
(M-1-7.north west) -- (M-9-7.south west)
(M-1-9.north west) -- (M-9-9.south west)
;
% horizontal lines
\draw
(M-2-2.south west) -- (M-2-8.south east)
(M-3-1.south west) -- (M-3-8.south east)
(M-5-1.south west) -- (M-5-8.south east)
(M-7-1.south west) -- (M-7-8.south east)
(M-9-1.south west) -- (M-9-8.south east)
;
\end{tikzpicture}

\end{document}


The problems I faced are:

1. When drawing the vertical and horizontal lines, I was forced to add extra rows or columns, because other way I received an error like

Package pgf Error: No shape named M-i-j is known...

where of course i-j represents the location of my object (triangular network). A good example of this is the penultimate row that I added. As soon as there is no object in the matrix node, even if there is an empty element like {}, everything is OK.

1. I don't know what is the best way to center the row or columns numbers. Is even hard to do it for the degree pairs inside the brackets, so I did it manually playing with the command

text width,

and for the network objects I had to manually adjust their coordinate positions.

1. I don't quite understand why the thicker vertical lines are not of the same size. In general, I would like to easily control and draw the lines. Any suggestion to make it similar to a tabular environment will be highly appreciated.
2. The reason why I left m and the k's in their actual position is because what I explained in 1., so if somebody could help me to put them nicely in the top left corner of the matrix it will be awesome.

Jorge

• Welcome to TeX.SE! I do not yet fully understand your code and problems, but it seems to me that you are nesting tikzpictures. That is, you have a matrix of nodes and then use \filldraw inside the node contents. You may get rid of many issues by using path pictures instead. – user121799 Aug 10 '18 at 15:55
• Thanks for your welcoming message :) I googled path picture examples and couldn't find anything useful yet, unfortunately. Could you provide an specific example maybe? – Jorge Aug 10 '18 at 16:09

1. The shape unknown errors come because you did not tell TikZ that you want nodes in empty cells.
2. One of the issues of your approach is that you are nesting tikzpictures. It is sort of intuitive that text width clashes with nested tikzpictures. You can use minimum size and align=center.
3. I do not understand your 3rd question but in the answer below the lines have the width they got assigned.
4. I do not understand the 4th question either, but perhaps you could just tell me where the (which?) k should be.

Here is the updated code. Please note also that, in order to have the lines between the cells, one also has to draw them between, not south east or so of a given cell. This won't work because there are gaps between the cells. And this is the reason why I use all the ($(...)!0.5!(...)$) syntax, which just computes the average of two coordinates. I also made an effort in adding explanations in the code.

\documentclass[border=3.14mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,calc,fit}
\newcounter{slicenum}

\begin{document}

\def\side{0.5} % Define the size of the triangle's side

% in order to avoid nesting nodes, we draw the triangles as path pictures
% another option would be to store the triangles in \savebox es and use those
% for the nodes. But this approach is more flexible.
% Also, in order to avoid confusion, I introduced a counter to discriminate
% the nodes. Of course, this is not strictly necessary, and one may make this
% slightly more elegant by using prefixes, but for the moment this will do.
\tikzset{slice/.style={path picture={
\stepcounter{slicenum}
% \draw (path picture bounding box.south west) rectangle
% (path picture bounding box.north east);
\coordinate (O-\theslicenum) at ($(path picture bounding box.south west)!0.5!(path picture bounding box.north east)$);
\pgfmathsetmacro{\myshift}{2*(1-sqrt(3)/2)*\side}
\coordinate (A-\theslicenum) at
($(O-\theslicenum)+(150:\side)+(0,{\myshift})$);
\coordinate (B-\theslicenum) at ($(O-\theslicenum)+(30:\side)+(0,{\myshift})$);
\coordinate (C-\theslicenum) at ($(O-\theslicenum)+(-90:\side)+(0,{\myshift})$);
\filldraw (A-\theslicenum) circle (1pt) (B-\theslicenum) circle (1pt) (C-\theslicenum) circle (1pt);
\foreach \x/\y/\z in {#1} {\draw[\z] (\x-\theslicenum) -- (\y-\theslicenum);}
}}}

\begin{tikzpicture}

% Start the matrix
\matrix (M) [matrix of nodes,nodes in empty cells,nodes={
minimum width=2.4*\side*1cm,minimum height=2*\side*1cm,align=center}]
{
&  &  &  &  &  &  &  &  \\
\makebox[0.8cm][r]{$[k_i,k_j]$} & $[0,0]$ & $[0,1]$ & $[1,0]$ & $[1,1]$ & $[1,2]$ & $[2,1]$ & $[2,2]$ &
\\
& |[slice=]| &  &  &  &  &  &  &  \\
&  &  &  & |[slice={A/B/ultra thick}]| &  &  &  &  \\
&  & |[slice={B/C/}]| & |[slice={A/C/}]| &  &  &  &  &  \\
&  &  &  &  & |[slice={A/B/ultra thick, B/C/}]| & |[slice={A/B/ultra thick, A/C/}]|
&  &  &  \\
&  &  &  & |[slice={A/C/, B/C/}]| &  &  &  &  \\
&  &  &  &  &  &  & |[slice={A/B/ultra thick, A/C/, B/C/}]| &  \\
&  &  &  &  &  &  &  &  \\
&  &  &  &  &  &  &  &  \\
};
\path (M-1-2) -- (M-1-3) node[midway]{0}  (M-1-4) -- (M-1-6) node[midway]{1}
(M-1-7) -- (M-1-8) node[midway]{2} (M-1-1) node[right]{$k_i$};
\path (M-3-1) node(0){$0$} (M-4-1)-- (M-5-1) node[midway](1){$1$}
(M-6-1)-- (M-7-1) node[midway](2){$2$}  (M-8-1)-- (M-9-1) node[midway](3){$3$} ;
% horizontal lines
\path (0) -- (3) node[midway,left=6mm] (m) {$m$};
\foreach \X in {0,...,3}
{\draw[-latex] (m) to[out=90-\X*60,in=180] (\X);}
\newcommand{\DrawHorizontalLineInMatrix}[3][]{
\xdef\Lst{(M-#2-2)}
\foreach \XX in {3,...,8}
{\xdef\Lst{\Lst (M-#2-\XX)}}
\node [fit=\Lst,inner sep=0pt] (fit-#2) {};
\xdef\Lst{(M-#3-2)}
\foreach \XX in {3,...,8}
{\xdef\Lst{\Lst (M-#3-\XX)}}
\node [fit=\Lst,inner sep=0pt] (fit-#3) {};
\draw[#1] ($(fit-#2.south west)!0.5!(fit-#3.north west)$)
-- ($(fit-#2.south east)!0.5!(fit-#3.north east)$);
}
\foreach \X[evaluate=\X as \Y using {int(\X-1)}] in {2,4,...,10}
{
\DrawHorizontalLineInMatrix[]{\Y}{\X}
}
% vertical lines
\newcommand{\DrawVerticalLineInMatrix}[3][]{
\xdef\Lst{(M-1-#2)}
\foreach \XX in {2,...,9}
{\xdef\Lst{\Lst (M-\XX-#2)}}
\node [fit=\Lst,inner sep=0pt] (fit-#2) {};
\xdef\Lst{(M-1-#3)}
\foreach \XX in {2,...,9}
{\xdef\Lst{\Lst (M-\XX-#3)}}
\node [fit=\Lst,inner sep=0pt] (fit-#3) {};
\draw[#1] ($(fit-#2.north east)!0.5!(fit-#3.north west)$)
-- ($(fit-#2.south east)!0.5!(fit-#3.south west)$);
}
\DrawVerticalLineInMatrix{1}{2}
\foreach \X[evaluate=\X as \Y using {int(\X-1)}] in {2,4,7,9}
{
\DrawVerticalLineInMatrix[ultra thick]{\Y}{\X}
}
\end{tikzpicture}
\end{document}


• Hi @marmot and thanks a lot. I read your fist answer and now the updated version. Regarding my 3rd question, in the code I wrote, the vertical lines are clearly of different size, is not important now with your solution. About the 4th question, $k_i$ represents the first element in the bracket, and this means your third and fourth vertical lines (from left to right) are misplaced, but is fixed easily changing {2,4,6,8} to {2,4,7,9} in one if the last lines of your code. I think the k's should be at the left and not at the right of the expressions. The same for m, it should be up and not down. – Jorge Aug 10 '18 at 21:40
• I guess the most appealing way to see a matrix like this is similar to a joint probability table, see for instance math.stackexchange.com/questions/2634751/… so instead of X and Y, we have k_i, [k_i,k_j] for X, and m for Y. But is just an idea, maybe in LaTeX there is something better or simpler. – Jorge Aug 10 '18 at 22:27
• @Jorge Either way but let's just remove all obsolete comments... – user121799 Aug 10 '18 at 23:24

An option using scope to locate a definition drawing inside respective matrix node center.

RESULT:

MWE:

\documentclass[tikz,border=14pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows.meta, positioning,fit,shapes}

\begin{document}
\begin{tikzpicture}[
%Environment config
>={Stealth[inset=0pt,length=6pt]},
%Environment Styles
MyMatrix/.style={
matrix of nodes,
font=\scriptsize,
line width=0.75pt,
column sep=-0.5pt,
row sep=-0.5pt,
text height=18pt,
text width =24pt,
text depth =12pt,
align=center,
nodes={draw=none},
nodes in empty cells
}
]

% Start Drawing the thing
\matrix[
MyMatrix,
column 1/.style={nodes={draw=none},text width =12pt},
row 1/.style={text height =9pt,text depth =6pt},
row 2/.style={text height =9pt,text depth =4pt}
] at (0,0) (M1){%Matrix contents
&&&&&&&&\\
&$[0,0]$&$[0,1]$&$[1,0]$&$[1,1]$&$[1,2]$&$[2,1]$&$[2,2]$&$[k_i,k_j]$\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
};
%Draw thick vertical lines
\foreach \x in {1,3,5,7,9}{
\draw[line width=2pt](M1-1-\x.north east) -- (M1-10-\x.south east);
}
%Draw horizontal lines
\foreach \x in {1,2,...,10}{
\draw[line width=0.5pt](M1-\x-1.south east) -- (M1-\x-9.south east);
}
%Label row1
\foreach \x [count=\k from 1, evaluate=\k as \m using {int(\k*2)}] in {0,1,2,$k_i$}{
\node at (M1-1-\m.0){\x};
}
%Label col1
\foreach \x [count=\k from 1, evaluate=\k as \m using {int(1+\k*2)}] in {0,1,2,3}{
\node at (M1-\m-1.center){\x};
}

\def\slice(#1)[#2][#3][#4]{
\begin{scope}[shift={(#1)}]
\node[circle,fill,inner sep=1pt](c1) at (30:10pt){};
\node[circle,fill,inner sep=1pt](c2) at (150:10pt){};
\node[circle,fill,inner sep=1pt](c3) at (270:10pt){};
\path[#2](c1.center)--(c2.center);
\path[#3](c2.center)--(c3.center);
\path[#4](c3.center)--(c1.center);
\end{scope}
}

\slice(M1-3-2.center)[][][]
\slice(M1-5-3.center)[][][draw]
\slice(M1-5-4.center)[][draw][]
\slice(M1-4-5.center)[draw,very thick][][]
\slice(M1-6-6.center)[draw,very thick][][draw]
\slice(M1-6-7.center)[draw,very thick][draw][]
\slice(M1-7-5.center)[][draw][draw]
\slice(M1-9-8.center)[draw,very thick][draw][draw]

\end{tikzpicture}
\end{document}

• Hola @J Leon V. y muchas gracias por tu respuesta. I modified part of your code to achieve my requirements. It seems that I can't reply directly here with my new version of your code. Basically, I deleted many horizontal lines, added all the normal vertical lines, and corrected the misplaced third and fourth vertical lines (from left to right), as I previously explained to @marmot in the previous reply. I had to manually add the labels though. Should I write a new reply to my post to include this new version of your code? Thanks again! – Jorge Aug 10 '18 at 23:17
• Que bien, Español !!!, Well, sometimes the OP brings some picture or hand drawing photo to explain what they need, and then the attempt code to scape from the "do it for me" situation to "helpme to achieve this", that help us to obtain the desired result, that I did was to propose a solution to draw inside matrix nodes and not more; and feel free to use or modify the code, but its polite to refer the author to recognize his / her dedicated time to answer. – J Leon V. Aug 11 '18 at 0:11

My version of J Leon V.'s code is

\documentclass[tikz,border=14pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows.meta, positioning,fit,shapes}

\begin{document}
\begin{tikzpicture}[
%Environment config
>={Stealth[inset=0pt,length=6pt]},
%Environment Styles
MyMatrix/.style={
matrix of nodes,
font=\scriptsize,
line width=0.75pt,
column sep=-0.5pt,
row sep=-0.5pt,
text height=18pt,
text width =24pt,
text depth =12pt,
align=center,
nodes={draw=none},
nodes in empty cells
}
]

% Start Drawing the thing
\matrix[
MyMatrix,
column 1/.style={nodes={draw=none},text width =12pt},
row 1/.style={text height =9pt,text depth =6pt},
row 2/.style={text height =9pt,text depth =4pt}
] at (0,0) (M1){%Matrix contents
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
&&&&&&&&\\
};
%Draw thick vertical lines
\foreach \x in {1,3,6,8}{
\draw[line width=2pt](M1-1-\x.north east) -- (M1-8-\x.south east);
}
%Draw vertical lines
\foreach \x in {1,2,...,8}{
\draw[line width=0.5pt](M1-2-\x.north east) -- (M1-8-\x.south east);
}
%Draw horizontal lines
\foreach \x in {2,3,5,7,8}{
\draw[line width=0.5pt](M1-\x-1.south east) -- (M1-\x-8.south east);
}
%Label row1
\node at (M1-1-2.0){0};
\node at (M1-1-5.center){1};
\node at (M1-1-7.0){2};
\node at (M1-1-9.center){$k_i$};
\node at (M1-2-2.center){$[0,0]$};
\node at (M1-2-3.center){$[0,1]$};
\node at (M1-2-4.center){$[1,0]$};
\node at (M1-2-5.center){$[1,1]$};
\node at (M1-2-6.center){$[1,2]$};
\node at (M1-2-7.center){$[2,1]$};
\node at (M1-2-8.center){$[2,2]$};
\node at (M1-2-9.center){$[k_i,k_j]$};
%Label col1
\node at (M1-3-1.center){0};
\node at (M1-5-1.north){1};
\node at (M1-7-1.north){2};
\node at (M1-8-1.center){3};
\node at (M1-9-1.center){$m$};

\def\slice(#1)[#2][#3][#4]{
\begin{scope}[shift={(#1)}]
\node[circle,fill,inner sep=1pt](c1) at (30:10pt){};
\node[circle,fill,inner sep=1pt](c2) at (150:10pt){};
\node[circle,fill,inner sep=1pt](c3) at (270:10pt){};
\path[#2](c1.center)--(c2.center);
\path[#3](c2.center)--(c3.center);
\path[#4](c3.center)--(c1.center);
\end{scope}
}

\slice(M1-3-2.center)[][][]
\slice(M1-5-3.center)[][][draw]
\slice(M1-5-4.center)[][draw][]
\slice(M1-4-5.center)[draw,very thick][][]
\slice(M1-6-6.center)[draw,very thick][][draw]
\slice(M1-6-7.center)[draw,very thick][draw][]
\slice(M1-7-5.center)[][draw][draw]
\slice(M1-8-8.center)[draw,very thick][draw][draw]

\end{tikzpicture}
\end{document}


And the result is

My version of @marmot code is

\documentclass[border=3.14mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,calc,fit}
\newcounter{slicenum}

\begin{document}

\def\side{0.5} % Define the size of the triangle's side

\tikzset{slice/.style={path picture={
\stepcounter{slicenum}
\coordinate (O-\theslicenum) at ($(path picture bounding box.south west)!0.5!(path picture bounding box.north east)$);
\pgfmathsetmacro{\myshift}{2*(1-sqrt(3)/2)*\side}
\coordinate (A-\theslicenum) at
($(O-\theslicenum)+(150:\side)+(0,{\myshift})$);
\coordinate (B-\theslicenum) at ($(O-\theslicenum)+(30:\side)+(0,{\myshift})$);
\coordinate (C-\theslicenum) at ($(O-\theslicenum)+(-90:\side)+(0,{\myshift})$);
\filldraw (A-\theslicenum) circle (1pt) (B-\theslicenum) circle (1pt) (C-\theslicenum) circle (1pt);
\foreach \x/\y/\z in {#1} {\draw[\z] (\x-\theslicenum) -- (\y-\theslicenum);}
}}}

\begin{tikzpicture}
% Start the matrix
\matrix (M) [matrix of nodes, nodes in empty cells, nodes={minimum width=2.4*\side*1cm, minimum height=2*\side*1cm, align=center}]
{
&  &  &  &  &  &  &  &  \\
& $[0,0]$ & $[0,1]$ & $[1,0]$ & $[1,1]$ & $[1,2]$ & $[2,1]$ & $[2,2]$ & \\
& |[slice=]| &  &  &  &  &  &  &  \\
&  &  &  & |[slice={A/B/ultra thick}]| &  &  &  &  \\
&  & |[slice={B/C/}]| & |[slice={A/C/}]| &  &  &  &  &  \\
&  &  &  &  & |[slice={A/B/ultra thick, B/C/}]| & |[slice={A/B/ultra thick, A/C/}]|
&  &  &  \\
&  &  &  & |[slice={A/C/, B/C/}]| &  &  &  &  \\
&  &  &  &  &  &  & |[slice={A/B/ultra thick, A/C/, B/C/}]| &  \\
&  &  &  &  &  &  &  &  \\
};
\path (M-1-2) -- (M-1-3) node[midway]{0} (M-1-4) -- (M-1-6) node[midway]{1} (M-1-7) -- (M-1-8) node[midway]{2} (M-1-1) node[right]{$k_i$};
\path (M-2-1) node[]{$[k_i,k_j]$};
\path (M-3-1) node(0){$0$} (M-4-1) -- (M-5-1) node[midway](1){$1$} (M-6-1) -- (M-7-1) node[midway](2){$2$} (M-8-1) node(3){$3$} ;
% horizontal lines
\path (0) -- (3) node[midway,left=6mm] (m) {$m$};
\foreach \X in {0,...,3}
{\draw[-latex] (m) to[out=90-\X*60,in=180] (\X);}
\newcommand{\DrawHorizontalLineInMatrix}[3][]{
\xdef\Lst{(M-#2-2)}
\foreach \XX in {3,...,8}
{\xdef\Lst{\Lst (M-#2-\XX)}}
\node [fit=\Lst,inner sep=0pt] (fit-#2) {};
\xdef\Lst{(M-#3-2)}
\foreach \XX in {3,...,8}
{\xdef\Lst{\Lst (M-#3-\XX)}}
\node [fit=\Lst,inner sep=0pt] (fit-#3) {};
\draw[#1] ($(fit-#2.south west)!0.5!(fit-#3.north west)$)
-- ($(fit-#2.south east)!0.5!(fit-#3.north east)$);
}
\foreach \X[evaluate=\X as \Y using {int(\X-1)}] in {3,4,6,8,9}
{
\DrawHorizontalLineInMatrix[]{\Y}{\X}
}
% thick vertical lines
\newcommand{\DrawThickVerticalLineInMatrix}[3][]{
\xdef\Lst{(M-1-#2)}
\foreach \XX in {2,...,8}
{\xdef\Lst{\Lst (M-\XX-#2)}}
\node [fit=\Lst,inner sep=0pt] (fit-#2) {};
\xdef\Lst{(M-1-#3)}
\foreach \XX in {2,...,8}
{\xdef\Lst{\Lst (M-\XX-#3)}}
\node [fit=\Lst,inner sep=0pt] (fit-#3) {};
\draw[#1] ($(fit-#2.north east)!0.5!(fit-#3.north west)$)
-- ($(fit-#2.south east)!0.5!(fit-#3.south west)$);
}
\DrawThickVerticalLineInMatrix{1}{2}
\foreach \X[evaluate=\X as \Y using {int(\X-1)}] in {2,4,7,9}
{
\DrawThickVerticalLineInMatrix[ultra thick]{\Y}{\X}
}
% vertical lines
\newcommand{\DrawVerticalLineInMatrix}[3][]{
\xdef\Lst{(M-2-#2)}
\foreach \XX in {2,...,8}
{\xdef\Lst{\Lst (M-\XX-#2)}}
\node [fit=\Lst,inner sep=0pt] (fit-#2) {};
\xdef\Lst{(M-2-#3)}
\foreach \XX in {2,...,8}
{\xdef\Lst{\Lst (M-\XX-#3)}}
\node [fit=\Lst,inner sep=0pt] (fit-#3) {};
\draw[#1] ($(fit-#2.north east)!0.5!(fit-#3.north west)$)
-- ($(fit-#2.south east)!0.5!(fit-#3.south west)$);
}
\foreach \X[evaluate=\X as \Y using {int(\X-1)}] in {3,5,6,8}
{
\DrawVerticalLineInMatrix[]{\Y}{\X}
}
\end{tikzpicture}
\end{document}


And the result is