Both contour and 3d plots can be done easily in pgfplots, but I have a hard time combining them nicely.
Here's an example of what I'd like to achieve (from the matplotlib examples):
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityBoth contour and 3d plots can be done easily in pgfplots, but I have a hard time combining them nicely.
Here's an example of what I'd like to achieve (from the matplotlib examples):
Pgfplots can compute the z contours by means of gnuplot and its contour gnuplot
interface.
The projection onto the x axis (i.e. with fixed y) can be done by means of a matrix line plot in which you replace the y coordinate of the input matrix by some fixed constant.
The projection onto the y axis (i.e. with fixed x) is more involved (at least if mesh/ordering=x varies
as in my example below) because one needs to transpose the input matrix. In my example below, I simply replaced the meaning of x and y to achieve the transposal. This, of course, would be more involved for a data matrix (and I think that pgfplots has no builtin to do it).
Here is what I got so far:
\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
domain=-2:2,
domain y=0:2*pi,
]
\newcommand\expr[2]{exp(-#1^2) * sin(deg(#2))}
\addplot3[
contour gnuplot={
% cdata should not be affected by z filter:
output point meta=rawz,
number=10,
labels=false,
},
samples=41,
z filter/.code=\def\pgfmathresult{-1.6},
]
{\expr{x}{y}};
\addplot3[
samples=41,
samples y=10,
domain=0:2*pi,
domain y=-2:2,
% we want 1d (!) individually colored mesh segments:
mesh, patch type=line,
x filter/.code=\def\pgfmathresult{-2.5},
]
(y,x,{\expr{y}{x}});
\addplot3[
samples=41,
samples y=10,
% we want 1d (!) individually colored mesh segments:
mesh, patch type=line,
y filter/.code=\def\pgfmathresult{8},
]
{\expr{x}{y}};
\addplot3[surf,samples=25]
{\expr{x}{y}};
\end{axis}
\end{tikzpicture}
\end{document}
As you see, the first contour is the z contour. It is computed using gnuplot (and requires the -shell-escape
mechanism to this end!).
The x and y projections are computed using the same matrix of function values. I chose a different sampling density to control how many "contour lines" shall be drawn. Note that these lines are conceptionally different from the z contours: they are already part of the sampling procedure and do not need to be computed externally. Note that I used mesh, patch type=line
to tell pgfplots that (a) it should use individually colored segments and (b) it should not color the 2d structure, just the lines in scanline order (which is mesh/ordering=x varies
in my case).
plot3
to also make the side projections. (I can't compete with the master.) @ChristianFeuersanger: Do you plan to bring native contour plots to pgfplots
or is it beyond the scope? If so, what algorithm would you use to implement it?
splot ... using 1:3:2
or something like that. I will think about a suitable pgfplots option.
Dec 22, 2012 at 7:29
contour dir=x|y|z
). It is currently part of the unstable (cf pgfplots.sourceforge.net).
Dec 29, 2012 at 9:53
pgfplot
supports contour plots by using the external-gnuplot
. The side curves are obtained by two parametric curves. You can combine the 4 plots by putting all of them inside the axis
environment.
The code is redundant, specially because the function in gnuplot
(which does the contour) can not be passed from the tex code, as far as I know.
The result is the following:
The code follows:
\documentclass{scrartcl}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[domain=-5:5]
\addplot3[domain=-5:5,samples=80,samples y=0,mark=none,black, opacity=0.5,thick]({x},{6.},{exp(-x*x - 0*0 + x*0. + 0.)});
\addplot3[domain=-5:5,samples=80,samples y=0,mark=none,black, opacity=0.5,thick]({-6.},{x},{exp(-0*0 - x*x + 0.*x + x)});
\addplot3 +[no markers,
raw gnuplot,
mesh=false,
z filter/.code={\def\pgfmathresult{-2}}
] gnuplot {
set contour base;
set cntrparam levels 20;
unset surface;
set view map;
set isosamples 500;
set samples 100;
splot [-5:5][-5:5][0:1] exp(-x*x-y*y + x*y + y);
};
\end{axis}
\addplot3[surf,opacity=0.5,samples=40] {exp(-x*x-y*y + x*y + y)};
\end{tikzpicture}
\end{document}
\addplot3
at the end of all \addplot3
s? The surf
plot is always on top? Nonetheless opacity
should be included anyway to show hidden contour lines.
Dec 20, 2012 at 4:46
opacity
simply because that is what is shown in the example of the question. Admittedly the OP probably wants a fully automatic solution, but I don't know how to do that, I mention that in the new answer.
here is a solution with pst-solides3d
for the function z=sin(x)*sin(y), which can be adopted to your function.
\documentclass[12pt]{article}
\usepackage{pst-solides3d}
\pagestyle{empty}
\begin{document}
\psset{arrowlength=3,arrowinset=0,viewpoint=50 30 20 rtp2xyz,Decran=50,
lightsrc=viewpoint}
\begin{pspicture}(-7,-8)(7,8)
\axesIIID[linecolor=gray](0,0,0)(7,7,7)
\psSolid[ngrid=.3 .3,object=grille,base=1 8 1 8,
linewidth=0.4pt,linecolor=gray!50,action=draw]%
{\psset{object=courbe,r=0,linecolor=blue,resolution=360,function=Fxy}
\multido{\rA=0.0+1.0}{8}{%
\defFunction[algebraic]{Fxy}(x){x}{0}{sin(x)*sin(\rA)+3}
\psSolid[range=1 8]}
\multido{\rA=0.0+1.0}{8}{%
\defFunction[algebraic]{Fxy}(y){0}{y}{sin(\rA)*sin(y)+3}
\psSolid[range=1 8]}}
\psSurface[ngrid=.3 .3,fillcolor=green!30,incolor=gray!30,
linewidth=0.4pt,algebraic](1,1)(8,8){ sin(x)*sin(y) +3 }
\end{pspicture}
\end{document}
and the same for a more complicated funktion: