0

I want to make the quiver plot a bit nicer, so I have worked on a nicer representation of the arrow with a bit of a 3D look. The shading of the arrow is taken from another question on this site. And this question is the origin of the \arrowthreeD macro.

At the moment, I'm struggling with the positioning of the arrows. Everything else works fine: the arrows are scaled well and also the coloring via the colormaps works fine. Also, the placement of the arrows is done inside the axis cs, as I see it. (They are placed at 1,\pgfplotspointmetatransformed/200 where \pgfplotspointmetatransformed is 0..1000. So, they are placed accordingly between 0 and 5 for the y value.

However, at the position of the comment in the code, I have no method to access the coordinates (x,y) where the arrows are placed originally. In the pgfplots codem I found something about \pgfplots@current@point@[xyz]. But I could not manage to access the values stored there... Similarly, I don't know how to access u and v, the quiver arrow dimensions, to calculate the angle via atan() or similar procedure.

So, my question might be: How can I access

  • \pgfplots@current@point@x
  • \pgfplots@current@point@y
  • \pgfplots@quiver@u
  • \pgfplots@quiver@v

If I try to just use them, they cannot be evaluated (I get some errors after \pgfplots. E.g. using \pgfplots@current@point@x for the x coordinate results in

! Undefined control sequence.

<argument> \pgfplots

@current@point@x,\pgfplotspointmetatransformed /200

l.95 \end{axis}

?

\documentclass[]{standalone} 
\usepackage{tikz,pgfplots,pgfplotstable,filecontents}
\usepgfplotslibrary{colormaps}
\usetikzlibrary{calc}
\pgfplotsset{compat=1.13}

\newcommand*{\arrowheadthreeD}[4]{%
  \colorlet{beamcolor}{#1!75!black}
  \colorlet{innercolor}{#1!50}
  \foreach \i in {1, 0.975, ..., 0} {
    \pgfmathsetmacro{\shade}{\i*\i*100}
    \pgfmathsetmacro{\startangle}{90-\i*30}
    \pgfmathsetmacro{\endangle}{90+\i*30}
    \fill[beamcolor!\shade!innercolor,shift={#2},rotate=#3,line width=0,line cap=butt,]%,
      (0,0) -- (\startangle:0.2599) arc (\startangle:\endangle:0.2599)--cycle;
  }
  \fill[beamcolor,shift={#2},rotate=#3,line width=0,line cap=butt] (60:0.26) arc (60:120:0.26) -- ($(120:0.26)!0.06*#4!(0,0.0)$) arc (120:60:{0.26-0.015*#4}) -- cycle;
}

\newcommand*{\arrowthreeD}[4]{
  \begin{scope}[shift={([rotate = -#4]#2)}]
    \begin{scope}[,,transform canvas={rotate=#4},scale=#3,]
      \fill [left color=#1!75!black,right color=#1!75!black,middle color=#1!50,join=round,line cap=round,draw=none] (0.05,0) -- (0.05,-0.175) arc (360:180:0.05 and 0.05) -- (-0.05,0)--cycle;
      \arrowheadthreeD{#1}{(0,0.25)}{180}{#3};
    \end{scope}
  \end{scope}
} 


\begin{filecontents}{quiver.txt}
x y u v
1 0.5 1.4 1.4
2 0.1 0 1.5
0.1 2 1 0
0.2 0.75 0.5 0
1 1 0.1 0.1
\end{filecontents}

\begin{document}
\thispagestyle{empty} 
  \begin{tikzpicture}
    \begin{axis}[
        width= 5cm,
        ymin=0, 
        ymax=6,
        xmin=0,
        xmax=3,
        axis equal image,
        clip=false,
        grid=both,
        colormap/hot2,
        ]





      \addplot[
               point meta={sqrt{\thisrow{u}*\thisrow{u}+\thisrow{v}*\thisrow{v}}},
               point meta min=0,
               quiver={u=\thisrow{u},
                       v=\thisrow{v},
                       every arrow/.append style={
                         line width=1pt,
                         draw=none,
                         },
                       after arrow/.code={
                         \arrowthreeD{mapped color}{1,\pgfplotspointmetatransformed/200}{sqrt{\pgfplotspointmetatransformed}/25}{90}
                         %%%%%
                         %%%%%
                         % Explanation: arguments are 
                         %   color 
                         %   coordinates (should be (x,y))
                         %   scaling value
                         %   angle (should be computed from atan(u,v) or similar)
                         %%%%%
                         %%%%%
                       },  
                       },
               ] table {quiver.txt};

      \addplot[
               point meta={sqrt{\thisrow{u}*\thisrow{u}+\thisrow{v}*\thisrow{v}}},
               quiver={u=\thisrow{u},
                       v=\thisrow{v},
                       every arrow/.append style={
                         line width=2pt*\pgfplotspointmetatransformed/1500,
                         ->,
                         },
                       },
               ] table {quiver.txt};
   \end{axis}
  \end{tikzpicture} 

\end{document}

And of course a picture of the current results: (positioning of the new arrows is quite arbitrary) enter image description here

  • 2
    Do you have links for the sources you used? Not just an issue of courtesy in attribution, but we currently have no idea how you've modified what, which might indicate what is going on. You need to use the axis coordinate system - the axisenvironment switches to its own coordinate system, but you seem to be placing things using the regular coordinate system. At first glance, anyway. So I'm confused as to how this can have worked in whatever source you got it from. – cfr Apr 21 '17 at 1:32
  • @cfr I have added the underlying questions, they are tikz only. I use these tikz stuff inside the axis environment and hence the arrow placing already happens accordingly in the axis cs (I tried to explain it in the question). – Faekynn Apr 21 '17 at 7:52
  • I also tried to clarified that I saw something in the pgfplotscode about \pgfplots@current@point@[xyz] and wonder how to get these values.... Using \E\pgfplots@current@point@z as I see it in pgfplotsplothandlers.code.tex didn't work. – Faekynn Apr 21 '17 at 7:53
1

With the help of other questions, here and here, I could manage to achieve my goal. In my opinion, such a quiver plots is really much more beautiful!

First an example from the pgfplots manual enter image description here

My "improved" version enter image description here

And the code to reproduce it

\documentclass[border=9,tikz]{standalone} 
\usepackage{pgfplots,filecontents}\pgfplotsset{compat=newest}
\usetikzlibrary{arrows.meta,calc}


\newcommand*{\arrowheadthreeD}[4]{%
  \colorlet{beamcolor}{#1!75!black}
  \colorlet{innercolor}{#1!50}
  \foreach \i in {1, 0.9, ..., 0} {
    \pgfmathsetmacro{\shade}{\i*\i*100}
    \pgfmathsetmacro{\startangle}{90-\i*30}
    \pgfmathsetmacro{\endangle}{90+\i*30}
    \fill[beamcolor!\shade!innercolor,shift={#2},rotate=#3,line width=0,line cap=butt,]%,
      (0,0) -- (\startangle:0.259) arc (\startangle:\endangle:0.259)--cycle;
  }
%  \pgfmathparse{#4}
  \fill[beamcolor,shift={#2},rotate=#3,line width=0,line cap=butt] (60:0.26) arc (60:120:0.26) -- ($(120:0.26)!0.06*1!(0,0.0)$) arc (120:60:{0.26-0.015*1}) -- cycle; % statt *1 *#4???
      %\draw[blue,thick,shift={#2},rotate=#3] (0,0) -- (0,0.25);
}

\newcommand*{\arrowthreeD}[4]{
  %\begin{scope}[shift={([rotate = -#4]#2)}]
    %\begin{scope}[,,transform canvas={rotate=#4},scale=#3,]
    \begin{scope}[scale=#3,]
      \fill [left color=#1!75!black,right color=#1!75!black,middle color=#1!50,join=round,line cap=round,line width=0,draw=none,shading angle=#4+90,,shift={(0,0.25)},rotate=180] (0,0.25) -- (0.05,0.25) -- (0.05,0.175+0.25) arc (0:180:0.05 and 0.05) -- (-0.05,0.25)--cycle;
     % \fill [left color=#1!75!black,right color=#1!75!black,middle color=#1!50,draw=none,shading angle=#4-90] (0,0) -- (0.05,0) -- (0.05,-0.175) -- (-0.05,-0.175) -- (-0.05,0)--cycle;

      \arrowheadthreeD{#1}{(0,0.25)}{180}{#3};
    \end{scope}
  %\end{scope}
} 


\begin{document}

\makeatletter
\def\pgfplotsplothandlerquiver@vis@path#1{%
    % remember (x,y) in a robust way
    #1%
    \pgfmathsetmacro\pgfplots@quiver@x{\pgf@x}\global\let\pgfplots@quiver@x\pgfplots@quiver@x%
    \pgfmathsetmacro\pgfplots@quiver@y{\pgf@y}\global\let\pgfplots@quiver@y\pgfplots@quiver@y%
    % calculate (u,v) in relative coordinate
    \pgfplotsaxisvisphasetransformcoordinate\pgfplots@quiver@u\pgfplots@quiver@v\pgfplots@quiver@w%
    \pgfplotsqpointxy{\pgfplots@quiver@u}{\pgfplots@quiver@v}%
    \pgfmathsetmacro\pgfplots@quiver@u{\pgf@x-\pgfplots@quiver@x}%
    \pgfmathsetmacro\pgfplots@quiver@v{\pgf@y-\pgfplots@quiver@y}%
    \pgfmathparse{atan2(\pgfplots@quiver@v,\pgfplots@quiver@u)-90}
    \pgfmathsetmacro\pgfplots@quiver@a{\pgfmathresult}\global\let\pgfplots@quiver@a\pgfplots@quiver@a%
    % move to (x,y) and start drawing
    {%
        \pgftransformshift{\pgfpoint{\pgfplots@quiver@x}{\pgfplots@quiver@y}}%
        \pgfpathmoveto{\pgfpointorigin}%
        \pgfpathlineto{\pgfpoint\pgfplots@quiver@u\pgfplots@quiver@v}%
    }%
}%

    \begin{tikzpicture}
        \begin{axis}[axis equal image,enlargelimits=false,view={0}{90},domain=-2:2,,xmin=-2.1,xmax=2.1,ymin=-2.1,ymax=2.1]
\addplot3[contour gnuplot={number=9,
labels=false},thick]
{exp(0-x^2-y^2)*x};
            \addplot3[
                colormap/hot2,
           % point meta=x,
           % quiver={
           %     u=x,v=y,
            point meta={sqrt{exp(0-x^2-y^2)*(1-2*x^2)*exp(0-x^2-y^2)*(1-2*x^2)+exp(0-x^2-y^2)*(-2*x*y)*exp(0-x^2-y^2)*(-2*x*y)}},
            quiver={u={exp(0-x^2-y^2)*(1-2*x^2)},
                    v={exp(0-x^2-y^2)*(-2*x*y)},
                every arrow/.append style={%
                    draw=none,%-{Latex[scale length={max(0.1,\pgfplotspointmetatransformed/1000)}]},mapped color
                },
                after arrow/.code={
                    \relax{% always protect the shift
                        \pgftransformshift{\pgfpoint{\pgfplots@quiver@x}{\pgfplots@quiver@y}}%
                        %\node[below right]{\tiny\color{mapped color!50!black}\pgfplotspointmetatransformed};
                        \pgftransformrotate{\pgfplots@quiver@a}%
                        \arrowthreeD{mapped color}{0,0}{sqrt{\pgfplotspointmetatransformed}/62}{\pgfplots@quiver@a}
                    }
                }
            },
            samples=15,
           ] {exp(0-x^2-y^2)*x};
    \end{axis}
\end{tikzpicture}
\end{document}

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.