7

I'm trying to draw specific arrows from table cells to nodes. This is what I have done so far:

enter image description here

I'm trying to get this:

enter image description here

This is my code:

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc}
\usetikzlibrary{arrows,automata}
\begin{document}
\begin{tikzpicture}[->,>=stealth,node distance=4cm,semithick]
  \tikzstyle{every state}=[draw=black,text=black,minimum size=2cm]

  \node[state]at (0,0)(0)  {
                    \begin{tabular}{|c|}
                    \hline
                    \rowcolor{gray!50}
                     5   \\\hline
                     13  \\\hline
                     14  \\\hline
                    \end{tabular}
                   };
  \node[state]at (-4,-4)(1)  {
                    \begin{tabular}{|c|  }
                    \hline
                     \cellcolor{gray!50} 1   \\\hline
                     11  \\\hline
                     12  \\\hline
                    \end{tabular}
                   };

  \node[state](2)  at (-2,-8){
                    \begin{tabular}{|c|  }
                    \hline
                     \cellcolor{gray!50} 2   \\\hline
                     17  \\\hline
                     18  \\\hline
                    \end{tabular}
                   };;
  \node[state](3) at (4,-4) {
                    \begin{tabular}{|c|  }
                    \hline
                     \cellcolor{gray!50} 3   \\\hline
                     15  \\\hline
                     16  \\\hline
                    \end{tabular}
                   };
  \node[fill=gray!50,state](4)  at (6,-8)   {4 jump };
  %\node[fill=gray!50,draw=black,text=black,minimum size=2cm](6)  at (6,-8) { };
   \node[draw=black,thick,circle,inner sep=4.5pt](6)  at (6,-8)   {4 jump };
  \node[state](5)   at (-6,0)     {
                    \begin{tabular}{|c|  }
                    \hline
                     \cellcolor{gray!50} 5   \\\hline
                     17  \\\hline
                     18  \\\hline
                    \end{tabular}
                   };

\draw (0) -- (1);
\draw (0) -- (3);  

\draw (1) -- (3);
\draw (1) -- (2);

\draw (2) -- (4);
\draw[transform canvas={xshift=4pt,yshift=2pt}] (2)--(1);

\draw (3) -- (2);
\draw (3) -- (4);

\draw (5) -- (1);
\draw (5) -- (3);


\end{tikzpicture}

\end{document}

Is there a way to do that?

  • 2
    Please forgive me, but to me, your result looks much smoother and more elegant, than the second image. I think, you don't need the "bumps" at the crossing lines, as you have arrows at the end. Unless you really need to connect a particular cell in the table, there is neither a need, to elongate the lines into the circles. Its just my two cents, but I'd stay with that neat and clean result, you have achieved. It is very appealing to me! – Jan Jan 19 '17 at 13:28
  • I completely agree! – pschulz Jan 19 '17 at 13:30
  • Thanks, but I'm trying to get the arrows to start from the cells not the the node. – user123348 Jan 19 '17 at 13:31
  • 1
    I have no time to try now, but if you use a native tikzmatrix instead of the circular nodes with tabulars inside you can address the individual cells easily. You can then draw a circle around them if you really want... otherwise, you can use tikzmark tex.stackexchange.com/a/295987/38080 – Rmano Jan 19 '17 at 13:36
  • Another method could be to write the Contents of the cells next to the arrow, this way you could Show, which value is used. But then again i don't know what you want to Show. – pschulz Jan 19 '17 at 13:48
7

with multipart shapes instead of tables:

enter image description here

\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{arrows,
                automata, 
                calc, 
                fit,                % <-- added
                shapes.multipart,   % <-- added
                tikzmark}

\begin{document}
    \begin{tikzpicture}[->,>=stealth, semithick,
 node distance = 4cm, 
  state/.style = {shape=rectangle split, draw,
                  rectangle split parts=3,
                  rectangle split part fill={gray!30,white},
                  minimum width=20mm},
fitnode/.style = {shape=circle, draw, inner sep=1pt,outer sep=0pt,
                  node contents={}}                    
                        ]
