9.2 Constructing a flowchart

In the previous recipe, Building smart diagrams, we used predefined chart types. In a case when we would need more flexibility, we can do it ourselves from scratch. It’s also not too hard, and it’s a very good way of learning to draw with TikZ.

How to do it…

Similar to what we saw in our description diagram of the first recipe, we will:

  1. Define shapes and colors
  2. Place nodes using a matrix
  3. Insert labeled arrows between selected nodes

Of course, whatever is done in each step may be modified at any time. It’s usual to place nodes and arrows and then start fine-tuning shapes and colors.

So let’s tackle it. Go through the following steps, and also look at the graphical output shown after them to understand the meaning of your drawing tasks:

  1. Start with a document class:

  2. We load the geometry package and specify a vertical margin so that our long chart would fit to the page:

  3. Load the TikZ package:

  4. Load the matrix, calc, and shapes TikZ libraries:

  5. We define styles for the nodes, which is our first major step:
    treenode/.style = {shape=rectangle, rounded corners,
    draw, anchor=center,
    text width=5em, align=center,
    top color=white, bottom color=blue!20,
    inner sep=1ex},
    decision/.style = {treenode, diamond, inner sep=0pt},
    root/.style = {treenode, font=\Large,
    bottom color=red!30},
    env/.style = {treenode, font=\ttfamily\normalsize},
    finish/.style = {root, bottom color=green!40},
    dummy/.style = {circle,draw}

  6. Create some useful shortcuts for edge types:
    \newcommand{\yes}{edge node [above] {yes}}
    \newcommand{\no}{edge node [left] {no}}

  7. Start the document:

  8. Begin the TikZ picture. Add the desired options; here, we just declare –latex as the default arrow tip for edges:

  9. Now comes the second major step—positioning. Start a matrix with the name chart:
      \matrix (chart)

  10. Define the options for the matrix:
    matrix of nodes,
    column sep = 3em,
    row sep = 5ex,
    column 1/.style = {nodes={decision}},
    column 2/.style = {nodes={env}}

  11. Now add the actual matrix contents, which will be the nodes of your flowchart. As with tabular, columns are separated by & and lines end with \\. This is also necessary for the last line. We modify the style of a certain node by inserting |<style>| before the node content. A final semicolon ends the \matrix command with options:
    |[root]| Formula & \\
    single-line? & equation \\
    centered? & gather \\
    aligned at relation sign? & align, flalign \\
    aligned at several places? & alignat \\
    first left, centered,
    last right? & multline \\
    & & |[decision]| numbered? \\
    & & |[treenode]| Add a \texttt{*}
    & |[finish]| Done \\

  12. And now, for the third major step—drawing arrows. Draw the no edges in the first column downwards and the yes edges to the right. We use \foreach loops to reduce the quantity of code. The final edge goes to the final node in the bottom-right corner:
    (chart-1-1) edge (chart-2-1)
    \foreach \x/\y in {2/3, 3/4, 4/5, 5/6} {
    (chart-\x-1) \no (chart-\y-1) }
    \foreach \x in {2,...,6} {
    (chart-\x-1) \yes (chart-\x-2) }
    (chart-7-3) \no (chart-8-3)
    (chart-8-3) edge (chart-8-4);

  13. Draw a line back to the start:
    (chart-6-1) -- +(-2,0) |- (chart-1-1)
    node[near start,sloped,above] {no, reconsider};

  14. Next, draw lines from the nodes in the second column to another node down in the third column:
      \foreach \x in {2,...,6} {
    \draw (chart-\x-2) -| (chart-7-3);}

  15. Draw a yes edge to the final node at the bottom-right corner:
     \draw   (chart-7-3)  -| (chart-8-4)
    node[near start,above] {yes};

  16. End the picture and the document:

  17. Compile, and examine the output:


How it works…

Positioning the nodes is one of the main things here. Providing coordinates for nodes would be too laborious and error-prone. Using relative positioning of nodes would be another option. But the easiest is defining a matrix where we can place nodes as simply as within tabular. This requires a kind of grid structure, however. TikZ provides a matrix library, which has a section of its own in the manual. Refer to it to understand all the options. Here, we defined only the space between rows and columns and some styles for columns.

Styles can be defined locally, for example, as an option in a tikzpicture environment. For repeated use, it is better to define them globally. For this, we used the \tikzset command. It takes a list of style assignments as the argument. As you saw the following principle:

    thingy/.style = {list of style options}

You can redefine existing styles in this way, or create your own styles. Now you can simply use that new style name as an option wherever needed instead of always listing specific options. You get the same benefits here as with macros, such as readability and consistency. You can combine styles and use them to define derived styles. So, we defined a base style for tree nodes, created additional styles that inherited it, and added some code.

Now, back to our code; our matrix structure is as follows:

    \matrix (name) [options] {
entry & entry & ... \\
entry & entry & ... \\

For additional drawing, each node of the matrix got a name now. We can refer to it as (name-row-column), just as we did here:

    \draw (chart-1-1) edge (chart-2-1);

This draws a vertical edge from the top-left node of our chart to the node below it. For column styles, we used the handy nodes={decision} syntax, which simply says that all nodes should have this style. We still can apply local styles, so we used the |[style]| shortcut at the beginning of the matrix cells.

After the matrix, we used \draw to draw all the edges. They are arrows in our case, since we added the –latex option to tikzpicture. We could have chosen -> instead; latex gives just another arrow tip.

To repeat things efficiently, we used \foreach loops. The simplified syntax is as follows:

    \foreach <variables> in {<list>} { <commands> }

Here, the commands can contain variables. These are replaced by list values, iterating through the whole list. The \foreach loop has an entire section in the TikZ manual. For our recipe, that syntax and the samples with one variable and two variables should suffice for a basic understanding.

A special edge is drawn by -|. This means a horizontal line and then a vertical line to the destination. The |- sign is its counterpart, which works the other way round. For details regarding drawing syntax and the available options, refer to the TikZ manual. It also contains tutorials that are really useful for diving into the topic quickly.