# How to plot three-dimensional polar functions with pgfplots

I would like to plot the following functions with pgfplots:

I know how they are defined:

\sqrt{r}\sin\frac{\theta}{2}, \sqrt{r}\sin\frac{\theta}{2}\sin\theta,
\sqrt{r}\cos\frac{\theta}{2}, \sqrt{r}\cos\frac{\theta}{2}\sin\theta

but nothing else (for example the domain).

I'll post soon my solution (which is far from what I'm looking for), but I would like to now your opinion from now.

EDIT: here is my attempt to reproduce the first function:

\documentclass{scrbook}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5.1}
\begin{document}

\begin{tikzpicture}
\begin{axis}[
xtick=\empty,
ytick=\empty,
ztick=\empty,
unbounded coords=jump,
]
surf,
faceted color=blue,
samples=20,
domain=-1:1, y domain=-5:0]
{sqrt(x^2+y^2)*sin(0.5*atan(y/x))};
\end{axis}
\end{tikzpicture}

and here is the result:

I know, it's very different from how it should be, but I don't know how to improve it.

• I'm not really sure what the question is here. Apr 15, 2012 at 8:27
• @mp87: I think you're more likely to get helpful answers if you edit your question to include your current approach and what you don't like about it.
– Jake
Apr 15, 2012 at 9:05
• @JosephWright: I took the plots from an article, but I don't know how to reproduce them.
– mp87
Apr 15, 2012 at 12:03
• @Jake: You're right, in fact I usually add a MWE. But this time, when I posted the question, I didn't have the code with me. I decided to ask for help anyway because I thought that maybe someone could help me without further information.
– mp87
Apr 15, 2012 at 12:04

You can plot polar functions by setting domain=<your theta domain>, y domain=<your r domain>, data cs=polar. Using this approach, the jumps in your functions will be plotted correctly.

In this example, I've used the same color range for all four plots (by setting point meta min and point meta max explicitly). That way, you can immediately see that the functions span different z-ranges. If you don't want that, just delete the point meta min/max keys.

If you want the plots to fill out the whole x/y plane, you'll need to stretch r accordingly. I've defined two functions here, stretch that does just that. It needs to be applied to both y coord trafo and to the function to be plotted. In conjunction with shader=interp, we're getting pretty close to the original plots:

Code for circular polar plots

\documentclass{article}
\usepackage{pgfplots}
\usepackage{amsmath}
\begin{document}
\pgfplotsset{
mp87's style/.style={
view={285}{30},
unit vector ratio*=0.707 1.5 1,
domain=0:360, samples=30,   % theta
y domain=0:9, samples y=8,  % r
x dir=reverse,
data cs=polar,
zmin=-3, zmax=3,
3d box=complete*,           % draw all box lines, "*" = draw grid lines also in front
point meta min=-3, point meta max=3,  % same colour scaling for all plots
grid=major,             % draw major grid lines
xtick=\empty,               % no x or y grid lines
ytick=\empty,
ztick=0, zticklabels={}, % one grid line at z=0
z buffer=sort
}
}

\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \sin(\theta / 2)$]
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \cos(\theta / 2)$]
\end{axis}
\end{tikzpicture}\\[2ex]
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \sin(\theta / 2) \sin(\theta)$]
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \cos(\theta / 2) \sin(\theta)$]
\end{axis}
\end{tikzpicture}
\end{document}

Code for square polar plots

\documentclass{article}
\usepackage{pgfplots}
\usepackage{amsmath}
\begin{document}

\tikzset{
declare function={stretch(\r)=min(1/cos(mod(\r,90)),1/sin(mod(\r,90));}
}
\pgfplotsset{
mp87's style/.style={
view={285}{30},
unit vector ratio*=0.707 1.5 1,
x dir=reverse,
domain=0:360, samples=41,   % theta, with samples = 8*n+1
y domain=0:9, samples y=8,  % r
zmin=-3,zmax=3,
3d box=complete*,           % draw all box lines, "*" = draw grid lines also in front
grid=major,             % draw major grid lines
grid style={black, thick},
xtick=\empty,               % no x or y grid lines
ytick=\empty,
ztick=0, zticklabels={}, % one grid line at z=0
z buffer=sort,
colormap/jet,
every axis plot post/.style={opacity=0.8},
data cs=polar,
before end axis/.code={
\draw [/pgfplots/every axis grid](rel axis cs:0.5,0.5,0.5) -- (rel axis cs:0,0.5,0.5);
},
y coord trafo/.code=\pgfmathparse{y*(stretch(x))},
y coord inv trafo/.code=\pgfmathparse{y/(stretch(x))},
}
}

\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \sin(\theta / 2)$]
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \cos(\theta / 2)$]
\end{axis}
\end{tikzpicture}\\[2ex]
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \sin(\theta / 2) \sin(\theta)$]
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[mp87's style, title=$\sqrt{r} \cos(\theta / 2) \sin(\theta)$]
\end{axis}
\end{tikzpicture}

\end{document}
• is the 3D-perspective projection view expected soon in Tikz? (instead of the current parallel projection one) Apr 15, 2012 at 14:21
• @pluton There is a feature request for perspective views in pgfplots. The feature request has no schedule, though - it might need some time. Apr 15, 2012 at 17:53
• @Jake @Torbj if I am not mistaken then the transformation should be {cos(x)*y}, {sin(x)*y)} in both the first sentence AND in the listing. Otherwise you would have exchanged x and y Apr 15, 2012 at 19:31
• @ChristianFeuersänger: I've edited my answer to use the data cs:polar now. Much more elegant! Slight problem: I don't seem to be able to use the axis cs: coordinate system in my before end axis/.code in the square plots anymore, it complains about not knowing y and x. Any ideas?
– Jake
Apr 15, 2012 at 21:22
• @Jake: wow, impressive! Thank you very much for the excellent answer! I'll post soon another request that I consider even more challenging, I hope that you'll find it as easy as this one :)
– mp87
Apr 15, 2012 at 22:35

In addition to the good answer of Jake, I would point out that pgfplots can automatically handle input coordinates in polar form: you simply need to say that they are given in polar form by means of the data cs=polar key.

If you do that, you can omit the explicitly provided parametric form of Jake's answer, i.e. instead of

\addplot3  [surf, z buffer=sort] ({cos(x)*y}, {sin(x)*y}, {sqrt(y)*sin(x/2)});

you simply write

\addplot3  [surf, z buffer=sort,data cs=polar] {sqrt(y)*sin(x/2)};

Here, only the z expression has to be provided, together with data cs=polar. Pgfplots assumes that your final X and Y coordinates are (angle,radius) and they are converted to cartesian coordinates on-the-fly without touching the z value.

Note that the "polar" system is 2d, its transformation is only applied to the first two coordinates.

So, my suggestion is to stick with Jake's answer together with the simplification by means of the data cs=polar key.