How to draw automatically parallel lines?

Something like this?

\documentclass{scrartcl}
\usepackage{tikz}

\tikzset{
         signal/.style = coordinate,
         block/.style = {
                         draw,
                         rectangle,
                         minimum height = 2em,
                         minimum width = 4em
                        }
        }
\usetikzlibrary{decorations.markings,positioning}
\tikzset{triple line with arrows/.style args={#1,#2,#3}{decorate,decoration={markings,%
mark=at position 0 with {\coordinate (ta-base-1) at (0,4pt);
\coordinate (ta-base-2) at (0,0pt);
\coordinate (ta-base-3) at (0,-4pt);},
mark=at position 1 with {\draw[#1] (ta-base-1) -- (0,4pt);
\draw[#2] (ta-base-2) -- (0,0pt);
\draw[#3] (ta-base-3) -- (0,-4pt);}}}}

\begin{document}

  \begin{tikzpicture}

    \node[signal] (input) {};
    \node[
          block,
          right = of input
         ] (block 1) {};
    \node[
          block,
          right = of block 1
         ] (block 2) {};
    \node[
          signal,
          right = of block 2
         ] (output) {};
    \draw
      [->] (input) -- (block 1);
    \draw
      [triple line with arrows={->,->,->}] (block 1) -- (block 2);
    \draw
      [triple line with arrows={->,->,->}] (block 2) -- (output);

  \end{tikzpicture}

\end{document}

enter image description here

ADDENDUM: Just for fun: a slightly more flexible version.

\documentclass{scrartcl}
\usepackage{tikz}

\tikzset{
         signal/.style = coordinate,
         block/.style = {
                         draw,
                         rectangle,
                         minimum height = 2em,
                         minimum width = 4em
                        }
        }
\usetikzlibrary{decorations.markings,positioning}
\pgfkeys{tikz/.cd,
         triple line distance/.store in =\triplelinedist,
         triple line distance=4pt
}
\tikzset{triple line with arrows/.style args={#1,#2,#3}{decorate,decoration={markings,%
mark=at position 0 with {\coordinate (ta-base-1) at (0,\triplelinedist);
\coordinate (ta-base-2) at (0,0pt);
\coordinate (ta-base-3) at (0,-\triplelinedist);},
mark=at position 1 with {\draw[#1] (ta-base-1) -- (0,\triplelinedist);
\draw[#2] (ta-base-2) -- (0,0pt);
\draw[#3] (ta-base-3) -- (0,-\triplelinedist);}}}}

\begin{document}

  \begin{tikzpicture}

    \node[signal] (input) {};
    \node[
          block,
          right = of input
         ] (block 1) {};
    \node[
          block,
          right = of block 1
         ] (block 2) {};
    \node[
          signal,
          right = of block 2
         ] (output) {};
    \draw
      [->] (input) -- (block 1);
    \draw
      [triple line with arrows={->,->,->}] (block 1) -- (block 2);
    \draw
      [triple line with arrows={->,->,->},triple line distance=5pt] (block 2) -- (output);

  \end{tikzpicture}

\end{document}

enter image description here


You can make use of the \foreach loop

\documentclass{scrartcl}
\usepackage{tikz}

\tikzset{
         signal/.style = coordinate,
         block/.style = {
                         draw,
                         rectangle,
                         minimum height = 2em,
                         minimum width = 4em
                        }
         }
\usetikzlibrary{positioning}

\begin{document}

  \begin{tikzpicture}

  \node[signal] (input) {};
  \node[
        block,
        right = of input
       ] (block 1) {};
  \node[
        block,
        right = of block 1
       ] (block 2) {};
  \node[
        signal,
        right = of block 2
       ] (output) {};
  \draw
    [->] (input) -- (block 1);
  \foreach \k in {-1,0,1}{
    \draw [->] ([yshift=\k*.2cm]block 1.east) -- ([yshift=\k*.2cm]block 2.west);
    \draw [->] ([yshift=\k*.2cm]block 2.east) -- ([yshift=\k*.2cm]output.west);
  }
  \end{tikzpicture}

\end{document}

result

I am shifting the positions of the arrows up and down by a certain amount depending on the value of \k (-1, 0, and finally 1).


Shamelessly quoting my own answer here (slightly adjusted for this case).

I defined a new shape block which has three options that can be given to the style as block={inputs=<inputs>,outputs=<outputs>,io spacing=<length>}:

  • inputs Arbitrary integer number of inputs, defaults to 1
  • outputs Arbitrary integer number of outputs, defaults to 1
  • io spacing Spacing between in- and outputs, defaults to 5mm

With this shape/style we can draw:

enter image description here

With only (also uses the positioning library, see the MWE at the bottom):

\begin{tikzpicture}
    \node[block={outputs=3}](node1){};
    \node[block={inputs=3,outputs=3},right=of node1](node2){};

    \draw[<-] (node1.input 1) -- ++(-1,0);

    \foreach \i in {1,...,3}{
        \draw[->] (node1.output \i) -- (node2.input \i);
        \draw[->] (node2.output \i) --++(1,0);
    }
\end{tikzpicture}

This might be a little overkill for your problem, but who knows, you might have some additional demands that can be met with this :)

The complete shape definition is:

\makeatletter
\newdimen\block@iospacing
\newdimen\block@height

\newif\if@block@flip

\tikzset{
    block/.code={
        \pgfkeys{
            /block/.cd,
            #1
        }
        \pgfmathsetlengthmacro{\block@height}{%
            max(10mm, int(max(\block@inputs,\block@outputs) * \block@iospacing))}
        \tikzset{
            draw,
            align=center,
            minimum width = 15mm,
            minimum height = \block@height,
            shape=block
        }
    }
}
\pgfkeys{
    /block/.is family,
    /block/.cd,
    inputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@inputs=\pgfmathresult
    },
    inputs=1,
    outputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@outputs=\pgfmathresult
    },
    outputs=1,
    io spacing/.code=\setlength\block@iospacing{#1},
    io spacing=5mm,
    flip/.is choice,
    flip/true/.code={\@block@fliptrue\def\@block@flipbool{1}},
    flip/false/.code={\@block@flipfalse\def\@block@flipbool{0}},
    flip/.default=true,
    flip=false,
}

\pgfdeclareshape{block}{
    \inheritsavedanchors[from={rectangle}]
    \savedanchor\centerpoint{%
        \pgf@x=.5\wd\pgfnodeparttextbox%
        \pgf@y=.5\ht\pgfnodeparttextbox%
        \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
    }
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north west}
    \inheritanchor[from=rectangle]{north east}
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{text}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{mid}
    \inheritanchor[from=rectangle]{mid west}
    \inheritanchor[from=rectangle]{mid east}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{base west}
    \inheritanchor[from=rectangle]{base east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south west}
    \inheritanchor[from=rectangle]{south east}
    \savedmacro\blockinputs{%
        \pgfmathparse{int(\block@inputs)}%
        \let\blockinputs=\pgfmathresult}%
    \savedmacro\blockoutputs{%
        \pgfmathparse{int(\block@outputs)}%
        \let\blockoutputs=\pgfmathresult}%
    \savedmacro\blockmaxio{%
        \pgfmathparse{int(max(\block@inputs,\block@outputs))}%
        \let\blockmaxio=\pgfmathresult}%
    \savedmacro\blockflip{%
        \pgfmathparse{\@block@flipbool}%
        \let\blockflip=\pgfmathresult}%
    \saveddimen\halfwidth{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum width}/2}\pgfmathresult}
    \saveddimen\halfheight{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum height}/2}\pgfmathresult}
    \saveddimen\iospacing{\pgfmathsetlength\pgf@x{%
            \block@iospacing}\pgfmathresult}
    \inheritbackgroundpath[from={rectangle}]
    \pgfutil@g@addto@macro\pgf@sh@s@block{%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockinputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@input \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@input %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@in@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockoutputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@output \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@output %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@out@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
    }%
}

\def\pgf@sh@lib@block@in@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\southwest}%
    \else%
        \pgf@process{\northeast}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockinputs+1)-#1)*\iospacing}
}
\def\pgf@sh@lib@block@out@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\northeast}%
    \else%
        \pgf@process{\southwest}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockoutputs+1)-#1)*\iospacing}
}
\makeatother

