# plot 3d graphs of functions defined implicitly

How can I plot 3d graphs of functions defined implicitly (quadratic forms, for Linear Algebra course notes -- I'd like to include lots of examples)? As far as I can see it is not possible with pgfplots and not through gnuplot either. Is there any package that will help with that?

For example, parabolic and hyperbolic cylinders, hyperboloids, ellipsoids, etc. Concrete examples:

2xy + 2xz = 1 (hyperbolic cylinder)

(x^2)/(2^2) + (y^2)/(3^2) + (z^2)/(2^2) = 1 (ellipsoid)

I also see that Maxima can do this:

(%11) hc:2*x*y+2*x*z=2;
(%i2) draw3d(enhanced3d=true,implicit(hc,x,-5,5,y,-5,5,z,-5,5));

This will work fine (the hyperbolic cylinder is correctly plotted on the screen), but I don't know what backend Maxima uses for this, and I'd like to use a plain LaTeX method, or something that could be called from LaTeX, as I may have to send the document for others to compile themselves on different environments.

• please give an example with the function that doesn't work. Oct 23, 2013 at 14:54
• Well, it's not that there is a function that doesn't work, but rather that there doesn't seem to be any package that will plot functions defined implicitly. I'll add one example function to the description.
– Jay
Oct 23, 2013 at 14:57
• If available, Maxima uses gnuplot to plot graphics. To plot implicit functions with gnuplot see this FAQ, this not-so-FAQ and also the related questions Plotting an implicit function using pgfplots Oct 23, 2013 at 16:07
• Yes -- I have seen the question about implicit functions with pgfplots, but that's for 2d only. Implicit functions of two variables (that is, defined using three variables) are a bit trickier. So far I have been parameterizing them (I tell Maxima to solve the equation for z, then use the result), but that's not a perfect solution...)
– Jay
Oct 23, 2013 at 16:11
• I see. With gnuplot I fear it's impossible to directly plot such functions because you can't plot them in 4d and project onto 3d. I think you can only solve the equation numerically, and plot the result stored in a text file. This is what Maxima does, all in all (in your home directory Maxima should leave the gnuplot script used to create the last plot). Oct 23, 2013 at 16:22

Asymptote contour3 package draws 3D surfaces described as the null space of real-valued functions of (x, y, z). Note that the images here are rendered into raster format (png).

% impsurf.tex :
%
\documentclass[10pt,a4paper]{article}
\usepackage{lmodern}
\usepackage{subcaption}
\usepackage[inline]{asymptote}
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
\begin{asydef}
settings.outformat="png";
settings.render=8;
import graph3;
import contour3;
currentlight=light(gray(0.8),ambient=gray(0.1),specular=gray(0.7),
specularfactor=3,viewport=true,dir(42,48));
pen bpen=rgb(0.75, 0.7, 0.1);
material m=material(diffusepen=0.7bpen
,ambientpen=bpen,emissivepen=0.3*bpen,specularpen=0.999white,shininess=1.0);
\end{asydef}

%
\begin{document}
%
\begin{figure}
\captionsetup[subfigure]{justification=centering}
\centering
\begin{subfigure}{0.49\textwidth}
\begin{asy}
size(200,0);
currentprojection=orthographic(camera=(9,10,4),up=Z,target=O,zoom=1);

// ellipsoid
real f(real x, real y, real z) {return (x^2)/(2^2) + (y^2)/(3^2) + (z^2)/(2^2)-1;}

draw(surface(contour3(f,(-3,-3,-3),(3,3,3),32)),m
,render(compression=Low,merge=true));

xaxis3(Label("$x$",1),-4,4,red);
yaxis3(Label("$y$",1),-4,4,red);
zaxis3(Label("$z$",1),-4,4,red);

\end{asy}
%
\caption{$(\frac{x}{2})^2+(\frac{y}{3})^2+(\frac{z}{2})^2= 1$ (ellipsoid)}
\label{fig:1a}
\end{subfigure}
%
\begin{subfigure}{0.49\textwidth}
\begin{asy}
size(200,0);
currentprojection=orthographic(camera=(9,4,4),up=Z,target=O,zoom=1);

// hyperbolic cylinder
real f(real x, real y, real z) {return 2*x*y + 2*x*z-1;}

draw(surface(contour3(f,(-3,-3,-3),(3,3,3),32)),m
,render(compression=Low,merge=true));

xaxis3(Label("$x$",1),-4,4,red);
yaxis3(Label("$y$",1),-4,4,red);
zaxis3(Label("$z$",1),-4,4,red);
\end{asy}
%
\caption{$2xy + 2xz = 1$ (hyperbolic cylinder)}
\label{fig:1b}
\end{subfigure}
\caption{}
\label{fig:1}
\end{figure}
%
\end{document}
%
% Process:
%
% pdflatex impsurf.tex
% asy impsurf-*.asy
% pdflatex impsurf.tex

