Plotting a 3d surface in tikz, with a limit to the infinity

I want to plot the function 1/(x²+y²), but since it tends to infinity in (0,0), I get a horrible plot:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[grid=both]
\addplot3 [surf] {1 / (x^2 + y^2)};
\end{axis}
\end{tikzpicture}
\end{document}


By restricting the domain of z, I get anyway a not so nice plot:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[grid=both,restrict z to domain=0:1]
\addplot3 [surf] {1 / (x^2 + y^2)};
\end{axis}
\end{tikzpicture}
\end{document}


I would like to get something smooth, which finish in a circle (the circle of the intersection of this function with the plane z=1 for example).

Something like this would be great:

• For that I think you need a different parametrization of the surface. Otherwise you will get that sampling behavior. – percusse Oct 10 '16 at 20:41
• But there may be a way to intersect this surface with the plane z=1, and "hide" what is above it, or something like that... – Alejandro DC Oct 10 '16 at 20:52
• That's not how meshing is performed. – percusse Oct 10 '16 at 21:42
• You also need to set zmax to a value less than that used by [restrict z to domain]. The way it works, the plot is clipped at zmax, but you need additional points outside the plot to interpolate the edges. – John Kormylo Oct 11 '16 at 14:35
• That is a really good tip. I am trying, but I am not sure how to add the additional points outside the plot, because the zmax goes in the option of the axis, not of the addplot3, and hence, anything I add outside that limit, will be clipped out. – Alejandro DC Oct 11 '16 at 14:55

After hours (at least one) of trying to make what is written in the first plot, I thought of polar coordinates. It works.

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}[width=\textwidth,
axis equal,
xmin=-0.1,xmax=5,ymin=-0.5,ymax=3,zmin=-0.4,zmax=7,
xtick=\empty,ytick=\empty,ztick=\empty,
axis lines=center]

({x*cos(y)+3}, {x*sin(y)+2}, {1/(x^2)});
\end{axis}
\end{tikzpicture}
\end{document}


• Fantastic, that's a great approach. Thanks for posting, and welcome to the site! – Jake Nov 30 '16 at 16:53

pgfplots supports the "starred" version restrict z to domain* which clips all bigger values into the prescribed domain. The result is a closed cap on top:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}

\begin{document}
\begin{tikzpicture}
\begin{axis}[grid=both,restrict z to domain*=0:10]
domain=-2:2,miter limit=1] {1 / (x^2 + y^2)};
\end{axis}
\end{tikzpicture}
\end{document}


Here is the same with 71 samples:

Here's a possibility using the sagetex package and a (free) SagemathCloud account giving you access to a computer algebra system Sage for your LaTeX document. The idea is to generate the data points and for "large" z-values redefine the point to be the maximum z-value on the graph.

\documentclass[11pt,border={10pt 10pt 10pt 10pt}]{standalone}
\usepackage{pgfplots}
\usepackage{sagetex}
\begin{document}
\begin{sagesilent}
x = var('x')
y = var('y')
step = .10
x1 = -2
x2 = 2
y1 = -2
y2 = 2
output = ""
output += r"\begin{tikzpicture}[scale=1.0]"
output += r"\begin{axis}[xmin=%d, xmax=%d, ymin=%d, ymax=%d]"%(x1,x2,y1,y2-step)
# rows is the number of y values
for y in srange(y1,y2,step):
for x in srange(x1,x2,step):
if (1/(x^2+y^2))<10:
output += r"(%f, %f, %f) "%(x,y,1/(x^2+y^2))
else:
output += r"(%f, %f, %f) "%(x,y,10)
output += r"};"
output += r"\end{axis}"
output += r"\end{tikzpicture}"
\end{sagesilent}
\sagestr{output}
\end{document}


Running in SagemathCloud you get this output:

If you don't mind MetaPost output, the Function Grapher can easily do something similar :