# TikZ: shading a ball with colors

I am interested in plotting a ball similar to the ones below:

where the color of the surface of the ball depends on the distance from a chosen point (where the vector arrow points to). How can I achieve the coloring? I have checked several resources regarding shading, but since TikZ seems to treat a 3D ball like a 2D object I find it hard to achieve an effect like this.

I am currently using this code from TikZ Examples to draw my sphere, but I would appreciate any recommendations for a better method that would allow for shading like that.

• All I could see is that the sphere goes from red to blue. But how fast is it? Perhaps this would give you some idea. – Symbol 1 Nov 26 '15 at 16:46
• @Symbol1 It doesn't really matter as long as it's some sort of a gradient. Your link does look useful but the comments say that this way of shading doesn't work in many PDF readers which could be problematic. Thanks anyway! – sps Nov 26 '15 at 16:57

With pgfplots, the keyword you're looking for is point meta: you can specify a formula, according to it's value the point on the sphere is colored:

## Code

\documentclass[tikz, border=2mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}
\pgfmathsetmacro{\R}{5}
% Point components
\pgfmathsetmacro{\Px}{4}
\pgfmathsetmacro{\Py}{-1}
\pgfmathsetmacro{\Pz}{3}

\begin{tikzpicture}
\begin{axis}
[   view={45}{20},
unit vector ratio=1 1 1,
[   domain=0:180,
y domain=0:360,
surf,
z buffer=sort,
% Your distance formula goes here
point meta={sqrt(pow(x-\Px,2)+pow(y-\Py,2)+pow(z-\Pz,2))},
colormap/jet,
]
({\R*sin(x)*cos(y)},
{\R*sin(x)*sin(y)},
{\R*cos(x)});

\draw[-latex] (-\R,0,0) -- (\R,0,0);
\draw[-latex] (0,-\R,0) -- (0,\R,0);
\draw[-latex] (0,0,-\R) -- (0,0,\R);

\draw[-latex, very thick] (0,0,0) -- (\Px,\Py,\Pz);
\end{axis}
\end{tikzpicture}

\end{document}


## Output

Edit 1: If you want to keep the coordinate grid, there's a shader type faceted interp for that:

## Code

\documentclass[tikz, border=2mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}
\pgfmathsetmacro{\R}{5}
% Point components
\pgfmathsetmacro{\Px}{4}
\pgfmathsetmacro{\Py}{-1}
\pgfmathsetmacro{\Pz}{3}

\begin{tikzpicture}
\begin{axis}
[   view={45}{20},
unit vector ratio=1 1 1,
]   %\draw[-latex] (0,0,0) -- (\Px,\Py,\Pz);
[   domain=0:180,
y domain=0:360,
surf,
z buffer=sort,
point meta={sqrt(pow(x-\Px,2)+pow(y-\Py,2)+pow(z-\Pz,2))},
%opacity=0.95,
colormap/jet,
samples=30,
samples y=60,
]
({\R*sin(x)*cos(y)},
{\R*sin(x)*sin(y)},
{\R*cos(x)});

\draw[-latex] (-\R,0,0) -- (\R,0,0);
\draw[-latex] (0,-\R,0) -- (0,\R,0);
\draw[-latex] (0,0,-\R) -- (0,0,\R);

\draw[-latex, very thick] (0,0,0) -- (\Px,\Py,\Pz);
\end{axis}
\end{tikzpicture}

\end{document}


## Output

• Great answer, thank you. I've been playing around with this code and it looks like PGFPlots removes the coordinate grid on the surface when you add this color shading. Is there a way to have both? – sps Nov 27 '15 at 11:25