# Rotation transformation of a parametrized plot

I'm working on this plot with pgfplots:

The image is from our sister-site Mathematica.SE and there's also a nice explanation how to do it with Mathematica.

1. Parametrize the 2d cut
2. Embed it in 3d
3. Rotate both in a circle and around itself

I originally posted the question on the TeXwelt LaTeX forum in German, my first steps which I wrote in "Drehtransformation mit pgfplots" are:

1. The 2d cut:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{polar}
\begin{document}
\begin{tikzpicture}
\begin{polaraxis}
{sin(3*x) + 1.25};
\end{polaraxis}
\end{tikzpicture}
\end{document}


2. Embedding in 3d for better visualizing with some temporary filling:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
( {cos(x)*(sin(3*x) + 1.25)},
{sin(x)*(sin(3*x) + 1.25)}, 0 );
\end{axis}
\end{tikzpicture}
\end{document}


No problem also to get a surface with simple 3d expansion:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
surf,
domain    = 0:360,
y domain  = 0:360,
samples   = 50,
samples y = 20,
]
( {cos(x)*(sin(3*x) + 1.25)},
{y}, {sin(x)*(sin(3*x) + 1.25)} );
\end{axis}
\end{tikzpicture}
\end{document}


3. That's my question, because I still need to bend and twist it:

How can I rotate that 2d plot around a circle, while rotating it at the same time around its origin, to get a surface plot like in the image at the top?

• There are a particular formula in the answer below. Is there are any reason not to use an equation? – m0nhawk Jul 21 '14 at 14:00
• @m0nhawk Yes - though a conjured up ready-to-plot but complex function is nice, I would like to learn about applying rotation transformations in 3d. It would be great if we could work out even a generic macro for it. – Stefan Kottwitz Jul 21 '14 at 14:17

When I saw your first picture, it immediately made me think of a torus; of course, it's a bit of a twisted torus, but it does have quite a lot in common. As detailed in How to draw a torus (for example), a torus can be parametrized as a surface using (for example)

x(t,s) = (2+cos(t))*cos(s+pi/2)
y(t,s) = (2+cos(t))*sin(s+pi/2)
z(t,s) = sin(t)


where t and s both lie on the interval [0,2\pi].

So, how can we apply this to your shape?

Let's start by trying to plot the curve given by the following parametrization in three dimensions:

x(t) = sin(3t)cos(t)
y(t) = sin(3t)sin(t)


A little bit of thought, and application of the torus idea tells us that in your example we can use the following, for example,

  x(t,s) = (4+(sin(3*(t))+1.25)*cos(t))*cos(s)
y(t,s) = (4+(sin(3*(t))+1.25)*cos(t))*sin(s)
z(t,s) = ((sin(3*(t))+1.25)*sin(t))


Which gives, for a fixed value of s and t\in[0,2\pi]

From here, we can allow s to vary - for example, if we allow s\in[0,\pi] then we achieve:

This is close, but it doesn't twist enough - for that we can choose, for example

  x(t,s) = (4+(sin(3*(t+Ns))+1.25)*cos(t))*cos(s)
y(t,s) = (4+(sin(3*(t+Ns))+1.25)*cos(t))*sin(s)
z(t,s) = ((sin(3*(t+Ns))+1.25)*sin(t))


The number N can be changed to increase/decrease the 'twistyness'; for example with N=10 and a fairly low resolution, then we achieve:

Finally, you crank up the resolution as much as you can before exhausting memory (running LuaLaTeX really helps - thanks Stefan), and you get the following:

This can be improved by using, for example, shader=interp. Here's the complete code to play with :)

% arara: lualatex
% !arara: indent: {overwrite: yes}
\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
axis equal,
]
surf,
samples=100, samples y=70,
colormap/cool,
domain=0:360,y domain=0:360,
z buffer=sort,
]
({(4+(sin(3*(x+2*y))+1.25)*cos(x))*cos(y)},
{(4+(sin(3*(x+2*y))+1.25)*cos(x))*sin(y)},
{((sin(3*(x+2*y))+1.25)*sin(x))});
\end{axis}
\end{tikzpicture}

\end{document}


Once we have the template, we can play with it a little more; for example, changing the parametrisation from sin(3(x+2y)) to sin(4(x+2y)) and using the hot2 colormap as follows

    \addplot3[
surf,
samples=100, samples y=70,
colormap/hot2,
domain=0:360,y domain=0:360,
z buffer=sort,
]
({(4+(sin(4*(x+2*y))+1.25)*cos(x))*cos(y)},
{(4+(sin(4*(x+2*y))+1.25)*cos(x))*sin(y)},
{((sin(4*(x+2*y))+1.25)*sin(x))});


gives a pleasing picture with a few more twists:

• Very nice! Btw. the memory exhaustion can be avoided simply using LuaLaTeX. I did, and I got surprisingly different results just by changing samples y to 30 and 50. – Stefan Kottwitz Jul 21 '14 at 21:02
• @StefanKottwitz thanks for noting that - I believe you'll get consistent results with the updated code :) – cmhughes Jul 21 '14 at 21:31
• You should consider the additional options shader=flat, miter limit=1. The fine grid lines result in a relatively hard look which is smoothened by shader=flat, and miter limit` avoids the tiny overshoots near edges. – Christian Feuersänger Aug 3 '14 at 11:47