2

In tikz, flowcharts are commonly built like this:

\documentclass{article}

\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\begin{document}
\pagestyle{empty}


% Define block styles
\tikzstyle{decision} = [diamond, draw, fill=blue!20, 
    text width=4.5em, text badly centered, node distance=3cm, inner sep=0pt]
\tikzstyle{block} = [rectangle, draw, fill=blue!20, 
    text width=5em, text centered, rounded corners, minimum height=4em]
\tikzstyle{line} = [draw, -latex']
\tikzstyle{cloud} = [draw, ellipse,fill=red!20, node distance=3cm,
    minimum height=2em]

\begin{tikzpicture}[node distance = 2cm, auto]
    % Place nodes
    \node [block] (init) {initialize model};
    \node [cloud, left of=init] (expert) {expert};
    \node [cloud, right of=init] (system) {system};
    \node [block, below of=init] (identify) {identify candidate models};
    \node [block, below of=identify] (evaluate) {evaluate candidate models};
    \node [block, left of=evaluate, node distance=3cm] (update) {update model};
    \node [decision, below of=evaluate] (decide) {is best candidate better?};
    \node [block, below of=decide, node distance=3cm] (stop) {stop};
    % Draw edges
    \path [line] (init) -- (identify);
    \path [line] (identify) -- (evaluate);
    \path [line] (evaluate) -- (decide);
    \path [line] (decide) -| node [near start] {yes} (update);
    \path [line] (update) |- (identify);
    \path [line] (decide) -- node {no}(stop);
    \path [line,dashed] (expert) -- (init);
    \path [line,dashed] (system) -- (init);
    \path [line,dashed] (system) |- (evaluate);
\end{tikzpicture}


\end{document}

However, manually specifying the "left of/right of/below of" for each element can be annoying and tiresome when you don't really care where they go. Is there some way to have tikz/latex automatically position the elements in the chart?

Stack Tracer
  • 121
  • 3

1 Answers1

4

I think a tikz matrix is what you're looking for, see Chapter 20 of the TikZ & PGF Manual.

See also (! Package pgf Error: No shape named m-2-2 is known) for other possible solutions and Should \tikzset or \tikzstyle be used to define TikZ styles? which explains why it's better not to use tykzstyle.

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{matrix, shapes,arrows.meta}
\tikzset{
    block/.style={
        rectangle, draw, fill=blue!20, 
        text width=5em, text centered, rounded corners, minimum height=4em
    },
    cloud/.style={
        draw, ellipse,fill=red!20, node distance=3cm,
        minimum height=2em
    },  
    decision/.style={
        diamond, draw, fill=blue!20, 
        text width=4.5em, text badly centered, node distance=3cm, inner sep=0pt
    },
    line/.style = {draw, -Latex},
}
\begin{document}
    \pagestyle{empty}
    \begin{center}
    \begin{tikzpicture}
    \matrix[
        row sep=7ex,
        column sep=3em,
        column 1/.style={nodes={anchor=east}}
        ] {
        \node [cloud] (expert) {expert}; &
        \node [block] (init) {initialize model}; &
        \node [cloud] (system) {system};\\
        & \node [block] (identify) {identify\\ candidate models};\\
        \node [block] (update) {update model}; & 
        \node [block] (evaluate) {evaluate\\ candidate models};\\
        & \node [decision] (decide) {is best candidate better?};\\
        & \node [block] (stop) {stop};  \\
        };
        % Draw edges
        \path [line] (init) -- (identify);
        \path [line] (identify) -- (evaluate);
        \path [line] (evaluate) -- (decide);
        \path [line] (decide) -| node [near start, above] {yes} (update);
        \path [line] (update) |- (identify);
        \path [line] (decide) -- node[right] {no}(stop);
        \path [line,dashed] (expert) -- (init);
        \path [line,dashed] (system) -- (init);
        \path [line,dashed] (system) |- (evaluate);
    \end{tikzpicture}
    \end{center}
\end{document}

enter image description here

When all matrix nodes are of the same style, it's better to use a matrix of nodes which saves some typing. The nodes' style is selected within a matrix option: nodes=... and, by default, all nodes are named after the matrix name and its row and column position. Therefore, something like \node [cloud] (expert) {expert}; can be replaced by expert.

When some node needs a particular style and/or name the syntax used is |[style] (name)| contents. The particular style is applied with .append style to the default one.

And also by default, all nodes from a matrix of nodes have anchor fixed in their base instead of their center.

Will all these considerations in mind, previous code can be written as

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{matrix, shapes,arrows.meta}
\tikzset{
    block/.style={
        rectangle, draw, fill=blue!20, 
        text width=5em, text centered, rounded corners, minimum height=4em
    },
    cloud/.style={
        draw, ellipse,fill=red!20, node distance=3cm,
        minimum height=2em, 
        text width={} %<------- to correct `text width` from `block`
    },  
    decision/.style={
        diamond, draw, fill=blue!20, 
        sharp corners, %<------- to correct `rounded corners` from `block`
        text width=4.5em, text badly centered, 
        node distance=3cm, inner sep=0pt
    },
    line/.style = {draw, -Latex},
}
\begin{document}
    \pagestyle{empty}
    \begin{center}
    \begin{tikzpicture}
    \matrix[
        matrix of nodes,   %<------ new option
        nodes={block, anchor=center},  %<------ default style for nodes 
        row sep=7ex,
        column sep=3em,
        column 1/.style={nodes={anchor=east}}
        ] {
        |[cloud] (expert)| expert &
        |(init)| initialize model &
        |[cloud] (system)| system\\
        & |(identify)| {identify\\ candidate models}\\
        |(update)| update model & 
        |(evaluate)| {evaluate\\ candidate models}\\
        & |[decision] (decide)| is best candidate better?\\
        & |(stop)| stop \\
        };
        % Draw edges
        \path [line] (init) -- (identify);
        \path [line] (identify) -- (evaluate);
        \path [line] (evaluate) -- (decide);
        \path [line] (decide) -| node [near start, above] {yes} (update);
        \path [line] (update) |- (identify);
        \path [line] (decide) -- node[right] {no}(stop);
        \path [line,dashed] (expert) -- (init);
        \path [line,dashed] (system) -- (init);
        \path [line,dashed] (system) |- (evaluate);
    \end{tikzpicture}
    \end{center}
\end{document}
Ignasi
  • 136,588
CarLaTeX
  • 62,716