19

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:

tikz

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

matlab

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.

3
  • 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. Commented Sep 19, 2013 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
    Commented Sep 19, 2013 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
    Commented Sep 20, 2013 at 16:20

2 Answers 2

17

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
]
\addplot3 [
    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} 
5
  • Thanks, this is nice. :) If there is no other pure TikZ solutions, I will accept your answer.
    – Shuhao Cao
    Commented Sep 19, 2013 at 21:13
  • 1
    @ShuhaoCao: what do you mean with pure TikZ? Pgfplots is built as an extension of TikZ so... Commented Sep 20, 2013 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
    Commented Oct 16, 2013 at 0:31
  • 1
    @Sigur: You may be using an old version of PGFPlots, I think you need at least version 1.4 for the quiver plots.
    – Jake
    Commented Oct 16, 2013 at 5:46
  • @Jake, thanks. I've installed the newer one and it's working fine.
    – Sigur
    Commented Oct 16, 2013 at 11:55
4

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:

scaled

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .