6

I really like the double arrows style "a la chef". I want to use them for a block diagram, but I realized they don't seem to work well with non-piecewise-linear paths obtained, e.g., using the to[in=#,out=#] command. For instance, this code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{verbatim}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength{\PreviewBorder}{10pt}%
\usetikzlibrary{arrows, decorations.markings}
% for double arrows a la chef
% adapt line thickness and line width, if needed
\tikzstyle{vecArrow} = [thick, decoration={markings,mark=at position
   1 with {\arrow[semithick]{open triangle 60}}},
   double distance=1.4pt, shorten >= 5.5pt,
   preaction = {decorate},
   postaction = {draw,line width=1.4pt, white,shorten >= 4.5pt}]
\tikzstyle{innerWhite} = [semithick, white,line width=1.4pt, shorten >= 4.5pt]

\begin{document}
\begin{tikzpicture}[thick]
  \node[draw,rectangle] (a) {A};
  \node[inner sep=0,minimum size=0,right of=a] (k) {}; % invisible node
  \node[draw,rectangle,right of=k] (b) {B};
  \node[draw,rectangle,below of=a] (c) {C};

  % 1st pass: draw arrows
  \draw[vecArrow] (a) to (b);
  \draw[vecArrow] (k) to[out=-90,in=0] (c);
  \draw[vecArrow] (a) to[out=90,in=90] (b);

  % 2nd pass: copy all from 1st pass, and replace vecArrow with innerWhite
  \draw[innerWhite] (a) to (b);
  \draw[innerWhite] (k) to[out=-90,in=0] (c);
  \draw[innerWhite] (a) to[out=90,in=90] (b);

  % Note: If you have no branches, the 2nd pass is not needed
\end{tikzpicture}
\end{document}

yields this result

enter image description here

where the arrowheads are not even visible.

Any idea of how to make the style consistently work with bent lines, too?

0

1 Answer 1

4

It is known that decorations may disappear at high curvature if they are at the end of the path. Therefore, a possible workaround is to replace at position 1 by at position 0.99at position 0.999. (switch to 0.999, thanks to @gbernardi!)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{verbatim}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength{\PreviewBorder}{10pt}%
\usetikzlibrary{arrows, decorations.markings}
% for double arrows a la chef
% adapt line thickness and line width, if needed
\tikzset{vecArrow/.style={thick, decoration={markings,mark=at position
   0.999 with {\arrow[semithick]{open triangle 60}}},
   double distance=1.4pt, shorten >= 5.5pt,
   preaction = {decorate},
   postaction = {draw,line width=1.4pt, white,shorten >= 4.5pt}},
innerWhite/.style={semithick, white,line width=1.4pt, shorten >= 4.5pt}}

\begin{document}
\begin{tikzpicture}[thick]
  \node[draw,rectangle] (a) {A};
  \node[inner sep=0,minimum size=0,right of=a] (k) {}; % invisible node
  \node[draw,rectangle,right of=k] (b) {B};
  \node[draw,rectangle,below of=a] (c) {C};

  % 1st pass: draw arrows
  \draw[vecArrow] (a) to (b);
  \draw[vecArrow] (k) to[out=-90,in=0] (c);
  \draw[vecArrow] (a) to[out=90,in=90] (b);

  % 2nd pass: copy all from 1st pass, and replace vecArrow with innerWhite
  \draw[innerWhite] (a) to (b);
  \draw[innerWhite] (k) to[out=-90,in=0] (c);
  \draw[innerWhite] (a) to[out=90,in=90] (b);

  % Note: If you have no branches, the 2nd pass is not needed
\end{tikzpicture}
\end{document}

enter image description here

Alternatively you can use the outlined arrow decoration.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{decorations,decorations.text} %  decorations.text just 4 fun

\usetikzlibrary{decorations,decorations.text} %  decorations.text just 4 fun
\pgfkeys{/tikz/.cd,
    outlined arrow width/.store in=\OutlinedArrowWidth,
    outlined arrow width=5pt,
    outlined arrow step/.store in=\OutlinedArrowStep,
    outlined arrow step=1pt,
    outlined arrow length/.store in=\OutlinedArrowLength,
    outlined arrow length=5pt,
}

