# How to draw complex nodes in tikz?

I know how to draw automaton in tikz. But how to use complex nodes in that? I want draw something like this in tikz:

-

Probably you can do it with the matrix library:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mymatrix/.style={draw,thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west}
]
\matrix[matrix of nodes, nodes=mymatrix] (firstmatrix) at (0,0)
{   q & w & e \\
a & s & d \\
};
\matrix[matrix of nodes, nodes=mymatrix] (secondmatrix) at (10,0)
{   i & o & p \\
j & k & l \\
};
\draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}


Edit 1: As Altermundus stated, the inner lines are double lines which is not desirable, so here's a solution using nodes and manually drawn lines (I'll try to automate this):

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mynode/.style={thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west},
mymatrix/.style={draw,inner sep=0}
]
\matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
{   \node (q) {q}; & w & \node (e) {e}; \\
\node (a) {a}; & s & \node (d) {d}; \\
};
\draw (q.south west) -- (e.south east);
\draw (q.north east) -- (a.south east);
\draw (e.north west) -- (d.south west);

\matrix[matrix of nodes, nodes=mynode, mymatrix] (secondmatrix) at (10,0)
{   \node (i) {i}; & o & \node (p) {p}; \\
\node (j) {j}; & k & \node (l) {l}; \\
};
\draw (i.south west) -- (p.south east);
\draw (i.north east) -- (j.south east);
\draw (p.north west) -- (l.south west);

\draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}


Edit 1.1: As Andrew Stacey remarked, it is of cause not neccessary to explicitely put nodes. You're in a matrix of nodes Neo, and not a slave. The individual cells all have names of the form matrixname-rownumber-columnnumber, and one can use this. The following produces exactly the same result as before:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mynode/.style={thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west},
mymatrix/.style={draw,inner sep=0},
myline/.style={shorten <=0.2pt, shorten >=0.2pt},
]
\matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
{   q & w & e \\
a & s & d \\
};
\draw[myline] (firstmatrix-1-1.south west) -- (firstmatrix-1-3.south east);
\draw[myline] (firstmatrix-1-1.north east) -- (firstmatrix-2-1.south east);
\draw[myline] (firstmatrix-1-3.north west) -- (firstmatrix-2-3.south west);

\matrix[matrix of nodes, nodes=mynode, mymatrix] (secondmatrix) at (10,0)
{   i & o & p \\
j & k & l \\
};
\draw[myline] (secondmatrix-1-1.south west) -- (secondmatrix-1-3.south east);
\draw[myline] (secondmatrix-1-1.north east) -- (secondmatrix-2-1.south east);
\draw[myline] (secondmatrix-1-3.north west) -- (secondmatrix-2-3.south west);

\draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}


Edit 2: Another way to "avoid" the double outline is to draw both the nodes and the matrix, but the latter with the double line width:

\tikzset{
mynode/.style={line width=0.25pt, draw, minimum width=1.0cm, minimum height=1.0cm, inner sep=0, anchor=south west},
mymatrix/.style={line width=0.5pt, draw, inner sep=0},
myline/.style={shorten <=0.2pt, shorten >=0.2pt},
}

\begin{tikzpicture}
\matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
{   q & w & e \\
a & s & d \\
};

\end{tikzpicture}


-
Thank you for your answer :) – tikzlearner Aug 17 '12 at 0:03
There is a little problem with the linewidth between the nodes. You get double lines. – Alain Matthes Aug 17 '12 at 6:50
Hmmm. Curious as to why you're using matrix of nodes and explicitly putting in the nodes. Also, your lines will be off if the nodes are of noticeably different sizes. See tex.stackexchange.com/a/21178/86 for a similar issue. – Loop Space Aug 17 '12 at 9:41
Dammit, it just struck me like a lightning: of cause the nodes are named name-row-column! D'oh! Thanks @AndrewStacey :D – Tom Bombadil Aug 17 '12 at 9:47

You can also use the infamous \tikzmark solution which allows one to compose the tables outside (or inside) of the tikzpicture environment, and mark the two points you want to connect, and then draw the arrow between them.

So, with the c data entry defined as c\tikzmark{left}, and the j data entry is defined as \tikzmark{right}j, one can use \DrawArrow[<draw_options>]{left}{right} with different draw options to obtain:

## Code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\newcommand*{\DrawArrow}[3][]{%
% #1 = draw options
% #2 = left point
% #3 = right point
\begin{tikzpicture}[overlay,remember picture]
\draw [-latex, shorten <= 0.25cm, shorten >= 0.30cm, #1] ($(#2)+(0,0.5ex)$) to ($(#3)+(0,0.25ex)$);
\end{tikzpicture}%
}%

\begin{document}
\begin{tabular}{| c | c | c |}\hline
a & b & c\tikzmark{left} \\\hline
d & e & f \\\hline
\end{tabular}
\hspace*{2.0cm}
\begin{tabular}{| c | c | c |}\hline
g & h & i \\\hline
\tikzmark{right}j & k & l \\\hline
\end{tabular}
%
\DrawArrow{left}{right}
\end{document}

-

This is an other idea based on Peter Grill's answer (I didn't even think of using a tabular when writing my first answer, so thanks for reminding me that there are some non-TikZ constructs one could use). It doesn't use \tikzmark (which otherwise is awesome, but in my humble opinion not needed here) and puts the tabulars in nodes instead, so you can use the degree notion (node.degree) to specify where to draw your arrows:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows}

\newcommand{\mytab}[2]% alignment, content
{   \begin{tabular}{#1}
#2
\end{tabular}
}

\begin{document}

\begin{tikzpicture}
\node[inner sep=0] (one) {\mytab{|c|c|c|}{\hline g & h & i \\ \hline j & k & l \\ \hline}};
\node[inner sep=0,right=2cm of one.east] (two) {\mytab{|c|c|c|}{\hline a & b & c \\ \hline d & e & f \\ \hline}};
\draw[-latex] (one.15) to[out=0,in=180] (two.195);
\end{tikzpicture}

\end{document}


-