如何自动绘制平行线?

如何自动绘制平行线?

梅威瑟:

\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);
    \draw
      [->] (block 1) -- (block 2);
    \draw
      [->] (block 2) -- (output);

  \end{tikzpicture}

\end{document}

给出:

result

我希望(线条和箭头不应该加粗):

wish

是否可以或多或少地自动完成此操作,而无需手动绘制三条线。甚至三条线的位置也应自动设置。这意味着:中线应位于垂直中间。上下线应对称地位于中线的上方和下方。

提前感谢您的帮助和努力!

答案1

你可以利用\foreach循环

\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

我根据\k-1、、0以及最终1)的值将箭头的位置上下移动一定量。

答案2

像这样吗?

\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

附录:只是为了好玩:一个稍微更灵活的版本。

\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

答案3

厚颜无耻地引用我自己的答案这里(针对此情况略作调整)。

我定义了一个新形状block,它有三个选项可以赋予样式block={inputs=<inputs>,outputs=<outputs>,io spacing=<length>}

  • inputs任意整数输入,默认为 1
  • outputs任意整数输出数,默认为 1
  • io spacing输入和输出之间的间距,默认为 5mm

利用这种形状/样式我们可以绘制:

enter image description here

仅使用(也使用positioning库,参见底部的 MWE):

\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}

对于您的问题来说,这可能有点小题大做,但是谁知道呢,您可能还有一些额外的需求可以通过这个来满足:)

完整的形状定义是:

\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-past能够):

\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}

相关内容