If you have octave
installed, you can triangulate the data from within your LaTeX document using the \addplot shell
functionality and plot it using the patch
plot style.
\documentclass[border= 5mm]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot3 [patch, patch table={triangles.txt}
] shell {echo "data=dlmread('data.txt');
tri=delaunay(data(:,1), data(:,2));
dlmwrite('triangles.txt',tri-1,' ');
disp(data)" | octave --silent};
\end{axis}
\end{tikzpicture}
\end{document}
You can also grid the data:
\documentclass[border= 5mm]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot3 [surf, mesh/cols=50, z buffer=sort, restrict z to domain=0:inf, shader=faceted interp] shell {
echo "
data=dlmread('data.txt');
res=\pgfkeysvalueof{/pgfplots/mesh/cols};
[xx,yy] = meshgrid(linspace(min(data(:,1)), max(data(:,1)),res), linspace(min(data(:,2)), max(data(:,2)),res));
zz=griddata(data(:,1),data(:,2),data(:,3),xx,yy);
zz(isnan(zz))=-999;
disp([xx(:) yy(:) zz(:)])
" | octave --silent};
\addplot3 [only marks] file {data.txt};
\end{axis}
\end{tikzpicture}
\end{document}
Gnuplot could be used to interpolate scattered data, but the available interpolation functions don't work particularly well for this dataset.
\documentclass[border= 5mm]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot3 [surf] gnuplot [raw gnuplot] {
set dgrid3d 30,30 spline;
splot 'data.txt';
};
\addplot3 [only marks] table {data.txt};
\end{axis}
\end{tikzpicture}
\end{document}
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}
Best Answer
You can use the
pgfplots
package at will. Please check the manual for lots of other possibilities such as view angle, shader types etc.