\node (0) [state]               {                   5   \\
                                \nodepart{two}      13  \\
                                \nodepart{three}    14  
                                };
\node (10) [fitnode, fit=(0)];
\node (1) [state] at (-4,-4)    {                   1   \\ 
                                \nodepart{two}      11  \\
                                \nodepart{three}    12  
                                };
\node (11) [fitnode,fit=(1)];
\node (2) [state] at (-2,-8)    {                   2   \\ 
                                \nodepart{two}      17  \\
                                \nodepart{three}    18  
                                };
\node (12) [fitnode,fit=(2)];
\node (3) [state] at (4,-4)    {                    3   \\ 
                                \nodepart{two}      15  \\
                                \nodepart{three}    16  
                                };
\node (13) [fitnode,fit=(3)];
\node (4) [shape=circle,draw, fill=gray!50, 
           double=gray!50,double distance=2mm, 
           align=center,
           inner sep=3mm,outer sep=1.5mm] at (4,-8)   {4\\ jump};
\node (5) [state] at (-6,0)    {                    5   \\ 
                                \nodepart{two}      17  \\
                                \nodepart{three}    18  
                                };
\node (15) [fitnode,fit=(5)];
%
\draw   (0.west)  edge (11) 
        (0.east)  edge (13) 
        (1.east)  edge (13) 
        (1.south) edge (12) 
        (2) edge (4) 
        (2.three west) edge [out=180,in=270] (11.south)
        (3.south) edge (12)
        (3.east)  edge [out=0,in=0] (4)
        (5.south) edge (11)
        (5.east)   --  (13);
    \end{tikzpicture}
\end{document}

Addendum: considering Guilherme Zanotelli comments and some further improvements of existing code, where is exploited positioning TikZ library for relative positioning of nodes controlled by node distance and redefined state style. For simplified relative positioning of nodes they are renamed. With this measures code become far more concise:

\documentclass[tikz, margin=5mm]{standalone}
\usetikzlibrary{arrows,
                automata, 
                calc, 
                fit,                % <-- added
                positioning,        % <-- added
                shapes.multipart,   % <-- added
                }

\begin{document}
    \begin{tikzpicture}[semithick,
     node distance = 24mm and 12mm, 
 state/.style args = {#1 #2 #3}%
        {shape=rectangle split, draw,
         rectangle split parts=3,
         rectangle split part fill={gray!30,white},
         minimum width=17mm,
         node contents={\nodepart{one}  #1  % <-- added                 
                        \nodepart{two}  #2        
                        \nodepart{three}#3},
         append after command=\pgfextra{   % <-- added
            \node (1\tikzlastnode) [fitnode, fit=(\tikzlastnode)];}%%
         },
   jump/.style = % <-- added
        {shape=circle,draw, fill=gray!50,
         double=gray!50,double distance=2mm,
         align=center,
         inner sep=3mm, outer sep=1.5mm
         },        
fitnode/.style = 
        {shape=circle, draw, 
         inner sep=1pt,outer sep=0pt,
         node contents={}}                    
                        ]
\node (1)  [state=5 17 18];
\node (2)  [state=1 11 12,below right=of 1];
\node (3)  [state=5 13 14,above right=of 2];
\node (4)  [state=3 15 16,below right=of 3];
\node (5)  [state=2 17 18,below right=of 2];
\node (6)  [jump,right=of 5] {4\\ jump};
%
\draw[-stealth]
    (1.south)  edge (12)
    (1.east)   edge (14)
    (2.east)   edge (14)
    (2.south)  edge (15)
    (3.west)   edge (12)
    (3.east)   edge (14)
    (4.south)  edge (15)
    (4.east)   edge [out=0,in=0] (6)
    (5.east)   edge (6)
    (5.west)    to  [out=180,in=270] (12);
    \end{tikzpicture}
\end{document}

enter image description here

| improve this answer | |
  • If you use append after command={\pgfextra{\node (1\tikzlastnode) [fitnode, fit=(\tikzlastnode)];}} inside the state style there will be no need for all the \node (yx) [fitnode, fit=(x)]; – Guilherme Zanotelli Jan 19 '17 at 16:33
  • @GuilhermeZanotelli, thank you for the tip. However, using this the it is not possible to manage connection between "tables" (multi part nodes) and circles around them. This is one of OP demands, as far I understand question. – Zarko Jan 19 '17 at 17:54
  • Of course it is! with \pgfextra{\node (1\tikzlastnode) [fitnode, fit=(\tikzlastnode)];} we are creating a new node which received the name of the previously delcared node plus a 1, exactly as you do manually. If you do as I say and remove all the \node (1x) [fitnode, fit=(x)]; your code still compiles perfectly! :) – Guilherme Zanotelli Jan 19 '17 at 17:57
  • @GuilhermeZanotelli, with your help I significantly improve answer! Thank you very much! – Zarko Jan 19 '17 at 19:01
  • Indeed, much more TikZxy! And better than using \matrix, the code is now neat! :D – Guilherme Zanotelli Jan 19 '17 at 19:06
4

I agree with Jan, the drawing you made Looks much better. But that's for you to judge, we're here to help only. :)

