2

I feel that there should be a simple, good way to plot a 3d surface and place a vector (or more) at one point on it, where the vector is a function of the point and the surface. For example, a normal vector.

I can of course compute the corrdinates and input those as a draw, but that doesn't seem to be the efficient way to do it. I'm looking for something like this:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}[
]
\begin{axis}[
xlabel=$x$, ylabel=$y$,
domain=0:2,
domain y=-1.3:1.3,
]
\addplot3[
surf,
shader=interp,
] 
{exp(-x^2-y^2)*x};
\addplot3[
black,-stealth,samples=2,
quiver,quiver/.cd,
    u=-exp(-x^2-y^2)+2*exp(-x^2-y^2)*x^2,v=2*exp(-x^2-y^2)*x*y,w=1,
    scale arrows=0.2,
] {exp(-x^2-y^2)*x};
\addplot3[
blue,-stealth,samples=2,
quiver,quiver/.cd,
    u=2*exp(-x^2-y^2)*x*y,v=exp(-x^2-y^2)-2*exp(-x^2-y^2)*x^2,w=0,
    scale arrows=5.8,
] {exp(-x^2-y^2)*x};
\end{axis}
\end{tikzpicture}
\end{document}

Result

Only I want to control the exact points at which the vectors are placed (say, x=1 and y=0, and have pgfplots compute the corresponding z coordinate and the vector etc.).

YMA
  • 195
  • Could you perhaps explain why you think your quivers will provide the tangents and normals? Superficially at least the top left combination does not really seem to display a tangent and normal. And it is always a good idea to promote the code to a full MWE, i.e. something that starts with \dcoumentclass and ends with \end{document}. –  Oct 13 '18 at 14:41
  • @marmot Thank you for the suggestion, done. Regarding the math, I think it's fine but regardless, say I want whatever vector my formula yields (that depends on the point etc.). How would I achieve that? – YMA Oct 13 '18 at 14:47

1 Answers1

2

What I can do is to tell you how you can draw single quiver arrows at a predefined position. This can be done using a table. However, I am not convinced that these are tangents and normals of the surface. Apart from the fact that a two-dimensional surface has a two-dimensional tangent space (meaning that there is not a single tangent), the information of the value of the function is missing. To me the output of the below code is just the two tangents at the curves defined by x=0 or y=0, respectively, but attached at z=0 rather than z=f(x,y). (It might well be that I introduced a sign error. I will be happy to expand this further. IMHO there are two well-defined arrow-like objects that one could plot: gradient and normal. Are you secretly looking for those?) It also makes sense to use declare function if one is to deal with lengthy expressions that one wants to use multiple times.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{tikzpicture}[declare function={f(\x,\y)=exp(-\x*\x-\y*\y)*\x;
dfdx(\x,\y)=exp(-\x*\x-\y*\y)-2*exp(-\x*\x-\y*\y)*\x^2;
dfdy(\x,\y)=-2*exp(-\x*\x-\y*\y)*\x*\y;}]
\begin{axis}[
xlabel=$x$, ylabel=$y$,
domain=0:2,
domain y=-1.3:1.3,
]
\addplot3[
surf,
shader=interp,
] 
{f(x,y)};

\addplot3 [color=blue,-stealth,
    quiver={u={-dfdx(\thisrow{x},\thisrow{y})},v={-dfdy(\thisrow{x},\thisrow{y})},
    w=1,scale arrows=0.2},
    ] table {
x y z
1 0 0
0.7 0.2 0
    };

\addplot3 [color=blue,-stealth,
    quiver={u={-dfdy(\thisrow{x},\thisrow{y})},v={dfdx(\thisrow{x},\thisrow{y})},
    w=0,scale arrows=2},
    ] table {
x y z
1 0 0
0.7 0.2 0
    };
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

As for the question in the comment: you can add the z coordinate. One possibility is

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{tikzpicture}[declare function={f(\x,\y)=exp(-\x*\x-\y*\y)*\x;
dfdx(\x,\y)=exp(-\x*\x-\y*\y)-2*exp(-\x*\x-\y*\y)*\x^2;
dfdy(\x,\y)=-2*exp(-\x*\x-\y*\y)*\x*\y;}]
\pgfmathsetmacro{\fone}{f(1,0)}
\pgfmathsetmacro{\ftwo}{f(0.7,0.2)}
\begin{axis}[
xlabel=$x$, ylabel=$y$,
domain=0:2,
domain y=-1.3:1.3,
]
\addplot3[
surf,
shader=interp,
] 
{f(x,y)};

\addplot3 [color=blue,-stealth,
    quiver={u={-dfdx(\thisrow{x},\thisrow{y})},v={-dfdy(\thisrow{x},\thisrow{y})},
    w=1,scale arrows=0.2}, % ,z={f(\thisrow{x},\thisrow{y})}
    ] table {
x y z
1 0 \fone
0.7 0.2 \ftwo
    };

\addplot3 [color=blue,-stealth,
    quiver={u={-dfdy(\thisrow{x},\thisrow{y})},v={dfdx(\thisrow{x},\thisrow{y})},
    w=0,scale arrows=2},
    ] table {
x y z
1 0 \fone
0.7 0.2 \ftwo
    };
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

I guess that there must be a simpler way to add the z coordinate. But I am still not sure that I know what I am doing here. I would be much more enthusiastic if I knew what you really want to plot. One can draw tangents of parametric curves in x and y directions, and their vector product yields the normal. So far, we add w by hand, but we could just calculate it, can't one?

  • Looks great. Is there a way that I can control the base point of the vectors in a way that depends on x, y and z (say, place them at the height of the surface)? – YMA Oct 14 '18 at 04:52
  • @YMA I added a possible way plus some comment what I would do to compute the tangents (plural) and normal vector. –  Oct 14 '18 at 08:33
  • Better. Regarding what I want to do: forget the second, tangent vector. Say I'm just looking to plot a normal (specifically, (-\grad f,1)). Thanks a lot for the help and patience. – YMA Oct 14 '18 at 08:42