4

I wish to draw a curved arrow whose thickness changes from end to head. Such arrows are commonly used in military maps to denote the moves of forces. Below is an example.

A Military Map

Is it possible to do it in tikz? Thanks!

4
  • 1
    Although typically questions like this will get a lot of comments about "showing what you've tried", in this case, the problem is truly quite difficult with TikZ. Related: Stroke with variable thickness and possibly Is it possible to increase the line's width from its start to its end?
    – Alan Munn
    Oct 24 '17 at 4:02
  • 1
    OTOH, if you don't think of it as an arrow, but as two curved lines with a straight line at one end and a triangle at the other... Oct 24 '17 at 4:11
  • @JohnKormylo Yes, that's probably the simplest way to draw them, but still not totally straightforward.
    – Alan Munn
    Oct 24 '17 at 4:15
  • @AlanMunn - The question is how to parameterize the arrow. End points aren't enough, you need the starting width, ending width and curvature. Oct 24 '17 at 4:19
10

Not amazing, and will quite happily produce horrendous results with extreme curves or parameter values. Currently for single curveto operations only (i.e., paths consisting of a single Bézier curve).

\documentclass[tikz,margin=5]{standalone}
\usetikzlibrary{calc,decorations.pathreplacing,decorations.markings}
\tikzset{big arrow/.style={
  /tikz/big arrow/.cd, #1, /tikz/.cd,
  decoration={show path construction,
  curveto code={%
%
\path [discard, decoration={ markings, 
  mark=at position -\bigarrowlength with {\coordinate (@); }}, decorate] 
  (\tikzinputsegmentfirst) .. controls (\tikzinputsegmentsupporta)
  and (\tikzinputsegmentsupportb) .. (\tikzinputsegmentlast);
\path[big arrow/.cd,#1] 
  let \p1=(\tikzinputsegmentfirst), \p2=(\tikzinputsegmentsupporta),
  \p3=(\tikzinputsegmentsupportb), \p4=(@), \p5=(\tikzinputsegmentlast),
  \n1={atan2(\y2-\y1,\x2-\x1)}, \n2={atan2(\y4-\y3,\x4-\x3)} in
  (\p1) -- ++(\n1+90:\bigarrowstartwidth/2) 
  .. controls ++(\x2-\x1, \y2-\y1) and ++(\x3-\x4, \y3-\y4) .. 
  ($(\p4)+(\n2+90:\bigarrowendwidth/2)$) -- 
  ($(\p4)+(\n2+90:\bigarrowwidth/2)$) -- (\p5) --
  ($(\p4)+(\n2-90:\bigarrowwidth/2)$) -- 
  ($(\p4)+(\n2-90:\bigarrowendwidth/2)$)
  .. controls ++(\x3-\x4, \y3-\y4) and ++(\x2-\x1, \y2-\y1) ..
  ($(\p1)+(\n1-90:\bigarrowstartwidth/2)$) -- cycle;
%
  }}, decorate
},
big arrow/.cd,
  start width/.store in=\bigarrowstartwidth,
  end width/.store in=\bigarrowendwidth,
  length/.store in=\bigarrowlength,
   width/.store in=\bigarrowwidth,
  start width=1cm,
  end width=0.5cm,
  length=0.25cm,
  width=1cm,
  .unknown/.code=%
    {\let\searchname=\pgfkeyscurrentname\pgfkeysalso{/tikz/\searchname=#1}}%
}
\begin{document}
\begin{tikzpicture}
\draw [big arrow={fill=red}] (0,0) to [bend left] (5,5);
\draw [big arrow={fill=green, length=0.5cm}] (0,0) to [bend right] (-3,3);
\draw [big arrow={fill=blue, start width=1.5cm, end width=1cm,
  width=1.5cm, length=0.75cm}] (0,0) to [bend right] (4,0);
\end{tikzpicture}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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