# Making the size of the arrow head proportional to the magnitude of a vector field in TikZ

Consider a scaled vector field v = (-x, 2x+y-1) living on the triangle at (0,1), (1,0), and (0,0):

\documentclass{minimal}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (0,1);

\draw[thick] ($(A)$) -- ($(B)$) -- ($(C)$)-- cycle;
\foreach \x in {1, 2, ..., 10}
\foreach \y in {0, 1, ..., \x}
{\draw [-stealth,blue] ($(B)-(0.1,0)+0.1*(1-\x,\y)$)
-- ++(0.02*\x - 0.2, -0.04*\x + 0.4 +0.02*\y-0.2);}
\end{tikzpicture}
\end{document}


The output is as follows:

Comparing with the vector fields drawn by MATLAB's quiver:

The MATLAB's quiver command automatically scales the size of the arrow heads according to the magnitude of the vector.

So my question is: how do we scale the size of the arrow heads in TikZ? Preferably in MATLAB's solution, the vector field vanishes at (0,1) so there is no arrow there.

For example I googled a little bit, and wonder if pgfmath could do some calculation about the length variable \l. Then doing something like will work:

\draw [-stealth,blue, single arrow head extend=\l mm] ($(B)-(0.1,0)+0.1*(1-\x,\y)$)
-- ++(0.02*\x - 0.2, -0.04*\x + 0.4 +0.02*\y-0.2);


Thanks.

• The arrow tip’s size is usually defined in dependence of the line width. One answer of Is it possible to change the size of an arrowhead in TikZ/PGF? should help here. – Qrrbrbirlbel Sep 19 '13 at 20:54
• @Qrrbrbirlbel Thank you sir. That's very informative. How to put some calculated length into the option of the \draw command? For example \draw [-stealth,blue, single arrow head extend=\x mm] – Shuhao Cao Sep 19 '13 at 21:12
• @Qrrbrbirlbel Thank you so much sir, I have used that new arrow library to make up an answer to my own question. – Shuhao Cao Sep 20 '13 at 16:20

You could use PGFPlots' quiver functionality together with a bit of coordinate filtering to achieve this:

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={0}{90},
axis equal image,
hide axis, clip=false
]
blue,
point meta={sqrt(x^2+(2*x+y-1)^2)},
quiver={
u={-x}, v={2*x+y-1},
scale arrows=0.1,
every arrow/.append style={
line width=2pt*\pgfplotspointmetatransformed/1000,
-latex
},
},
samples=10,
domain=0:1, y domain=0:1,
y filter/.append code={\pgfmathparse{(x+y)>1 ? nan : y}},
x filter/.append code={\pgfmathparse{(sqrt(x^2+(2*x+y-1)^2))==0 ? nan : x}}
] (x,y,0);

\draw (axis cs:0,0) -- (axis cs:1,0) -- (axis cs:0,1) -- cycle;
\end{axis}
\end{tikzpicture}

\end{document}

• Thanks, this is nice. :) If there is no other pure TikZ solutions, I will accept your answer. – Shuhao Cao Sep 19 '13 at 21:13
• @ShuhaoCao: what do you mean with pure TikZ? Pgfplots is built as an extension of TikZ so... – Claudio Fiandrino Sep 20 '13 at 6:23
• How to use quiver? I'm getting the error pgfkeys: I do not know the key '/tikz/quiver' and I am going to ignore it. Perhaps you misspelled it. ] (x,y,0); – Sigur Oct 16 '13 at 0:31
• @Sigur: You may be using an old version of PGFPlots, I think you need at least version 1.4 for the quiver plots. – Jake Oct 16 '13 at 5:46
• @Jake, thanks. I've installed the newer one and it's working fine. – Sigur Oct 16 '13 at 11:55

Based on Qrrbrbirlbel's comment I have come up with my own solution as well besides the nice answer using quiver by Jake. I am using the New arrows library in this question made by Luigi (and it is great!): Is it possible to change the size of an arrowhead in TikZ/PGF?

You can download the two .tex files in the sourceforge link Luigi gave, and put them in the same directory of your main file then you can compile it using pdflatex or xelatex.

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{arrows,arrows.new}
\begin{tikzpicture}[scale=4]
\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (0,1);
\draw[thick] ($(A)$) -- ($(B)$) -- ($(C)$)-- cycle;

\foreach \x in {1, 2, ..., 10}
\foreach \y in {0, 1, ..., \x}
{\pgfmathsetmacro\arrowHeadsize{sqrt(0.1*(-0.2*\x + 0.1*\y+1)*(-0.2*\x + 0.1*\y+1)
+0.1*(1-0.1*\x)*(1-0.1*\x))}
\draw [thick, -stealth new, blue, arrow head=\arrowHeadsize cm]
($(B)-(0.1,0)+0.1*(1-\x,\y)$)
-- ++(0.02*\x - 0.2, -0.04*\x + 0.4 +0.02*\y-0.2);}
\end{tikzpicture}
\end{document}


The output is as follows:

A major difference between above solution with the solution using PGFplots's quiver is that, by default, quiver scales the thickness of the arrow's body as well, here using this approach the arrow thickness is unchanged, only the size of the arrow heads are changed.