4

I want to create flow diagrams that contain forks and joins with tikz. The chains library seems well suited for the case, but I find it difficult to adjust the edges when I fork/join several chains.

Here is a MWE:

\documentclass{minimal}
\newcommand{\jobdescr}[2]{\textsf{\textit{#1}} \vspace{4mm} \\ \textsf{\textbf{#2}}}
\newcommand{\tikzjob}[4]{\node[job, join, on chain=#1] (#2) {\jobdescr{#3}{#4}}}

\usepackage{tikz}
\usetikzlibrary{calc,trees,positioning,arrows,chains,shapes.geometric,%
    decorations.pathreplacing,decorations.pathmorphing,shapes,%
    matrix,shapes.symbols}

\tikzset{
>=stealth',
  job/.style={
    rectangle,
    rounded corners,
    % fill=black!10,
    draw=black, very thick,
    text width=14em,
    minimum height=3em,
    text centered,
    on chain},
  line/.style={draw, thick, <-},
  element/.style={
    tape,
    top color=white,
    bottom color=blue!50!black!60!,
    minimum width=8em,
    draw=blue!40!black!90, very thick,
    text width=10em,
    minimum height=3.5em,
    text centered,
    on chain},
  every join/.style={->, thick,shorten >=1pt},
  decoration={brace},
  tuborg/.style={decorate},
  tubnode/.style={midway, right=2pt},
}
\begin{document}
\begin{tikzpicture}
  [node distance=.8cm,
  start chain=main going below,]
     \tikzjob{main}  {input}    {Input}  {Read Input};

     \node at (input.south west) (leftstart)  {};
     \node at (input.south east) (rightstart) {};

     \begin{scope}[start chain=left going below]
        \chainin (leftstart);
        \tikzjob{left}  {mapleft}  {Map} {Job 1};
     \end{scope}

     \begin{scope}[start chain=right going below]
       \chainin (rightstart);
       \tikzjob{right}  {mapright} {Map} {Job 2};
     \end{scope}

     \node (join) at (mapright.south -| input) {};

     \begin{scope}[start chain=end going below]
       \chainin (join);
       \tikzjob{end}    {join}      {Reduce}  {Join Results};
       \tikzjob{end}    {output}    {Output}  {Print Result};
     \end{scope}
   \end{tikzpicture}
\end{document}

As you can see, a fork/join involves four chains: The original chain, the left and the right children, and the continuation. With invisible nodes and \chainin it is straightforward to obtain a good looking spacing. But the edges are naturally drawn between the invisible nodes and not the actual nodes. I'd rather want to draw the edges as annotated in the image below.

Is there an easy way to fix this?

Example

ps.: Ideally I would like to keep the \tikzjob macro, as it nicely separates presentation from structure.

6

like this:

enter image description here

above image is drawn with very elementary, simple and clear tikz code (i must confess that i wen to lost in your sophisticated code):

\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{arrows.meta,
                positioning
                }

\begin{document}
\begin{tikzpicture}[
  node distance = 8mm and 1mm,
job/.style args = {#1/#2}{
    rectangle, rounded corners, draw=black, very thick,
    minimum height=3em, text width=14em, align=center,
    label={[font=\sffamily,anchor=north]above:\textit{#1}},
    label={[font=\sffamily,anchor=south]below:\textbf{#2}},
    node contents ={}},
    arr/.style = {semithick, -Stealth}
                    ]
\node (n1)  [job=Input/Read Input];
\node (n21) [job=Map/Job 1,below  left=of n1.south];
\node (n22) [job=Map/Job 2,below right=of n1.south];
\node (n3)  [job=Reduce/Join Results,below right=of n21.south];
\node (n4)  [job=Output/Print results,below=of n3];
%
\coordinate[below=4mm of n1.south] (aux1);
\coordinate[above=4mm of n3.north] (aux2);
%
\draw[arr]  (n1) -- (aux1) -| (n21);
\draw[arr]  (aux1) -| (n22);
\draw[arr]  (n21) |- (aux2)
            (n22) |- (aux2) -- (n3);
\draw[arr]  (n3)  -- (n4);
   \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.