Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Using pgfplots, I'm trying to create a quiver plot on a hyperboloid surface something like this.

enter image description here

I was able to generate the hyperboloid surface using parametric equations. I could'nt find out how to generate the quiver plot tangent to the surface. Any help would be greatly appreciated.

I'm okay with using any other package like asymptote etc if I can get this working.

The MWE is here

\documentclass[12pt]{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[view={110}{20}, %
      scale = 1.2, y post scale = 1.5,
    xlabel = $x$, ylabel = $y$, zlabel = $z$]
    \addplot3[surf, samples=25, variable = \u, variable y = \v, z buffer = sort,
      y domain = 0:2*pi]({sqrt(1+u^2)*cos(deg(v))}, {u}, {sqrt(1+u^2)*sin(deg(v))}); 
\end{axis}
\end{tikzpicture}
\end{document}

Surface of revolution of y=1/x. quiver plot code.

 \addplot3[surf,domain=1:2, y domain = 0:2*pi, z buffer=sort, samples = 10, quiver = {
      u = {(x+0.01)*cos(deg(y)) - x},
      v = {(x+0.01)*sin(deg(y)) - y},
      w = {1/(x+0.01) - z},
    }
  ]
  ({x*cos(deg(y))}, {x*sin(deg(y))}, {1/x});
share|improve this question

2 Answers 2

up vote 12 down vote accepted

Asymptote is probably better for this, since it allows for hiding the arrows behind the hyperboloid surface, but here's how you can draw the arrows using PGFPlots.

To calculate the tangent vector, you can simply evaluate the y and z values at a location a small distance along the x axis.

\documentclass[12pt]{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[view={110}{20}, %
      scale = 1.2, y post scale = 1.5,
    xlabel = $x$, ylabel = $y$, zlabel = $z$]
    \addplot3[surf, samples=8, variable = \u, variable y = \v, z buffer = sort,
      y domain = 0:2*pi,
      quiver={
        u={(sqrt(1+(u+0.01)^2)*cos(deg(v)))-x},
        v={0.01},
        w={(sqrt(1+(u+0.01)^2)*sin(deg(v)))-z},
        scale arrows=75
      },
      -stealth, thick]
      ({sqrt(1+u^2)*cos(deg(v))},
      {u},
      {sqrt(1+u^2)*sin(deg(v))}); 
\end{axis}
\end{tikzpicture}
\end{document}

This approach works for other functions as well. You need to make sure to explicitly assign the independent variables of your parametric plot variable names other than x and y, however, otherwise it's not clear whether x refers to the independent variable or to the x coordinate:

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[view={110}{20}, %
      scale = 1.2, y post scale = 1.5,
    xlabel = $x$, ylabel = $y$, zlabel = $z$]
 \addplot3[surf,domain=1:2, y domain = 0:2*pi, z buffer=sort, samples = 5, samples y=10,
  variable = \s, variable y=\t,
    quiver = {
      u = {(s+0.01)*cos(deg(t)) - x},
      v = {(s+0.01)*sin(deg(t)) - y},
      w = {1/(s+0.01) - z},
      scale arrows=15
    },
    -stealth, thick
  ]
  ({s*cos(deg(t))}, {s*sin(deg(t))}, {1/s});
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this answer
    
Worked like charm. –  Surya Nov 25 '13 at 12:38
    
Is this general method of creating quiver plots ? I tried the same logic (u+0.01) with surface of revolution of 1/x and I got some pretty weird lines. I've updated my original question with the new input. –  Surya Nov 26 '13 at 7:29
    
@Surya: Yes, that's a general method. You need to make sure to assign variable names for your independent variables that aren't x and y. I've edited my answer. –  Jake Nov 26 '13 at 7:49
    
Okay. That was the mistake then. Thanks. –  Surya Nov 26 '13 at 8:11

Here's an answer using Asymptote:

enter image description here

The code:

\documentclass[margin=10pt]{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}
settings.render=4;
settings.prc=false;

size3(8cm);
defaultpen(fontsize(10pt));

import graph3;
currentprojection=orthographic(5,2,3);

real ymax = 3;
real ymin = -ymax;
real h(real y) {
  return sqrt(1 + (y/2)^2);
}
path hyperbola = graph(h, ymin, ymax, operator ..);
path3 hyperbola3 = path3(hyperbola, plane=YZplane);
surface hyperboloid = surface(hyperbola3, c=O, axis=Y);

real umax = hyperboloid.index.length - .001;
real vmax = hyperboloid.index[0].length - .001;

/* Parametrize by the square [0,2pi] x [ymin,ymax] */
triple point(real theta, real y) {
  return hyperboloid.point(theta/(2pi) * umax, (y-ymin)/(ymax-ymin) * vmax);
}
triple normal(real theta, real y) {
  return hyperboloid.normal(theta/(2pi) * umax, (y-ymin)/(ymax-ymin) * vmax);
}

int n = 10;
int m = 10;
real shrinkfactor=0.8;
for (int i = 0; i < n; ++i) {
  real theta = i/n*2pi;
  triple f(real t) {
    return point(theta, t);
  }
  for (int j = 0; j < m; ++j) {
    real ylow = j/m*(ymax-ymin) + ymin;
    real yhigh = ylow + shrinkfactor*(ymax-ymin)/m;
    path3 arrowpath = graph(f, ylow, yhigh, n=10, operator..);
    draw(arrowpath, arrow=Arrow3(TeXHead2(normal=normal(theta,yhigh))));
  }
}

draw(hyperboloid, surfacepen=emissive(white));

pen extraspen = linewidth(0.2);
draw(Circle(c=ymax*Y, r=h(ymax), normal=Y), extraspen);
draw(Circle(c=ymin*Y, r=h(ymin), normal=-Y), extraspen);

scale(true);

xaxis3("$x$", Bounds, InTicks, p=extraspen);
yaxis3("$y$", Bounds, InTicks, p=extraspen);
zaxis3("$z$", Bounds, InTicks, p=extraspen);
\end{asy}
\end{document}
share|improve this answer
    
Wow.. the image looks very nice. I've to read asymptote docs to understand the code. Nice to have another option. Thx –  Surya Dec 5 '13 at 15:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.