pgfplots: drawing multiple vectors with corresponding unit vectors

Suppose you have a couple of 3D-vectors given by their start and endpoints. Now you want to define a command that draws one of these vectors together with its respective unit vector from the same origin.

A similar problem has been answered before here - however the solution only works for vectors starting from (0,0,0).

As I struggled to apply the presented \foreach-approach on two given coordinates simultaniously and given the age of the solution, I approached this problem using the calculator-package.

I'm getting a functioning output for a single vector - unfortunately only the last unit vector (called by \vecuvec{1,1,0}{0,2,1}) is getting drawn correctly for multiple executions of \vecuvec as the coordinates (\sola,\solb,\solc) seem to be overwritten by the last execution of \vecuvec.

Is there a practical alternative by for example storing/accessing the coordinates in a different way or changing the scopes within the command \vecuvec?

MWE:

\documentclass{article}
\usepackage{calculator}
\usepackage[]{pgfplots}
\usepackage{tikz-3dplot}
\pgfplotsset{compat=1.15}

% Draw vector and corresponding unitvector
\newcommand{\vecuvec}[2] %start point, end point (of vector)
{   \VECTORSUB(#2)(#1)(\sola,\solb,\solc)
\UNITVECTOR(\sola, \solb, \solc)(\sola,\solb,\solc)
%arrow in blue
\draw[->,thick,blue] (#1) -- (#2);
%corresponding unit-vector in red:
\draw[->, thick,red] (#1) -- ($(#1)+(\sola,\solb,\solc)$);
}

\begin{document}

\begin{tikzpicture}
\begin{axis}[xtick={0,1,...,4}, ytick={0,1,...,4}, ztick={0,1,...,4},
xmin=0,xmax=4,ymin=0,ymax=4, zmin=0,zmax=4]
\vecuvec{3,1,0}{4,2,1};
\vecuvec{2,2,2}{4,3,3};
\vecuvec{1,1,0}{0,2,1}; %only the last one works as intended
\end{axis}
\end{tikzpicture}

\end{document}


Output:

Here for the blue vectors only the leftmost has its unit vector drawn correctly (in red).

• Have you tried reading the docs? (Look for axis direction cs) – Henri Menke Dec 21 '17 at 23:54
• @HenriMenke Perhaps I'm missing something, but how does that help here? – Torbjørn T. Dec 22 '17 at 0:03
• @TorbjørnT. (#1) -- ($(#1)+(\sola,\solb,\solc)$) is a relative coordinate calculation which does not work like this in pgfplots. For relative coordinates you need axis direction cs as explained in the manual. So I guess the correct behaviour would be obtained by (#1) -- ++(axis direction cs:\sola,\solb,\solc) – Henri Menke Dec 22 '17 at 0:05
• @HenriMenke a) No it's not, you're thinking about (#1) -- +(\sola,\solb,\solc), which is a different thing from what the OP is using (calc library syntax). b) The problem here is I, would think, delayed expansion, similar to why you need special care for loops inside an axis. Note that the third of those work fine, and that the other two unit vectors are the same as the third. Remove the third, and the second works fine. – Torbjørn T. Dec 22 '17 at 0:14

The same trick used for \draw macros in loops (see pgfplots manual section 8.1 Utility commands) works here as well it seems, i.e.

    \edef\temp{\noexpand\draw[->, thick,red] (#1) -- ($(#1)+(\sola,\solb,\solc)$);}
\temp


which causes immediate expansion of \sola etc.

\documentclass{article}
\usepackage{calculator}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}

% Draw vector and corresponding unitvector
\newcommand{\vecuvec}[2] %start point, end point (of vector)
{   \VECTORSUB(#2)(#1)(\sola,\solb,\solc)
\UNITVECTOR(\sola, \solb, \solc)(\sola,\solb,\solc)
%arrow in blue
\draw[->,thick,blue] (#1) -- (#2);
%corresponding unit-vector in red:
\edef\temp{\noexpand\draw[->, thick,red] (#1) -- ($(#1)+(\sola,\solb,\solc)$);}
\temp
}

\begin{document}

\begin{tikzpicture}
\begin{axis}[xtick={0,1,...,4}, ytick={0,1,...,4}, ztick={0,1,...,4},
xmin=0,xmax=4,ymin=0,ymax=4, zmin=0,zmax=4]
\vecuvec{3,1,0}{4,2,1};
\vecuvec{2,2,2}{4,3,3};
\vecuvec{1,1,0}{0,2,1};
\end{axis}
\end{tikzpicture}

\end{document}