An example for the hyperbolic cylinder:

\documentclass[pstricks]{standalone}
\usepackage{pst-solides3d,pst-math}
\begin{document}

\begin{pspicture}(-4,-4)(4,4)% the main 2D area
\psset{lightsrc=viewpoint,viewpoint=50 -200 20 rtp2xyz,Decran=30}
\pstVerb{/constA 1 def /constB 1 def }
\defFunction[algebraic]{hcyl0}(u,v)
{ constA*SINH(u) }%                               x=f(u)
{ constB*COSH(u) }%                               y=f(u)
{ v }        %                               z=f(v)
\defFunction[algebraic]{hcyl1}(u,v)
{ constA*SINH(u) }%                               x=f(u)
{ -constB*COSH(u) }%                               y=f(u)
{ v }        %                               z=f(v)
\psSolid[object=surfaceparametree,base=-2 2 -3 3,
fillcolor=red!40,function=hcyl0,linewidth=0.1\pslinewidth,ngrid=25]
\psSolid[object=surfaceparametree,base=-2 2 -3 3,
fillcolor=red!40,function=hcyl1,linewidth=0.1\pslinewidth,ngrid=25]
\gridIIID[Zmin=-3,Zmax=3](-4,4)(-4,4)
\end{pspicture}

\end{document}

• +1 but you've parametrized the surfaces... the OP asked about implicit curves Oct 23, 2013 at 20:26
• implicit curves make only sense when they cannot be converted into another type.
– user2478
Oct 23, 2013 at 20:28
• Plotting implicit curves and surfaces is not so efficient in PSTricks as the current implementation does not use the most optimal algorithm. Oct 24, 2013 at 4:14
• Herbert: Implicit surfaces can also make sense when it is important to be able to change the (3d) bounding box easily. Additionally, it's easier to compute the intersection of a parametrized surface with an implicit surface than with another parametrized surface. Oct 24, 2013 at 23:15

This answer is based on g.kov's excellent answer, but uses the relatively new smoothcontour3 module to produce a nicer-looking surface. The smoothcontour3 module has been incorporated into Asymptote version 2.33 (released 11 May 2015, just a little too late for the Tex Live 2015 cutoff), so if you have that version or later, you should not need to download the module. However, if you have an earlier version of Asymptote (for instance, the version incorporated into TeX Live 2015), you need to download the module from the line above or from the asymptote base code and put it in the same directory as the file you want to compile.

The code (again, heavily based on g.kov's code):

% impsurfsmooth.tex :
%
\documentclass[10pt,a4paper]{article}
\usepackage{lmodern}
\usepackage{subcaption}
\usepackage{asypictureB}
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
settings.outformat="png";
settings.render=8;
import graph3;
import smoothcontour3;

pen bpen = rgb(0.75, 0.7, 0.1);
material m = material(diffusepen=0.7bpen, ambientpen=bpen, emissivepen=0.3*bpen,
specularpen=0.999white, shininess=1.0);

%
\begin{document}
%
\begin{figure}
\captionsetup[subfigure]{justification=centering}
\centering
\begin{subfigure}[b]{0.49\textwidth}
\begin{asypicture}{name=ellipsoid}
size(200,0);
currentprojection = orthographic(9,10,4);

// ellipsoid
real f(real x, real y, real z) {
return (x^2)/(2^2) + (y^2)/(3^2) + (z^2)/(2^2) - 1;
}

draw(implicitsurface(f, (-3,-3,-3), (3,3,3), overlapedges=true), surfacepen=m);

xaxis3(Label("$x$",1),-4,4,red);
yaxis3(Label("$y$",1),-4,4,red);
zaxis3(Label("$z$",1),-4,4,red);

\end{asypicture}
%
\caption{$(\frac{x}{2})^2+(\frac{y}{3})^2+(\frac{z}{2})^2= 1$ (ellipsoid)}
\label{fig:1a}
\end{subfigure}
%
\begin{subfigure}[b]{0.49\textwidth}
\begin{asypicture}{name=hyperboliccylinder}
size(200,0);
currentprojection=orthographic(9,4,4);

// hyperbolic cylinder
real f(real x, real y, real z) {
return 2*x*y + 2*x*z - 1;
}

draw(implicitsurface(f, (-3,-3,-3), (3,3,3), overlapedges=true), surfacepen=m);

xaxis3(Label("$x$",1),-4,4,red);
yaxis3(Label("$y$",1),-4,4,red);
zaxis3(Label("$z$",1),-4,4,red);
\end{asypicture}
%
\caption{$2xy + 2xz = 1$ (hyperbolic cylinder)}
\label{fig:1b}
\end{subfigure}
\caption{}
\label{fig:1}
\end{figure}
%
\end{document}
%
% Process:
%
% pdflatex --shell-escape impsurfsmooth.tex