Bend arrow decorations in Tikz

This is a follow-up to my recent question Half arrows in graph using TikZ.

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,arrows,arrows.meta,bending,decorations.pathreplacing,
decorations.pathmorphing,decorations.markings,fit,patterns,
shapes,intersections,calc}

\begin{document}

\tikzset
{
down oriented arrow/.style 2 args = {
thick,
decoration={
markings,
mark=at position 0.01 with
{
\coordinate (A) at (0,0);
\coordinate (B) at (.125,.125);
},
mark=at position 0.99 with
{
\coordinate (C) at (-.25,.125);
\coordinate (D) at (-.25,.25);
\coordinate (E) at (0,0);
\filldraw[#1,#2]
(A) -- (B) -- (C) -- (D) -- (E) -- cycle;
}
},
preaction = {decorate},
},
down oriented arrow/.default={draw=black}{fill=black!30}
}
\tikzset
{
up oriented arrow/.style 2 args = {
thick,
decoration={
markings,
mark=at position 0.01 with
{
\coordinate (A) at (0,0);
\coordinate (B) at (.125,-.125);
},
mark=at position 0.99 with
{
\coordinate (C) at (-.25,-.125);
\coordinate (D) at (-.25,-.25);
\coordinate (E) at (0,0);
\filldraw[#1,#2]
(A) -- (B) -- (C) -- (D) -- (E) -- cycle;
}
},
preaction = {decorate},
},
up oriented arrow/.default={draw=black}{fill=black!30}
}

\begin{tikzpicture}[align=center,node distance=3cm]
\node[draw,circle] (a) {};
\node[draw,circle,right of=a] (b) {};

\node[draw,circle,below of=a] (c) {};
\node[draw,circle,right of=c] (d) {};

\draw[down oriented arrow={draw=green!90}{fill=green!30}] (a) to node [midway,sloped,above = 2pt] {$\vec{e}$} (b);
\draw[down oriented arrow={draw=blue!90}{fill=blue!30}] (b) to (a);
\draw[up oriented arrow={draw=orange!90}{fill=orange!30}] (b) to node [midway,sloped,above = 2pt] {$\vec{e}$} (c);
\draw[up oriented arrow={draw=red!90}{fill=red!30}] (c) to (b);
\draw[down oriented arrow] (d) to[bend right] (b);
\end{tikzpicture}

\end{document}


What I would like to achieve is that the decorations created by the up oriented arrow and down oriented arrow styles bend with the edge. Is it possible to achieve this?

• If they were 'real' arrows, bending would work. But these are not... – cfr Feb 3 '15 at 23:25
• @cfr I think there is no existing arrow style that does what I want. If you include custom arrows, then I disagree. They would not bend automatically right if you somehow connect the arrow head and tail as above. But I am not sure about how to do that anyway, so I am thankful for help. – user26756 Feb 4 '15 at 6:03

Here's a Metapost approach, using a macro to do the half-arrow. The arguments to the macro are a path and a colour. The arrow is made by moving segments of the path and then joining them up.

prologues := 3;
outputtemplate := "%j%c.eps";

save base, shaft, outline, barb; path base, shaft, outline; pair barb;
base  = subpath(1/10 length p, 9/10 length p) of p;
shaft = subpath(3/20 length p, 8/10 length p) of p
shifted (unitvector(direction 1/2 length p of p rotated 90) scaled 4);
barb  = unitvector(direction 8/10 length p of p rotated 90) scaled 6 shifted point 8/10 length p of p;
outline = base -- barb -- reverse shaft -- cycle;

enddef;

beginfig(1);

u = 3cm;

z0 = origin;
z1 = (u,0);
z2 = (u,u);
z3 = (0,u);

do_half_arrow(z3 -- z2, 1/2 green);
do_half_arrow(z2 -- z3, blue);
do_half_arrow(z0 -- z2, red + 1/2 green);
do_half_arrow(z2 -- z0, red);

draw z0--z2;
draw z2--z3;

path arc; arc = z1 {dir 60} .. z2;

do_half_arrow(arc,black);

draw arc;

forsuffixes $= range 0 thru 3: fill fullcircle scaled .12u shifted z$ withcolor background;
draw fullcircle scaled .12u shifted z$; endfor picture e; e = thelabel(btex$\vec{e}etex, origin); draw e shifted 10 up shifted .5[z3,z2]; draw e shifted 10 up rotated 45 shifted .5[z0,z2]; endfig; end.  The path can be any arbitrary curve, but it will probably work best with straight or gently curved lines, like this for example: beginfig(2); path p; p = origin .. (50,15) .. (100,-5) .. (140,10); do_half_arrow(p, .67 blue); do_half_arrow(reverse p, .53 red); drawarrow p; endfig;  • Pfff... very nice again. Now I have to make the TikZ equivalent. Why do you do this to me? ;) – percusse Feb 4 '15 at 13:58 • @percusse it's not personal! – Thruston Feb 4 '15 at 15:23 • Very nice thank you. Still hope that someone is going to post a TikZ solution though. – user26756 Feb 5 '15 at 18:23 I managed to finaly come up with a TikZ solution. It uses markings to define coordinates along the arrow and connects them afterwards. \documentclass[tikz]{standalone} \usetikzlibrary{matrix,arrows,arrows.meta,bending,decorations.pathreplacing, decorations.pathmorphing,decorations.markings,fit,patterns, shapes,intersections,calc} \begin{document} \tikzset { down oriented arrow/.style 2 args = { thick, shorten >= 0.2ex, shorten <= 0.2ex, line cap=round, decoration={ markings, mark=at position 1ex with { \coordinate (T) at (0,0); }, mark=between positions 2ex and -2ex step 1ex with { \pgfkeysgetvalue{/pgf/decoration/mark info/sequence number}{\j} \pgfmathtruncatemacro{\i}{\j-1} \coordinate (A\i) at (0,0); \coordinate (B\i) at (0,.1); \coordinate (C\i) at (0,.15); }, mark=at position -1ex with { \pgfkeysgetvalue{/pgf/decoration/mark info/sequence number}{\j} \pgfmathtruncatemacro{\marks}{\j-2} \coordinate (H) at (0,0); \filldraw[#1,#2] (H) -- (C\marks) foreach \i in {\marks,...,1} { -- (B\i) } -- (T) foreach \i in {1,...,\marks} { -- (A\i)} -- cycle; } }, preaction = {decorate}, }, down oriented arrow/.default={draw=black}{fill=black!30} } \tikzset { up oriented arrow/.style 2 args = { thick, shorten >= 0.2ex, shorten <= 0.2ex, line cap=round, decoration={ markings, mark=at position 1ex with { \coordinate (T) at (0,0); }, mark=between positions 2ex and -2ex step 1ex with { \pgfkeysgetvalue{/pgf/decoration/mark info/sequence number}{\j} \pgfmathtruncatemacro{\i}{\j-1} \coordinate (A\i) at (0,0); \coordinate (B\i) at (0,-.1); \coordinate (C\i) at (0,-.15); }, mark=at position -1ex with { \pgfkeysgetvalue{/pgf/decoration/mark info/sequence number}{\j} \pgfmathtruncatemacro{\marks}{\j-2} \coordinate (H) at (0,0); \filldraw[#1,#2] (H) -- (C\marks) foreach \i in {\marks,...,1} { -- (B\i) } -- (T) foreach \i in {1,...,\marks} { -- (A\i)} -- cycle; } }, preaction = {decorate}, }, up oriented arrow/.default={draw=black}{fill=black!30} } \begin{tikzpicture}[align=center,node distance=3cm] \node[draw,circle] (a) {}; \node[draw,circle,right of=a] (b) {}; \node[draw,circle,below of=a] (c) {}; \node[draw,circle,right of=c] (d) {}; \draw[down oriented arrow={draw=green!90}{fill=green!30}] (a) to node [midway, sloped, above = 2pt] {\color{green}\vec{e}$} (b); \draw[down oriented arrow={draw=blue!90}{fill=blue!30}] (b) to node [midway, sloped, below = 1pt] {\color{blue}$\vec{f}$} (a); \draw[up oriented arrow={draw=orange!90}{fill=orange!30}] (b) to node [midway, sloped, above = 2pt] {\color{orange}$\vec{g}$} (c); \draw[up oriented arrow={draw=red!90}{fill=red!30}] (c) to node [midway, sloped, below = 1pt] {\color{red}$\vec{h}\$} (b);
\draw[down oriented arrow] (d) to[bend right] (b);
\end{tikzpicture}

\end{document}


Result: