# Decorate path with arrows at nodes

Standalone example:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes}

\begin{document}
\begin{tikzpicture}
\draw[black, very thick] plot[smooth] coordinates {(4,1) (2,2) (1,3) (2,4) (4,3)};

\node[fill=green!60, inner sep=3pt, circle, draw] at (4, 1) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (2, 2) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (1, 3) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (2, 4) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (4, 3) {};
\end{tikzpicture}
\end{document}


Result:

What I want:

I like to have arrows before each node point at the node on all nodes in the path. How do I achieve this?

-
Possible duplicate: TikZ: How to draw an arrow in the middle of the line? – Paul Gaborit Oct 3 '12 at 20:02
No, I do not think this is a duplicate. Here it is a complete curve which passes behind the nodes. I also tried with path between nodes (it also works) but then you lose the effect of the curve. – madit Oct 3 '12 at 20:12

Based on my own answer to this question, I got the following result:

Positioning of the arrows is done automatically according to the list of points that appears at the beginning of the code. Here we go:

\documentclass{standalone}

\usepackage{etoolbox}

\usepackage{tikz}
\usetikzlibrary{shapes}
\usetikzlibrary{intersections}
\usetikzlibrary{decorations.markings}

\newcounter{counter}
\newcommand\getpoint[1]{\csuse{point#1}}
\def\pointlist{}
\newcommand\setpoint[2]{
\node (point#1) at #2 {};
\csxdef{point#1}{#2}
\edef\pointlist{\pointlist \getpoint{#1}}
}

\newcounter{anothercounter}
\newcommand\getanotherpoint[1]{\csuse{anotherpoint#1}}
\def\anotherpointlist{}
\newcommand\setanotherpoint[2]{
\csxdef{anotherpoint#1}{#2}
\edef\anotherpointlist{\anotherpointlist \getanotherpoint{#1}}
}

\begin{document}
\begin{tikzpicture}

\draw [name path = curve 1, black, very thick] plot [smooth] coordinates {\pointlist};
\path [name intersections={of=curve 1 and curve 1, name=i, total=\t, sort by = curve 1}] node {\xdef\totalone{\t}};

\edef\mypath{}
\pgfmathsetmacro{\lastbutone}{\totalone - 1}
\foreach \k in {1, ..., \lastbutone}
{
\xdef\mypath{\mypath (i-\k) -- }
}
\edef\mypath{\mypath (i-\totalone)}

\newdimen\xone
\newdimen\yone
\newdimen\xtwo
\newdimen\ytwo

\foreach \q in {1, ..., \thecounter}
{
\pgfextractx{\xtwo}{\pgfpointanchor{point\q}{center}}
\pgfextracty{\ytwo}{\pgfpointanchor{point\q}{center}}

\foreach \p in {1, ..., \totalone}
{
\pgfextractx{\xone}{\pgfpointanchor{i-\p}{center}}
\pgfextracty{\yone}{\pgfpointanchor{i-\p}{center}}

\ifboolexpr{
test {\ifdimless{\xtwo - 0.6pt}{\xone}} and test {\ifdimless{\xone}{\xtwo + 0.6pt}}
and
test {\ifdimless{\ytwo - 0.6pt}{\yone}} and test {\ifdimless{\yone}{\ytwo + 0.6pt}}
}{
\setanotherpoint{\q}{\p}
}{
}
}
}

\foreach \k in {1, ..., \thecounter}
{
\node [
circle
, fill = green!60
, inner sep = 3pt
] (thepoint \k) at (i-\getanotherpoint{\k}) {};
}

\foreach \k in {2, ..., \thecounter}
{
\pgfmathtruncatemacro{\lastpoint}{\getanotherpoint{\k} - 5}
\draw [decorate, decoration = {markings, mark = at position -0.01pt with {
\node [
single arrow
, fill = red
, anchor = east
, minimum size = 2mm
, inner sep = 1pt
, single arrow head extend = 2pt
, transform shape
]{};
}}] (i-\lastpoint) -- (thepoint \k) {};
}
\end{tikzpicture}
\end{document}


## EDIT

OBS: I changed the style of the arrow just to be more like the provided example.

Well, just to complete my answer, now I will give a little more detail. Tripplet said there was a space between the arrow and cículo and he was right, as can be seen here:

The distance between the circle and the arrow was given by the contour line, which was not being drawn. This is easily fixed as you can see:

\foreach \k in {1, ..., \thecounter} {
\node [
circle
, draw = green      % added
, fill = green!50
, inner sep = 3pt
] (thepoint \k) at (i-\getanotherpoint{\k}) {};
}


And the result is

But, if desired the arrow gets further into the circle, one can make the following changes:

\foreach \k in {1, ..., \thecounter} {
\node [
circle
, inner sep = 2.75pt
] (thepoint \k) at (i-\getanotherpoint{\k}) {};
\node [
circle
, draw = green
, fill = green!50
, inner sep = 3pt
] at (i-\getanotherpoint{\k}) {};
}


And you will get:

-
I don't like the point, that the arrows are not curved and look a little out of place. – tripplet Oct 11 '12 at 12:43
@tripplet: Could you explain a little better? What do you mean by out of place? The arrows are being placed along the path. The distance is calculated directly by Tikz. I have no influence in this point. – tecepe Oct 11 '12 at 17:12
To me the arrows don't look like they are part of the path and separately put over it. Maybe thats just a personal thing, the solution is just as good as the other, but I personally just like the look of madit's solution a little more ;) – tripplet Oct 12 '12 at 11:30
@tripplet, take another look. ;) – tecepe Oct 12 '12 at 14:18
awesome thats exactly what I wanted, thanks @tecepe. I didn't expect this to end this in so much code, good I asked, I would have never figured this out myself. – tripplet Oct 15 '12 at 12:58

Try with

\documentclass[border=2mm,tikz]{standalone}
\usetikzlibrary{shapes}
\usetikzlibrary{decorations.markings,arrows}

\begin{document}
\begin{tikzpicture}[decoration={markings,%
mark=at position .270  with {\arrow[red,line width=3pt]{>}},%
mark=at position .470  with {\arrow[red,line width=3pt]{>}},%
mark=at position .680  with {\arrow[red,line width=3pt]{>}},%
mark=at position .980  with {\arrow[red,line width=3pt]{>}},%
}]
\draw[
black, thick,postaction={decorate} ]%
plot[smooth] coordinates {(4,1) (2,2) (1,3) (2,4) (4,3)};

\node[fill=green!60, inner sep=3pt, circle, draw] at (4, 1) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (2, 2) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (1, 3) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (2, 4) {};
\node[fill=green!60, inner sep=3pt, circle, draw] at (4, 3) {};
\end{tikzpicture}
\end{document}


It works home with pdftex. I havent any trick to find the correct position ... except try and error ;-)

-
Seems to be the best looking solution so far, except the fact, that I have to position the arrows by try and error. Maybe someone knows a solution to this? – tripplet Oct 11 '12 at 12:41

Here a "solution" derived from my answer to TikZ: How to draw an arrow in the middle of the line?.

The result is correct but with errors during compilation. Without smooth, there is no error.

The code:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,decorations.markings}
\tikzset{
% style to apply some styles to each segment of a path
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);
},
},
},
% style to add an arrow
mid arrow/.style={decorate,decoration={
markings,
mark=at position .93 with {\arrow[#1]{stealth}},
},
},
% style to add a circle
point/.style={decorate,decoration={
markings,
mark=at position .99 with {\node[#1,thin,circle,inner sep=2pt]{};},
},
},
}

\begin{document}
\begin{tikzpicture}
\draw[black, very thick,
postaction={on each segment={mid arrow={fill=red,line width=3pt}}},
postaction={on each segment={point={fill=lime,draw=green!50!black}}},
]
plot[smooth] coordinates {(4,1) (2,2) (1,3) (2,4) (4,3)};
\end{tikzpicture}
\end{document}

-
Is Dimension too large the compile error you are referring to? That's what I get if the smooth option is left in there. – Peter Grill Oct 3 '12 at 23:50
@PeterGrill Exact. I'm pretty sure it comes from the markings library... – Paul Gaborit Oct 4 '12 at 0:28
The smooth option is pretty important to me so not the best solution, but good suggestion. – tripplet Oct 11 '12 at 12:40
@tripplet The bug with smooth option and markings library can and must be fixed. I just need time... ;-) – Paul Gaborit Oct 11 '12 at 13:06