\pgfdeclaredecoration{outlined arrow}{initial}
{% initial arrow butt
\state{initial}[width=\OutlinedArrowStep,next state=cont] {
    \pgfmoveto{\pgfpoint{\OutlinedArrowStep}{\OutlinedArrowWidth/2}}
    \pgfpathlineto{\pgfpoint{0.3\pgflinewidth}{\OutlinedArrowWidth/2}}
    \pgfpathlineto{\pgfpoint{0.3\pgflinewidth}{-\OutlinedArrowWidth/2}}
    \pgfpathlineto{\pgfpoint{1pt}{-\OutlinedArrowWidth/2}}
    \pgfcoordinate{lastup}{\pgfpoint{1pt}{\OutlinedArrowWidth/2}}
    \pgfcoordinate{lastdown}{\pgfpoint{1pt}{-\OutlinedArrowWidth/2}}
    \xdef\marmotarrowstart{0}
  }
  \state{cont}[width=\OutlinedArrowStep]{
    \ifdim\pgfdecoratedremainingdistance>\OutlinedArrowLength% continue the outlined path
     \pgfmoveto{\pgfpointanchor{lastup}{center}}
     \pgfpathlineto{\pgfpoint{\OutlinedArrowStep}{\OutlinedArrowWidth/2}}
     \pgfcoordinate{lastup}{\pgfpoint{\OutlinedArrowStep}{\OutlinedArrowWidth/2}}
     \pgfmoveto{\pgfpointanchor{lastdown}{center}}
     \pgfpathlineto{\pgfpoint{\OutlinedArrowStep}{-\OutlinedArrowWidth/2}}
     \pgfcoordinate{lastdown}{\pgfpoint{\OutlinedArrowStep}{-\OutlinedArrowWidth/2}}
    \else
     \ifnum\marmotarrowstart=0% draw the arrow head
     \pgfmoveto{\pgfpointadd{\pgfpointanchor{lastup}{center}}{\pgfpoint{-0.5\pgflinewidth}{0}}}
     \pgflineto{\pgfpoint{-0.5\pgflinewidth}{\OutlinedArrowWidth}}
     \pgflineto{\pgfpointadd{\pgfpointdecoratedpathlast}{\pgfpoint{-0.5\pgflinewidth}{0}}}
     \pgflineto{\pgfpoint{-0.5\pgflinewidth}{-\OutlinedArrowWidth}}
     \pgflineto{\pgfpointadd{\pgfpointanchor{lastdown}{center}}{\pgfpoint{-0.5\pgflinewidth}{0}}}
     \xdef\marmotarrowstart{1}
     \else
     \fi
    \fi%
  }
  \state{final}[width=5pt]
  { % perhaps unnecessary but doesn't hurt either
    \pgfmoveto{\pgfpointdecoratedpathlast}
  }
}
\begin{document}
\begin{tikzpicture}[thick,decoration=outlined arrow]
  \node[draw,rectangle] (a) {A};
  \node[inner sep=0,minimum size=0,right of=a] (k) {}; % invisible node
  \node[draw,rectangle,right of=k] (b) {B};
  \node[draw,rectangle,below of=a] (c) {C};
  \draw[decorate] (a) to (b);
  \draw[decorate] (k) to[out=-90,in=0] (c);
  \draw[decorate] (a) to[out=90,in=90] (b);
  \draw[white,line width=4pt,shorten <=1pt,shorten >=4pt] (a) to (b);
  \draw[white,line width=4pt] (k) -- ++(0,-4pt);
\end{tikzpicture}  
\end{document}

enter image description here

2
  • Thanks. That works. Although in the specific case I was working on, 0.99 would show the arrowhead far enough from the block to be noticed, 0.999 seems to be doing the trick ;)
    – gbernardi
    Commented Oct 8, 2018 at 14:56
  • @gbernardi You are right. I switched to 0.999 (and added an alternative).
    – user121799
    Commented Oct 8, 2018 at 14:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .