[Tex/LaTex] Add arrows to a smooth tikz function

tikz-pgf

Using this answer here I have been able to draw smooth curves using tikz
Easy curves in TikZ
but I also wanted arrows along my curves, after a bit of fiddling I came up with
the following

\documentclass[a4paper,12pt]{standalone} 
\usepackage{tikz}
\usetikzlibrary{arrows}
\input{arrowsnew}
\usetikzlibrary{decorations.pathreplacing,decorations.markings}
\tikzset{arrow data/.style 2 args={%
      decoration={%
         markings,
         mark=at position #1 with \arrow{#2}},
         postaction=decorate}
      }%
\begin{document}
\begin{tikzpicture}
\begin{scope}[scale=2]
\node[label=below:$A$] (A) at (0,0) {};
\node[label=below:$B$] (B) at (2,0.25){};
\draw [red,arrow data={0.25}{stealth},
           arrow data={0.5}{stealth},
           arrow data={0.75}{stealth}] plot [smooth,tension=1] coordinates {(A) (1,0) (1.14,-0.6) (0.5,-0.5) (0.5,0.5) (1.5,0) (B)};
\draw [black] plot [smooth,tension=1] coordinates {(A) (1,0) (1.14,-0.6) (0.5,-0.5) (0.5,0.5) (1.5,0) (B)};
\end{scope}
\draw [fill=black] (A) circle (1pt);
\draw [fill=black] (B) circle (1pt);
\end{tikzpicture}
\end{document}

enter image description here

This seems somewhat hacky and I am looking for a solution improving a few parts about the code. Optimally I would like

  • that the arrow scales along with the scaling of the figure (or specify size, not really wanted).
  • different colors for the curve and the arrow heads. Something along the lines of
    \draw[color = black,arrow color = red,...]
  • to specify number of arrows along the curve OR use the number of points.
    Eg
    \draw[arrow number=10] and \draw[arrow number=points]

For the colors I used the same plot function twice, ugh. Optimally the arrows should be in front of the figure and not behind.
I have seen a post about scaling arrow heads, for an example
Is it possible to change the size of an arrowhead in TikZ/PGF?
but I was not able to implement the solution… Adding arrowhead=10mm to the \draw
command did nothing. I also found a question regarding several arrows along a curve
deppendant on the number of points, TikZ: How to draw an arrow in the middle of the line?
However this is using the \path option in tikz instead of \plot as I am using.
Blindly implementing the solution Latex decided to throw me a couple of dimensions to large errors, so I guess one has to use a bit more finesse to implement this.

Any help or ideas for implementing the bulleted items would be much appreaciated. I really tried solving these issues on my own, but my tikz abilities are somewhat limited.

Best Answer

Adapting Qrrbrbirlbels answer from here: https://tex.stackexchange.com/a/131325/10995

You will want to use it like

\draw plot ... [arrow inside={end=stealth,opt={scale=2}}{0.25,0.5,0.75}];

It is important, to place it after the plot part, because else you will get Dimension too large errors, which emerge from an incompatibility between smooth and decorate. The first argument of arrow inside accepts the keys end and opt; in end=... you put the arrow tip, in opt={...} you can put any arrow tip options. The second argument to arrow inside is a list of positions between 0 and 1 where you want the markings to be placed.

Implementation

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{decorations.markings}
\tikzset{
    set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
    set arrow inside={end/.initial=>, opt/.initial=},
    /pgf/decoration/Mark/.style={
        mark/.expanded=at position #1 with
        {
            \noexpand\arrow[\pgfkeysvalueof{/tikz/arrow inside/opt}]{\pgfkeysvalueof{/tikz/arrow inside/end}}
        }
    },
    arrow inside/.style 2 args={
        set arrow inside={#1},
        postaction={
            decorate,decoration={
                markings,Mark/.list={#2}
            }
        }
    },
}
\begin{document}
\begin{tikzpicture}
    \begin{scope}[scale=2]
        \node[label=below:$A$] (A) at (0,0) {};
        \node[label=below:$B$] (B) at (2,0.25){};
        \draw[blue] plot [smooth,tension=1]
        coordinates {(A) (1,0) (1.14,-0.6) (0.5,-0.5) (0.5,0.5) (1.5,0) (B)}
        [arrow inside={end=stealth,opt={red,scale=2}}{0.25,0.5,0.75}];
    \end{scope}
    \draw [fill=black] (A) circle (1pt);
    \draw [fill=black] (B) circle (1pt);
\end{tikzpicture}
\end{document}

Output

enter image description here


Alternatively you can draw an arrow at the end of each line segment using the on each segment style as defined here: https://tex.stackexchange.com/a/69225/10995

You need the bending library (from TikZ 3.0.0) to use the [bend] option for the arrows, because else the arrow will modify the path's tension such that the original path and the path redrawn using on each segment will visibly differ. Of course you still apply color, etc. to the arrows. It seems, though, that scale is not possible.

Implementation

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{decorations.pathreplacing,bending}
\makeatletter
\tikzset{
    on each segment/.style={
        decorate,
        decoration={
            show path construction,
            moveto code={},
            lineto code={
                \path [#1]
                (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
            },
            curveto code={
                \path [#1] (\tikzinputsegmentfirst)
                .. controls
                (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb)
                ..
                (\tikzinputsegmentlast);
            },
            closepath code={
                \path [#1]
                (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
            },
        },
    },
}
\makeatother
\begin{document}

\clearpage

\begin{tikzpicture}
    \begin{scope}[scale=2]
        \node[label=below:$A$] (A) at (0,0) {};
        \node[label=below:$B$] (B) at (2,0.25){};
        \draw[blue] plot [smooth,tension=1]
        coordinates {(A) (1,0) (1.14,-0.6) (0.5,-0.5) (0.5,0.5) (1.5,0) (B)}
        [postaction={on each segment={draw,-{stealth[red,bend]}}}];
    \end{scope}
    \draw [fill=black] (A) circle (1pt);
    \draw [fill=black] (B) circle (1pt);
\end{tikzpicture}
\end{document}

Output

enter image description here