7

I'm looking for a convenient way to draw a smooth, tapered path (i.e. a path of variable line width) ending in an arrowhead using TikZ — something like this (drawn in Inkscape):

enter image description here

One approach would be to use a custom decoration as described in this answer (from March 2011), but perhaps there are more straightforward approaches nowadays.

An idea that comes to mind is to draw a smooth path of constant line width and clip it with another path starting at the tail, going up to the start of the arrowhead. However, I just noticed that adding an arrowhead to a path actually changes the path itself (see code snippet and output below), which probably makes this approach a bit more complicated than I originally thought.

\usetikzlibrary{arrows.meta}

\begin{tikzpicture} \draw[line width=1mm, black!40, -{Stealth[length=10mm, width=6mm]}] (0,0) .. controls (2,-1) and (4,-1) .. (6,0); \draw[line width=.2mm] (0,0) .. controls (2,-1) and (4,-1) .. (6,0); \end{tikzpicture}

enter image description here

[Edit] Thanks to @Markus G.'s comment, the changed path issue is resolved (see below). How to proceed?

\usetikzlibrary{bending, arrows.meta}

enter image description here

Ailurus
  • 1,163
  • 1
    Loading the bending library solves this issue. See also here: https://tex.stackexchange.com/a/273201/118712 – Markus G. Jun 07 '21 at 12:02
  • 2
    The calligraphy library can handle the tapering, and then you could add the arrow head separately. – Andrew Stacey Jun 07 '21 at 17:21
  • Concerning your question of tapering the path, this question has apparently been around for a while, as you can see here: https://tex.stackexchange.com/q/14283/118712 There is possible solution given, but I couldn't make this work with an arrow head, but it may be a good starting point. – Markus G. Jun 08 '21 at 09:35
  • @MarkusG. : Here is a working arrow by Milo: https://tex.stackexchange.com/a/471213/8650 . – hpekristiansen Jun 08 '21 at 12:17
  • Could this question be a duplicate of: https://tex.stackexchange.com/questions/471204/randomly-curved-arrows-in-tikz - I am not sure. -anyway there are some solutions, that might work here. – hpekristiansen Jun 08 '21 at 12:18
  • Your example is really what you are looking for in terms of geometry, i.e. are you looking for a path with at most one bent? – Daniel N Jun 09 '21 at 08:24
  • @MarkusG. That is indeed the approach I'm referring to in my question. Unfortunately, just as with Andrew Stacey's calligraphy package, adding a separate arrowhead to the path (which at that end has a larger line width) does not appear exactly trivial. – Ailurus Jun 09 '21 at 09:18
  • @hpekristiansen This looks promising — the variable line width is based on the method I'm referring to in my question, and they manage to attach an arrowhead to the resulting path. I'll look into it and report back! – Ailurus Jun 09 '21 at 09:18
  • @DanielN Good question! Although I'd be curious about how to pull this off for general paths, focusing on singly bent paths would suffice. – Ailurus Jun 09 '21 at 09:19

1 Answers1

5

enter image description here

I propose a solution (or at least the beginning of a solution) based on @Alain Matthes's answer. Looking at the image above, we see, on the left, a case when the solution works (a simple to[] operation) and a case when it doesn't (an arc operation). The lower-right curve is the original curve from Alain's answer with width factor = 1 (for reference).

I introduce a decoration that puts together Alain's and a show path construction that introduces the arrow tip. There are three arguments: the width factor and the colors, start color and end color (already present in the previous answer).

Note that the resulting curve is slightly longer; the yellow curve drawn over the lower-left curve in the image shows the original path.

Remark 1. You can modify the relationship between the widths of the curve and arrow at their meeting point by modifying the constants in the definitions of \w and \d.

Remark 2. I think Alain's decoration could be modified in a more intelligent way to produce the result you are looking for, but I don't know how (I don't know how to use pgf commands).

The code

\documentclass[11pt, border=.5cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{math, arrows.meta}
\usetikzlibrary{decorations.pathreplacing}

%%% Alain Matthes's decoration \pgfkeys{/pgf/decoration/.cd, width factor/.store in =\wfactor, start color/.store in =\startcolor, end color/.store in =\endcolor }

\makeatletter \pgfdeclaredecoration{width and color change}{initial}{ \state{initial}[width=0pt, next state=line, persistent precomputation={% \pgfmathdivide{50}{\pgfdecoratedpathlength}% \let\increment=\pgfmathresult% \def\x{0}% }]{} \state{line}[width=.5pt, persistent postcomputation={% \pgfmathadd@{\x}{\increment}% \let\x=\pgfmathresult% }]{% \pgfsetlinewidth{\wfactor\x/500.075pt+\pgflinewidth}% \pgfsetarrows{-}% \pgfpathmoveto{\pgfpointorigin}% \pgfpathlineto{\pgfqpoint{.75pt}{0pt}}% \pgfsetstrokecolor{\endcolor!\x!\startcolor}% \pgfusepath{stroke}% } \state{final}{% \pgfsetlinewidth{\pgflinewidth}% \pgfpathmoveto{\pgfpointorigin}% \color{\endcolor!\x!\startcolor}% \pgfusepath{stroke}% } } \makeatother

\begin{document}

\tikzset{ tmp/.style n args={3}{ postaction={ decoration={ width and color change, width factor=#1, start color=#2, end color=#3 }, decorate }, preaction={ decoration={ show path construction, curveto code={ \tikzmath{ real \w, \d; \w = {#160}; \d = {#190}; } \draw[#3, arrows={-Stealth[width=\w pt, length=\d pt]}] (\tikzinputsegmentfirst) .. controls (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb) ..(\tikzinputsegmentlast) -- ([turn]0: \w pt); } }, decorate } } }

\begin{tikzpicture} \draw[tmp={.4}{blue}{gray}] (0, 0) to[out=0, in=150] ++(6, 2); \draw[tmp={.4}{blue}{gray}] (0, -1) to[out=0, in=150] ++(6, 2); \draw[yellow, thin] (0, -1) to[out=0, in=150] ++(6, 2);

\path[tmp={.4}{yellow}{red}] (14, -1) arc (0: 120: 4); \draw[line width=.4pt, decoration={width and color change,
width factor=1, start color=yellow, end color=red}, decorate] (14, -3) arc (0:120:4cm); \end{tikzpicture}

\end{document}

Daniel N
  • 5,687