So, this seems like a matrix thing. A \matrix in tikz is a big node that contains other nodes inside, the beauty of it is the automatic naming. Say you name a matrix A by using: \matrix (A) {...}; all nodes inside the matrix A will have names like A-<row>-<column>. And since the matrix itself is a node, you can use anchor, above, inner sep and so on.

Finally, the nodes iside the \matrix are defined like if they were a table, so your syntax needs little modification, only removing the \begin \end{tabular} and the \hlines would suffice. Let's get to the MWE!

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,automata}
\begin{document}
\begin{tikzpicture}[->,>=stealth,
    node distance=4cm,semithick,
    every state/.style={
        draw=black,
        text=black,
        minimum size=2cm},
    row 1/.style={fill=gray!50},
    state matrix/.style={
        state,
        matrix of nodes,
        row sep=0pt,
        column sep=0pt,
        nodes={draw, rectangle, minimum height=0pt, minimum width=3em}}]
  \matrix[state matrix] (0) at (0,0)  {
                     |[row 1]| 5\\
                     13\\
                     14\\};
  \matrix[state matrix] (1) at (-4,-4) {
                     |[row 1]| 1   \\
                     11  \\
                     12  \\};

  \matrix[state matrix] (2) at (-2,-8){
                     |[row 1]| 2   \\
                     17  \\
                     18  \\};

  \matrix[state matrix] (3) at (4,-4) {
                     |[row 1]| 3   \\
                     15  \\
                     16  \\};
  \node[state,fill=gray!50,double=gray!50, double distance=5pt] (4)  at (6,-8) {4 jump };
  \matrix[state matrix] (5) at (-6,0) {
                     |[row 1]| 5   \\
                     17  \\
                     18  \\
                   };
\foreach \i in {0,...,5} \node[above] at (\i.north) {\i};
\draw[->]%
    (5-2-1.east) edge (3)
    (5-3-1.south) edge (1)
    (0-2-1.west) edge (1)
    (0-2-1.east) edge (3)
    (1-2-1.east) edge (3)
    (1-3-1.east) edge (2)
    ;
\end{tikzpicture}
\end{document}

The matrix library makes available the matrix of nodes style, which reduces the amount of \node necessary (check the manual for further info), with that style all nodes inside the Matrix receive the style provided by nodes={sty keys}, so I gave them all a minimum width=3em but you can adjust that value. Furthermore I used double in the 4 jump node instead of drawing it twice with different sizes. I drew some of the edges but left the rest to you as I now am out of time! Also there's a \foreach naming the state matrices just for a reference to draw the edges, just remove it once you're done.

For the lines jumping one another check Intersection of 2 lines not really connected in TikZ Mark Wibrow has a pretty neat answer there and I made a slight modification of it (which is also answered there).

enter image description here

| improve this answer | |
  • @user123348, you're welcome! And, I forgot to add this: \tikzstyle is deprecated, it's not even in the manual anymore. To define a style one should use the handler: mystyle/.style={keys} which work inside pretty much anywhere a style can be applied. – Guilherme Zanotelli Jan 19 '17 at 14:57

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.