# tikz/pgfplots - Plotting 3D surface with sphere

I am trying to solve the following problem: First I would like to produce a surface plot of a function of two variables (in this particular case this surface has a saddle shape). Then I would like to draw a sphere in the same plot in such a way that the sphere is tangent to the surface at a point that can be specified freely. Achieving the first part was not a problem. For the second part, I have so far been able to place something that at least resembles a sphere somewhere in the plot (see below). However, specifying the position of where to put the sphere seems to be done not in relation to the axes that I am plotting in, but some other reference point (so (0,0) does not put the sphere at the origin of the axes).

Has someone got a suggestion for the following questions:
1) How do I make the bounding line of the ball thinner?
2) To make it look like an actual sphere, how could I add grid lines (like longitude and latitude) that are correctly projected?
3) How do I specify the position relative to the axes?

To achieve my actual goal:
4) In order to make the sphere with a given radius tangent at a user-specified point, I guess I have to calculate the position in the axes coordinate system via some external program (python ideally). How do I get that information into LateX?
5) Is there a way to do all this in python alone and get a vector graphic out that looks as great as what you get with tikz?

Sorry for the long post, but answers to at least 1-3 would be much appreciated.

\documentclass{standalone}

\usepackage{amsmath}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}
surf,
samples=25,
domain=-4:4,
y domain=-4:4
] {x^2-y^2};
\end{axis}
\end{tikzpicture}
\end{document}


• Are you aware of asymptote? And what do you mean by "position relative to the axes"? – user121799 Apr 17 '18 at 13:21

I'd recommend asymptote for this. All one has to do is to move to some point on the surface (with coordinates myx and myy in the code below) and then go radius units along the normal of that surface, and to draw a sphere there. (With improved(?) output.)

\documentclass[border=3.14pt]{standalone}
\usepackage{asypictureB}
\begin{document}
\begin{asypicture}{name=AsyPlot}
import three;
import graph3;
import grid3;
import palette;
import solids;
unitsize(1cm);
settings.outformat="pdf";
defaultrender.merge=true;
size(12cm,IgnoreAspect);
currentprojection=perspective(4,-6,4);
real f(pair z) {return 0.1*(z.x^2-z.y^2);}
triple normalf(pair z) {
static real dx=sqrtEpsilon, dy=dx;
return (-(f((z.x+dx,z.y))-f((z.x-dx,z.y)))/2dx,
-(f((z.x,z.y+dy))-f((z.x,z.y-dy)))/2dy,
1);
}
real r1=0.5, myx=-1.0, myy=-2.0; // x-y location of the sphere and radius
triple v1=(myx,myy,f((myx,myy)))+r1*normalf((myx,myy));
triple fs(pair t){ //parametrization of a shifted sphere
return v1+r1*(cos(t.x)*sin(t.y),sin(t.x)*sin(t.y),cos(t.y));
}
surface s1=surface(fs,(0,0),(2pi,pi),8,Spline);
surface s=surface(f,(-4,-4),(4,4),Spline);
xaxis3(XYZero(extend=true),red,Arrow3);
yaxis3(XYZero(extend=true),red,Arrow3);
zaxis3(XYZero(extend=true),red,Arrow3);
s.colors(palette(s.map(abs),Wheel()));
draw(s,render(compression=Low,merge=true));
draw(s1
,gray+opacity(0.25)
,render(merge=true), meshpen=0.6*white
);
\end{asypicture}
\end{document}


Just for fun: an animated version, almost impossible to do with pgfplots IMHO.

You can also use pgfplots, but ultimately you will always be limited by the fact that this has no true 3D engine. To make the line thinner, you can adjust line width. To place the sphere in the coordinate system, use axis cs:. (The problem, though, is that the radius does not get translated.) You can draw circles in the plot, the problem is to project on the visible parts. There are ways to achieve this, yet it will not be too easy to marry them to pgfplots. This has to do with the fact that there all sorts of rotated scopes are used, which interfere with the coordinate transformations made by pgfplots.

\documentclass{standalone}

\usepackage{amsmath}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}
surf,
samples=25,
domain=-4:4,
y domain=-4:4
] {x^2-y^2};
\filldraw[ball color=white,line width=0.1pt] (axis

• @Quantum I don't think that asymptote supports vector graphics for 3D output at this point (but I may be wrong). But the output is my fault, if you use size(600); instead of size(400,0);, the picture will look much better. (I didn't pay attention to this.) – user121799 Apr 17 '18 at 18:26