4

I'm trying to create a nested chart in tikz. I have a nonnested chart completed, but I'm trying to nest the blue boxes inside the first yellow box. I'm trying to follow the advice given here, so I created a tikz picture inside of the tikz picture. MWE below. enter image description here However, that throws off all of my node spacing (the paths inside the nested picture don't line up anymore, for some reason), and also makes the decisiong box have rounded corners...which is minor but perhaps related? Additionally, I have math formulas off to the side, which depend on the nodes in the blue boxes. I think it looks like they'll still compile with the nested tikz pictures, but the top two math formulas are now overlapping.

So, I have a few questions. Is this the best way to nest a flow chart? Can I have `outside nodes' that refer to nodes defined in a nested tikz picture? How do I fix the spacing on the node paths?

EDIT: It has been pointed out that nesting tikz pictures is not a good practice. Multiple solutions below modify tikz elements such that the figure appears nested, without actually nesting the tikzpicture enviroments.

MWE with both charts:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows, positioning}
\begin{document}

% Define block styles
\tikzstyle{decision} = [diamond, draw, fill=yellow!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{decisiong} = [diamond, draw, fill=blue!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{block} = [rectangle, node distance=1.75cm, minimum width=1cm, minimum height=0.5cm, draw, fill=yellow!20, 
    text width=20em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{blockg} = [rectangle, minimum width=1cm, minimum height=0.5cm, draw, fill=blue!20, 
    text width=15em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{line} = [draw, -latex']
\tikzstyle{cloud} = [draw, ellipse,fill=yellow!20, node distance=1.5cm, 
    minimum height=2em]
\tikzstyle{invis} = [draw, fill=yellow!10, node distance=4.25cm, 
    minimum height=2em]
\tikzstyle{invisg} = [draw, fill=yellow!10, node distance=3.5cm, 
    minimum height=2em]
\tikzstyle{matheq} = [node distance=8.75cm, text width=21em, minimum width=1cm, 
    minimum height=2em, text centered]


\begin{tikzpicture}[node distance = 1.25cm, auto]
    % Place nodes
    \node [cloud] (init) {update time};
    \node [matheq, right of=init] {$math$};

    \node [block, below of=init] (second) {iterate through all elements};
    \node [blockg, below of=second] (third) {local update};
    \node [matheq, right of=third] {$math$};
    \node [blockg, below of=third] (fourth) {calculate,\\ update };
    \node [matheq, right of=fourth] {$math$};
    \node [blockg, below of=fourth] (fifth) {calculate stuff};   
    \node [matheq, right of=fifth] {$math$};
    \node [decisiong, below of=fifth] (conver1) {{\scriptsize converged?}};
    % Draw edges
    \path [line] (init) -- (second);
    \path [line] (second) -- (third);
    \path [line] (third) -- (fourth);
    \path [line] (fourth) -- (fifth);
    \path [line] (fifth) -- (conver1); 
    \coordinate[left of=third] (c1);  %This is so the path doesn't intersect the diagram
    \coordinate[left of=conver1] (d1);
    \path [line] (conver1) -| node [near start] {no} ([xshift=-2.5cm]d1) -- ([xshift=-2.5cm]c1)-- (third);

    \node [block, below of=conver1] (solve) {solve global equations};
    \node [matheq, right of=solve] {$math$
    \\ $math$ \\ $math$}; 
    \node [decision, below of=solve] (conver) {{\scriptsize converged?}};
    \coordinate[right of=init] (a1);  %This is so the path doesn't intersect the diagram
    \coordinate[left of=conver] (b1);  
    \coordinate[right of=conver] (e1);
    \coordinate[left of=second] (f1);
    % Draw edges
    \path [line] (conver1) --node {yes} (solve);
    \path [line] (solve) -- (conver);
    \path [line] (conver) -| node [near start] {no} ([xshift=-3.25cm]b1) -- ([xshift=-3.25cm]f1)-- (second);


    \path [line] (conver) -| node [near start] {yes} ([xshift=3.25cm]e1) -- ([xshift=3.25cm]a1)-- (init);
\end{tikzpicture}


\clearpage
This should be the same chart, but the blue boxes should be nested inside the first yellow box.

\begin{tikzpicture}[node distance = 1.25cm, auto]
    % Place nodes
    \node [cloud] (init) {update time};
    \node [matheq, right of=init] {$math$};

    \node [block, below of=init] (second) {iterate through all elements
        \begin{tikzpicture}[node distance = 1.25cm, auto]
        \node [blockg] (third) {local update};
        \node [blockg, below of=third] (fourth) {calculate,\\ update};
        \node [blockg, below of=fourth] (fifth) {calculate stuff};   
        \node [decisiong, below of=fifth] (conver1) {{\scriptsize converged?}};
        \path [line] (third) -- (fourth);
        \path [line] (fourth) -- (fifth);
        \path [line] (fifth) -- (conver1);
        \end{tikzpicture}
        };
    %Math equations
    \node [matheq, right of=third] {$math$};
    \node [matheq, right of=fourth] {$math$};
    \node [matheq, right of=fifth] {$math$};
    % Draw edges
    \path [line] (init) -- (second);
    %\path [line] (second) -- (third);

    \coordinate[left of=third] (c1);
    \coordinate[left of=conver1] (d1);
    \path [line] (conver1) -| node [near start] {no} ([xshift=-2.5cm]d1) -- ([xshift=-2.5cm]c1)-- (third);

    \node [block, below of=conver1] (solve) {solve global equations};
    \node [matheq, right of=solve] {$math$
    \\ $math$ \\ $math$}; 
    \node [decision, below of=solve] (conver) {{\scriptsize converged?}};
    \coordinate[right of=init] (a1);
    \coordinate[left of=conver] (b1);  
    \coordinate[right of=conver] (e1);
    \coordinate[left of=second] (f1);
    % Draw edges
    \path [line] (conver1) --node {yes} (solve);
    \path [line] (solve) -- (conver);
    \path [line] (conver) -| node [near start] {no} ([xshift=-3.25cm]b1) -- ([xshift=-3.25cm]f1)-- (second);


    \path [line] (conver) -| node [near start] {yes} ([xshift=3.25cm]e1) -- ([xshift=3.25cm]a1)-- (init);
\end{tikzpicture}

\end{document}
  • 1
    Nesting tikzpictures is not, I think, considered a good practice. See e.g. tex.stackexchange.com/a/46792/586 A couple of other comments: 1) You're not actually using the syntax of the positioning library, it should be below=of, not below of=, see Difference between "right of=" and "right=of" in PGF/TikZ 2) I think it's common to recommend \tikzset{stylename/.style={...}} instead of \tikzstyle{stylename}=[...], see e.g. Is there something like \providetikzstyle similar to \providecommand? – Torbjørn T. Jul 7 '15 at 15:47
  • @TorbjørnT. Thank you for pointing out that nesting tikzpictures is not a good practice. I edited the question to note this. This was my first experience with a chart in tikz, and I was following an example from texample.net/tikz/examples/simple-flow-chart that used the positioning and style commands I employed in the MWE. I think that perhaps these were older commands. The formulation of \tikzset{stylename/.style={...}} reminds me of object oriented programming. Are there other .* attributes (if that's the word) that are associated with styles? Thank you for your input. – user2441511 Jul 7 '15 at 21:30
  • 1
    See for example section 82.4.4 Defining Styles in the TikZ manual. – Torbjørn T. Jul 7 '15 at 21:45
5

Following you'll find an example with a background fitting node instead of a nesting tikzpicture. Is this what you want?

enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows, positioning, fit, backgrounds}
\begin{document}

% Define block styles
\tikzstyle{decision} = [diamond, draw, fill=yellow!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{decisiong} = [diamond, draw, fill=blue!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{block} = [rectangle, node distance=1.75cm, minimum width=1cm, minimum height=0.5cm, draw, fill=yellow!20, 
    text width=20em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{blockg} = [rectangle, minimum width=1cm, minimum height=0.5cm, draw, fill=blue!20, 
    text width=15em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{line} = [draw, -latex']
\tikzstyle{cloud} = [draw, ellipse,fill=yellow!20, node distance=1.5cm, 
    minimum height=2em]
\tikzstyle{invis} = [draw, fill=yellow!10, node distance=4.25cm, 
    minimum height=2em]
\tikzstyle{invisg} = [draw, fill=yellow!10, node distance=3.5cm, 
    minimum height=2em]
\tikzstyle{matheq} = [node distance=8.75cm, text width=21em, minimum width=1cm, 
    minimum height=2em, text centered]


\begin{tikzpicture}[node distance = 1.25cm, auto]
    % Place nodes
    \node [cloud] (init) {update time};
    \node [matheq, right of=init] {$math$};

    \node [block, below of=init] (second) {iterate through all elements};
    \node [blockg, below of=second] (third) {local update};
    \node [matheq, right of=third] {$math$};
    \node [blockg, below of=third] (fourth) {calculate,\\ update };
    \node [matheq, right of=fourth] {$math$};
    \node [blockg, below of=fourth] (fifth) {calculate stuff};   
    \node [matheq, right of=fifth] {$math$};
    \node [decisiong, below of=fifth] (conver1) {{\scriptsize converged?}};

    \begin{scope}[on background layer]
    \node[draw, fill=yellow, fit=(second) (conver1), inner xsep=5mm]{};
    \end{scope}
    % Draw edges
    \path [line] (init) -- (second);
    \path [line] (second) -- (third);
    \path [line] (third) -- (fourth);
    \path [line] (fourth) -- (fifth);
    \path [line] (fifth) -- (conver1); 
    \coordinate[left of=third] (c1);  %This is so the path doesn't intersect the diagram
    \coordinate[left of=conver1] (d1);
    \path [line] (conver1) -| node [near start] {no} ([xshift=-2.5cm]d1) -- ([xshift=-2.5cm]c1)-- (third);

    \node [block, below of=conver1] (solve) {solve global equations};
    \node [matheq, right of=solve] {$math$
    \\ $math$ \\ $math$}; 
    \node [decision, below of=solve] (conver) {{\scriptsize converged?}};
    \coordinate[right of=init] (a1);  %This is so the path doesn't intersect the diagram
    \coordinate[left of=conver] (b1);  
    \coordinate[right of=conver] (e1);
    \coordinate[left of=second] (f1);
    % Draw edges
    \path [line] (conver1) --node {yes} (solve);
    \path [line] (solve) -- (conver);
    \path [line] (conver) -| node [near start] {no} ([xshift=-3.25cm]b1) -- ([xshift=-3.25cm]f1)-- (second);


    \path [line] (conver) -| node [near start] {yes} ([xshift=3.25cm]e1) -- ([xshift=3.25cm]a1)-- (init);
\end{tikzpicture}

\end{document}
  • That's a nice workaround. I modified it a bit to make it appear more like my diagram, with rounded corners \begin{scope}[on background layer] \node[draw, fill=yellow!20, rounded corners, fit=(second) (conver1), inner xsep=5mm]{}; \end{scope} I also want to note for future readers that this requires additional packages \usetikzlibrary{fit,backgrounds}...it took me a minute to find that. Thanks! – user2441511 Jul 7 '15 at 15:06
3

As I found my own workaround, I also wanted to post that here. It creates a fake node and shifts it, but it preserves the look of the diagram:

enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows, positioning,fit,backgrounds}
\begin{document}

\tikzstyle{decision} = [diamond, draw, fill=yellow!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{decisiong} = [diamond, draw, fill=blue!40, 
    text width=4.5em, text badly centered, node distance=1.75cm, inner sep=0pt]
\tikzstyle{block} = [rectangle, node distance=1.75cm, minimum width=1cm, minimum height=0.5cm, draw, fill=yellow!20, 
    text width=20em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{blockjusttext} = [rectangle, node distance=1.75cm, minimum width=1cm, minimum height=0.5cm,
    text width=20em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{blockfill} = [rectangle, node distance=1.75cm, minimum width=1cm, minimum height=14cm, draw, fill=yellow!20, 
    text width=20em, text centered, rounded corners, minimum height=16.8em]
\tikzstyle{blockg} = [rectangle, minimum width=1cm, minimum height=0.5cm, draw, fill=blue!20, 
    text width=15em, text centered, rounded corners, minimum height=1.5em]
\tikzstyle{line} = [draw, -latex']
\tikzstyle{cloud} = [draw, ellipse,fill=yellow!20, node distance=1.5cm, 
    minimum height=2em]
\tikzstyle{invis} = [draw, fill=yellow!10, node distance=4.25cm, 
    minimum height=2em]
\tikzstyle{invisg} = [draw, fill=yellow!10, node distance=3.5cm, 
    minimum height=2em]
\tikzstyle{matheq} = [node distance=8.75cm, text width=21em, minimum width=1cm, 
    minimum height=2em, text centered]

\begin{tikzpicture}[node distance = 1.25cm, auto]
    % Place nodes
    \node [cloud] (init) {update time};
    \node [matheq, right of=init] {$math$};


    \node [blockfill, below=0.5cm of init] (second2) {};
    \node [blockjusttext, below=0.5cm of init] (second) {iterate through all elements};
    \node [blockg, below =-0.1cm of second] (third) {local update };
    \node [matheq, right of=third] {$math$};
    \node [blockg, below of=third] (fourth) {calculate,\\ update};
    \node [matheq, right of=fourth] {$math$};
    \node [blockg, below of=fourth] (fifth) {calculate stuff};   
    \node [matheq, right of=fifth] {$math$};
    \node [decisiong, below of=fifth] (conver1) {{\scriptsize converged?}};
    % Draw edges
    \path [line] (init) -- (second);
    \path [line] (third) -- (fourth);
    \path [line] (fourth) -- (fifth); 
    \path [line] (fifth) -- (conver1); 
    \coordinate[left of=third] (c1);
    \coordinate[left of=conver1] (d1);
    \path [line] (conver1) -| node [near start] {no} ([xshift=-2.1cm]d1) -- ([xshift=-2.1cm]c1)-- (third);


    \node [block, below of=conver1] (solve) {solve global equations};
    \node [matheq, right of=solve] {$math$
    \\ $math$ \\ $math$}; 
    \node [decision, below of=solve] (conver) {{\scriptsize converged?}};
    \coordinate[right of=init] (a1);
    \coordinate[left of=conver] (b1);  
    \coordinate[right of=conver] (e1);
    \coordinate[left of=second] (f1);
    % Draw edges
    \path [line] (conver1) --node {yes} (solve);
    \path [line] (solve) -- (conver);
    \path [line] (conver) -| node [near start] {no} ([xshift=-3.25cm]b1) -- ([xshift=-3.25cm]f1)-- (second);


    \path [line] (conver) -| node [near start] {yes} ([xshift=3.25cm]e1) -- ([xshift=3.25cm]a1)-- (init);
\end{tikzpicture}

\end{document}

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.