3

The following flowchart was made in PowerPoint, and it describes the input and output of a function.

function input and output flowchart

As you can see, the diagram is quite intuitive: a set of files are piped into "Function", and it returns a data structure "Struct".

I am trying to draw it using TikZ.

My approach was to draw the first two blocks using nodes and then create the "Struct" shape using a node and a bunch of lines inside a scope environment, so that the node and the lines remain grouped together as a single shape.

I managed to draw and connect the first two blocks. However, I am having trouble to place and connect the "Struct" shape in the diagram. I was expecting that the scope environment would behave like a node, and gave this instruction:

\begin{scope}[right of=function]

But this is what I got:

incomplete flowchart

  • Is it possible to make scope environment behave like a node?
  • If so, how can I accomplish this?
  • Otherwise, what alternatives do I have?

Code:

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{
    shapes.geometric,
    arrows,
    shadows
}
\usepackage{varwidth}
\usepackage{enumitem}
\usepackage{courier}

\renewcommand*\familydefault{\ttdefault}

\begin{document}

\begin{tikzpicture}[node distance=5cm]
  \tikzset{
    files/.style = {
        rectangle,
        fill=white,
        draw=black,
        minimum width=3cm,
        minimum height=1.5cm
        },
    function/.style = {
        rectangle,
        fill=white,
        draw=black,
        minimum width=3cm,
        minimum height=1.5cm,
        text centered
        },
    box/.style = {
            rectangle,
            fill=white,
            draw=black,
            minimum width=2cm,
            minimum height=0.5cm
        },
    arrow/.style={
        ->,
        >=latex,
        },
  }

  % Input
  \node (files) [files, drop shadow] {
            \begin{varwidth}{3cm}
            \begin{itemize}[noitemsep, leftmargin=*]
            \item{file1.dat}
            \item{file2.dat}
            \item{file3.dat}
            \item{file4.dat}
            \end{itemize}
            \end{varwidth}
  };

  % Function
  \node (function) [function, right of=files, drop shadow] {Function};

  % Output
  \begin{scope}[right of=function]
        \draw (0,0) -- (0,1) node[above, box, drop shadow] {Struct};
        \draw (-1.5,-1) -- (-1.5,0) -- (1.5,0) -- (1.5,-1);
        \draw (-0.5,-1) -- (-0.5,0);
        \draw (0.5,-1) -- (0.5,0);
  \end{scope}

  % Arrows
  \draw [arrow] (files) -- (function);
\end{tikzpicture}

\end{document}
1
  • Not really. I mean. It isn't a node. You can use a bounding box trick, if you wish. Or you could use the fit library. Or you could use a pic. It is probably easiest to draw the complicated thing first and then put the simple things to the left, rather than drawing the simple things first and trying to put the complicated thing to the right. You can do the latter, but you're making yourself more work ;).
    – cfr
    Commented Apr 20, 2016 at 0:11

1 Answer 1

2

You can use a local bounding box declaration to name the collective contents of the scope. In order for this to work in this case, the most straightforward strategy is to draw the stuff in the scope first.

For example (updating the code a little along the way e.g. to use arrows.meta and positioning as recommended):

\documentclass[tikz,multi,border=10pt]{standalone}
\usetikzlibrary{arrows.meta,shadows,positioning}
\usepackage{enumitem}
\usepackage{courier}
\renewcommand*\familydefault{\ttdefault}
\begin{document}
\begin{tikzpicture}
  [
    node distance=3cm,
    basic/.style={%
      draw, fill=white
    },
    files/.style = {%
      basic,
      text width=3cm,
      minimum height=1.5cm
    },
    function/.style = {%
      basic,
      text width=3cm,
      minimum height=1.5cm,
      text centered
    },
    box/.style = {%
      basic,
      minimum width=2cm,
      minimum height=0.5cm
    },
    arrow/.style={%
      ->, >=Latex,
    },
  ]
  \begin{scope}[local bounding box=output]
    \draw (0,0) -- (0,1) node[above, box, drop shadow] {Struct};
    \draw (-1.5,-1) -- (-1.5,0) -- (1.5,0) -- (1.5,-1);
    \draw (-0.5,-1) -- (-0.5,0);
    \draw (0.5,-1) -- (0.5,0);
  \end{scope}
  \node (function) [function, left= of output, drop shadow] {Function};
  \node (files) [files, drop shadow, left=of function,] {%
    \vspace*{-.5\baselineskip}%
    \begin{itemize}[nosep,leftmargin=*]
      \item{file1.dat}
      \item{file2.dat}
      \item{file3.dat}
      \item{file4.dat}
    \end{itemize}
  };
  \draw [arrow] (files) -- (function);
\end{tikzpicture}
\end{document}

named scope with other things placed left

Another option is to use a pic however the pic stuff is buggy and the bugs do not show any sign of being fixed soon. While pics still work well in many cases, I think the bugginess would be a particular disadvantage here as it affects both relative positioning and naming. If these bugs are fixed at some happy future date, this would probably be the best option, however, as it would be more flexible than using a named scope.

Finally, the fit library could be used to put a node around nodes and coordinates in the scope. However, this would have no real advantages over the use of local bounding box above and would be a lot more hassle to implement. (You'd need to place coordinates on the lines for the fitted node as it can't use paths, as opposed to nodes and coordinates, when figuring out its intended contents.)

3
  • Thanks a lot for your answer! :) Your strategy has many advantages indeed. There are a couple of things that I am curious about. At the beginning of your post you suggest using arrows.meta and positioning libraries, can you explain why? Also, I noticed that you removed the varwidth environment and added \vspace*{-.5\baselineskip}, why such a change? Commented Apr 20, 2016 at 11:02
  • @Cebri arrows.meta is the new version of arrows and recommended. positioning enables the recommended right=of ... syntax in place of the old right of=... syntax. So those are both best practice things. varwidth just because it didn't seem to be needed and so seemed a potential complication. You can already use text width to set the width, rather than minimum width, so there's a built-in TikZ option for managing this already. The vertical adjustment is just because I couldn't quickly figure out how to adapt the list so forced things.
    – cfr
    Commented Apr 20, 2016 at 17:24
  • I suspect the main advantages are probably flexibility. You can customise arrows.meta arrows quite significantly without delving into their PGF underpinnings, whereas I'm not sure you can with arrows. But I didn't really use arrows much, so this might just be my ignorance.
    – cfr
    Commented Apr 20, 2016 at 19:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .