Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
    
Related: Qrrbrbirlbels answer tex.stackexchange.com/a/131325/10995 –  Henri Menke Mar 4 at 19:11
    
With TiKZ 3.0 and its arrows.meta library, arrow size is proportional to line thickness, you can define tip color different form line color, ... (tex.stackexchange.com/a/161238/1952) –  Ignasi Mar 4 at 19:35

1 Answer 1

up vote 12 down vote accepted

Adapting Qrrbrbirlbels answer from here: http://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: http://tex.stackexchange.com/a/69225/10995

You will need the bending library (from TikZ 3.0.0) and will will need to use the [bend] option for the arrows, because else the arrow will modify the paths tension and the original path an the path redrawn using on each segment will visibly differ. Of course you still apply color, etc. to the arrows. It seem thou, 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

share|improve this answer
    
Thanks! This solves one of my three problems, really nice (+1) –  N3buchadnezzar Mar 4 at 19:53
1  
@N3buchadnezzar Really? Which problems are still open? I thought, I solved them all. –  Henri Menke Mar 4 at 20:13
    
Ah you edited your post! Sneaky man ^^ One still has to specify the placement of the arrows. Is it possible to instead specify how many one wants? If I want n arrows the placement of them should be i/(n+1) where i ranges from 1 to n. I tried to impliment this with a loop pastebin.com/hG1GnNES However if i try to replace {0.25, 0.5, 0.75} with {\arrowN{3}} I get the following error ! Use of \@undeclaredcolor doesn't match its definition.\kernel@ifnextchar ...rved@d =#1\def \reserved@a {#2}\def \reserved@b {#3}\f... ...={end=stealth,opt={scale=2}}{\arrowN{3}}]; –  N3buchadnezzar Mar 4 at 20:25
    
@N3buchadnezzar I don't think, that this is possible with the current solution, because the list needs to be expanded before it can be passed to arrow inside (for reference try passing \xyz as second argument, where \def\xyz{0.25,0.5,0.75}). It might be possible with plastering the code with \expandafters. –  Henri Menke Mar 4 at 20:35
    
@N3buchadnezzar I added a solution, which uses the plot coordinates to draw the arrows. –  Henri Menke Mar 4 at 20:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.