# Tikz - How to nest nodes in a matrix so they can be connected?

I want to make a matrix which has multiple nodes in a single matrix cell. These nodes should be centered to each other. I managed to make this work by using a nested tikz environment like so:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}[auto, semithick]
\tikzstyle{block} = [rectangle, draw,
minimum width=5em, text centered, rounded corners, minimum
height=4em]

\matrix[matrix of nodes, row sep = 2em,
nodes={anchor=center}
] (mx2){
% First row:
label1
&
\node{\tikz{
\node[block](n1){node1};
\node[block, right=of n1](n2){node2};
}};
\\
% Second row:
label2
&
\node{\tikz{
\node[block] (n3)
{node 3};
\node[block] (n4) [right=of n3]
{node 4};
\node[block] (n5) [right=of n4]
{node 5};
}};
\\
};
\draw (n1) -- (n4); % this fails
\end{tikzpicture}

\end{document}


Now connecting these nodes is impossible because of the nested tikz environments. I have tried to get a similar image using the fit library, but I did not manage to make it work. Can any of you help me out?

-
Just upload the image but the remove the ! character in the front. We will fix it for you until you get enough rep points to do it. –  percusse Apr 25 '12 at 10:43
I upvoted. Now you must be able to upload the figure. pl. try. –  Harish Kumar Apr 25 '12 at 10:53
Thank you for the upvoting, I added the picture –  Ruben Apr 25 '12 at 11:02

In general one can use the remember picture option and apply it all pictures, that should be accessible later. Since your pictures are nested and the options are inheritable, it’s sufficient to apply remeber picture only to the upper level {tikzpicture}.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}[auto, semithick,remember picture,
block/.style={rectangle, draw,
minimum width=5em, text centered, rounded corners, minimum
height=4em,text width=5em}
]
\matrix[matrix of nodes, row sep = 2em,
nodes={anchor=center}
] (mx2){
% First row:
label1
&
\node{\tikz{
\node[block](n1){node1};
\node[block, right=of n1](n2){node2};
}};
\\
% Second row:
label2
&
\node{\tikz{
\node[block] (n3)
{node 3};
\node[block] (n4) [right=of n3]
{node 4};
\node[block] (n5) [right=of n4]
{node 5};
}};
\\
};
\draw (n1) -- (n4); % this fails
\end{tikzpicture}

\end{document}


Compile twice to get the right result.

Note that I replaced \tikzstyle{block} by block/.style which is the preferred way. See Should \tikzset or \tikzstyle be used to define TikZ styles?.

-
Looks like remember picture is inherited: your first nested node doesn't have it and yet the position is computed correctly. –  Andrew Stacey Apr 25 '12 at 11:11
@AndrewStacey: I realized it my self a few second ago. I’ll edit my answer. –  Tobi Apr 25 '12 at 11:13
Thank you, it works! –  Ruben Apr 25 '12 at 11:15
@AndrewStacey Yes !! another possibility of nested pictures. –  Alain Matthes Apr 25 '12 at 11:20
@AndrewStacey: I removed my \tikzstle macros, thank you –  Ruben Apr 25 '12 at 11:26

You can avoid the nested pictures

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}[auto, semithick,remember picture,
block/.style={rectangle, draw,
minimum width=5em, text centered, rounded corners, minimum
height=4em,text width=5em}
]

\matrix[matrix of nodes, row sep = 2em,
nodes={anchor=center}
] (mx2){
% First row:
label1
&
\node[block,right=1em,anchor=west](n1){node1};
\node[block, right=of n1](n2){node2};
\\
% Second row:
label2
&
\node[block] (n3) {node 3};
\node[block] (n4) [right=of n3] {node 4};
\node[block] (n5) [right=of n4]  {node 5};
\\
};
\draw (n1) -- (n4); % this fails
\end{tikzpicture}

\end{document}


-
does this work when I have nodes of varying width? –  Ruben Apr 25 '12 at 11:38
If all you nodes have different width, I change the method. First with a matrix or a grid, I will define some coordinates ( centers of future nodes ) and then I place the nodes centered on these coordinates. Perhaps something like percusse's answer. It's difficult to give an answer without to see the real problem. –  Alain Matthes Apr 25 '12 at 12:40

I think matrix library is redundant here (though I'm abusing it continuously). Straight forward use is also possible and (in my opinion) more convenient. The positioning library is used anyway so we can keep on relying on that.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[
block/.style={rectangle, draw,
minimum width=5em, text centered, rounded corners, minimum
height=4em,text width=5em}
]
\node (l1) at (0,2) {label 1};
\node (l2) at (0,0) {label 2};
\node[right = 2.5cm of l1,block] (n1) {Node 1};
\node[right = of n1,block] (n2) {Node 2};
\node[right = 1cm of l2,block] (n3) {Node 3};
\node[right = of n3,block] (n4) {Node 4};
\node[block,right=of n4] (n5) {node 5};
\draw (n1) -- (n4); % this fails not :)
\end{tikzpicture}
\end{document}


Note that you can keep track of individual positioning and the default settings by node distance option and <direction> = x cm of nodename just as you would need to do by row sep and column sep when using matrices.

EDIT As Altermundus commented you can stack your rows by centering on a predefined grid of coordinates

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}[
block/.style={rectangle, draw, text centered, rounded corners, minimum height=4em}
]
\foreach \x in {0,...,2} \node[circle,inner sep=1mm,fill] (cent\x) at (2,2*\x) {};
%The center goes in between
\node[right=of cent0,block] (n1) {A very wide node 1};
\node[left =of cent0,block] (n2) {2};
%The center hits the node
\node[block] at (cent1) (n4) {node 4};
\node[block,left =of n4] (n3) {Also a quite wide node 3};
\node[block,right=of n4] (n5) {5};
\draw (n1) -- (n4); % this fails not :)
%This uses eyeballing after compiling. Choose the widest and adjust.Can be absolute too.
\node[left= of n3] (l2) {label 2};
\node (l1) at (l2 |- cent0){label 1};
\node (l3) at (l2 |- cent2){label 3};
\end{tikzpicture}
\end{document}


-
This does not seem to center the nodes automatically. In my diagram the nodes have varying widths and I would like to have the whole group centered. Or am I wrong? –  Ruben Apr 25 '12 at 11:41
@Ruben In which direction do you want to center them, when the node is full vertically or centering horizontally with respect to other nodes? –  percusse Apr 25 '12 at 11:43
I would like to horizontally move Node 1 and Node 2 together to the center of Node 3, Node 4 and Node 5. The distance between the nodes of the group should stay the same and the whole group should move horizontally to the center of the other group. –  Ruben Apr 25 '12 at 11:51
I think I understood. But you have used the text width=5em option which fixes the width. So I guess you are solving your own problem anyway :) Just put a long text in one of the nodes. –  percusse Apr 25 '12 at 12:08
Ah yes, I forgot about that. That was actually part of my debug efforts. This is not in the final diagram. Sorry for the confusion. But I take it your solution does not work for variable width nodes? –  Ruben Apr 25 '12 at 12:17
show 1 more comment