MWE (copy-pastable):

\documentclass[tikz,margin=2mm]{standalone}

\usetikzlibrary{positioning}

\makeatletter
\newdimen\block@iospacing
\newdimen\block@height

\newif\if@block@flip

\tikzset{
    block/.code={
        \pgfkeys{
            /block/.cd,
            #1
        }
        \pgfmathsetlengthmacro{\block@height}{%
            max(10mm, int(max(\block@inputs,\block@outputs) * \block@iospacing))}
        \tikzset{
            draw,
            align=center,
            minimum width = 15mm,
            minimum height = \block@height,
            shape=block
        }
    }
}
\pgfkeys{
    /block/.is family,
    /block/.cd,
    inputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@inputs=\pgfmathresult
    },
    inputs=1,
    outputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@outputs=\pgfmathresult
    },
    outputs=1,
    io spacing/.code=\setlength\block@iospacing{#1},
    io spacing=5mm,
    flip/.is choice,
    flip/true/.code={\@block@fliptrue\def\@block@flipbool{1}},
    flip/false/.code={\@block@flipfalse\def\@block@flipbool{0}},
    flip/.default=true,
    flip=false,
}

\pgfdeclareshape{block}{
    \inheritsavedanchors[from={rectangle}]
    \savedanchor\centerpoint{%
        \pgf@x=.5\wd\pgfnodeparttextbox%
        \pgf@y=.5\ht\pgfnodeparttextbox%
        \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
    }
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north west}
    \inheritanchor[from=rectangle]{north east}
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{text}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{mid}
    \inheritanchor[from=rectangle]{mid west}
    \inheritanchor[from=rectangle]{mid east}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{base west}
    \inheritanchor[from=rectangle]{base east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south west}
    \inheritanchor[from=rectangle]{south east}
    \savedmacro\blockinputs{%
        \pgfmathparse{int(\block@inputs)}%
        \let\blockinputs=\pgfmathresult}%
    \savedmacro\blockoutputs{%
        \pgfmathparse{int(\block@outputs)}%
        \let\blockoutputs=\pgfmathresult}%
    \savedmacro\blockmaxio{%
        \pgfmathparse{int(max(\block@inputs,\block@outputs))}%
        \let\blockmaxio=\pgfmathresult}%
    \savedmacro\blockflip{%
        \pgfmathparse{\@block@flipbool}%
        \let\blockflip=\pgfmathresult}%
    \saveddimen\halfwidth{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum width}/2}\pgfmathresult}
    \saveddimen\halfheight{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum height}/2}\pgfmathresult}
    \saveddimen\iospacing{\pgfmathsetlength\pgf@x{%
            \block@iospacing}\pgfmathresult}
    \inheritbackgroundpath[from={rectangle}]
    \pgfutil@g@addto@macro\pgf@sh@s@block{%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockinputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@input \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@input %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@in@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockoutputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@output \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@output %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@out@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
    }%
}

\def\pgf@sh@lib@block@in@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\southwest}%
    \else%
        \pgf@process{\northeast}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockinputs+1)-#1)*\iospacing}
}
\def\pgf@sh@lib@block@out@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\northeast}%
    \else%
        \pgf@process{\southwest}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockoutputs+1)-#1)*\iospacing}
}
\makeatother

\begin{document}
    \begin{tikzpicture}
        \node[block={outputs=3}](node1){};
        \node[block={inputs=3,outputs=3},right=of node1](node2){};

        \draw[<-] (node1.input 1) -- ++(-1,0);

        \foreach \i in {1,...,3}{
            \draw[->] (node1.output \i) -- (node2.input \i);
            \draw[->] (node2.output \i) --++(1,0);
        }
    \end{tikzpicture}
\end{document}