I'm trying to draw in tikz the following figure taken from an old book:enter image description here

I tryed with standard spiral as suggested in How to draw vertical spiral using TiKZ? but the result is not satisfactory. Can you help me to create a faithful tikz version of this figure. thanks a lot :D


    \begin{axis} [
        axis lines=none,
        \addplot3 [domain=3.1*pi:5.5*pi, samples = 50, samples y=0]
        ({.5*sin(deg(-x))}, {.3*cos(deg(-x))+1}, {8*x*x*x});

        axis lines=center,axis on top,
        no marks,axis line style={draw=none}
        \addplot3+[no markers, variable=\t,domain=0:4*pi,
        mesh,samples= 50, black]
        ({sin(\t r)}, {cos(\t r)}, \t);
  • 1
    Welcome to TeX.SE! Please show us the code you have tried so far! Then we do not have to guess what you are doing ...
    – Mensch
    Oct 26, 2021 at 14:21
  • Thanks for the welcome! Oct 26, 2021 at 14:26
  • You could try to increase the sample size: samples=100, samples y=0. This will smoothen the curve. Oct 26, 2021 at 15:38
  • it's not a question of smoothness but of vertical lenght of the spiral Oct 26, 2021 at 15:51

6 Answers 6


I found this other approach quite appealing. It is a bit tricky to get the coil right, but if it is not too important where the spiral runs exactly, this may be a possible solution:

\documentclass[border=1mm, tikz]{standalone}


% base
\draw (-4,-1) node[shift={(.5,.25)}] {$\alpha$} -- (-2,1) -- 
      (4,1) -- (2,-1) -- cycle;

% cylinder
\draw (0,0) ellipse (2cm and .5cm);
\draw (0,5) ellipse (2cm and .5cm);
\draw (-2,0) -- (-2,5) (2,0) -- (2,5);

% axes
\draw[dashed] (0,0) node[above left] {$0$} -- (0,5);
\draw[->] (0,5) -- (0,6) node[right] {$x^3 = a$};;
\draw[->] (0,0) -- (2.25,0) node[right] {$x^2$};
\draw[->] (0,0) -- (-.75,-.75) node[left] {$x^1$};

% spiral
\clip (-2,0) rectangle (2,5);
\draw[decoration={coil, aspect=.55, segment length=50mm, amplitude=20mm}, decorate] (0,7.5) -- (0,-2.5);



enter image description here


I tried again, this time without using decorative coils but rather by drawing an approximation of the spiral using curved lines. It should actually be possible to draw an exact spiral this way, but I don't know the math behind it, so I leave it like this. I finally used the intersection and the calc libraries to compute the coordinates where the different lines intersect.

\documentclass[border=1mm, tikz]{standalone}

\usetikzlibrary{intersections, calc}


\begin{tikzpicture}[coord/.style={fill, circle, inner sep=1pt}]
% base
\draw (-4,-1) -- (-2,1) -- (4,1) -- (2,-1) -- cycle;

% cylinder
\draw[name path=cylinderbase] (-2,0) arc (180:360:2cm and .5cm);
\draw[dashed] (2,0) arc (0:180:2cm and .5cm);
\draw[name path=cylindertop] (0,5) ellipse (2cm and .5cm);
\draw (-2,0) -- (-2,5) (2,0) -- (2,5);

% axes
\draw[dashed] (0,0) node[coord, label=above left:$0$] (null) {} -- (0,5) node[coord] {};
\draw[->] (0,5) -- (0,6) node[right] {$x^3 = a$};
\draw[->] (0,0) -- (2.25,0) node[right] {$x^2$};
\draw[->] (0,0) -- (-.75,-.75) node[left] {$x^1$};

% spiral
\clip (-2,0) -- (-2,5) arc (180:360:2cm and .5cm) -- (2,0) arc (360:180:2cm and .5cm) -- cycle;
\draw[name path global=spiralstart] (2,5.175) to[controls=+(270:2) and +(270:.5)] (-2,3.175);
\draw[dashed] (-2,3.175) to[controls=+(90:.5) and +(90:2)] (2,1.175);
\draw[name path global=spiralend] (2,1.175) to[controls=+(270:2) and +(270:.5)] (-2,-.175);

% nodes
\path[name path=temp1] (null) -- ++(4.5,-1);
\path[name intersections={of=temp1 and cylinderbase}];
\node[coord, label=below:$P_1$] (p1) at (intersection-1) {};

\path[name path=temp2] (p1) -- ++(0,5);
\path[name intersections={of=temp2 and spiralend}];
\node[coord, label=above left:$P$] (p) at (intersection-1) {};

\path[name intersections={of=temp2 and spiralstart}];
\node[coord, label=above:$\bar P$] (pbar) at (intersection-1) {};

\draw[dashed] (null) -- (p1);
\draw[dashed] (p1) -- (pbar);
\draw[dashed] (p) -- +($(null)-(p1)$) node[coord, label=above left:$P_2$] {};

% labels
\node at (-3.45,-.75) {$\alpha$};
\node at (-1,0) {$\gamma$};
\node at (.125,-.25) {$\varphi$};


enter image description here

  • thanks a lot! it's a good starting point a more detailed drow. danke Oct 26, 2021 at 17:16
  • 1
    Well, I stopped right before the painstaking questions arose: How to style the part of the coil that runs behind the cylinder? How to get the coordinate where a line crosses the spiral? Anyways, non c'è di che! Oct 26, 2021 at 17:27
  • 1
    I added another answer that may better suit your needs. It is still not an exact drawing, but, I would guess, that if you know how to mathematically construct the curved lines that form the spiral, it should be possible to come up with an exact drawing based on this solution. Oct 26, 2021 at 19:48

While waiting for a Tikz's answer, see a bit with Asymptote.

Compile on http://asymptote.ualberta.ca/

I don't know what \alpha and \gamma mean!

import solids;
import graph3;
real r=3;
real h=2.5pi;


revolution R=cylinder(O,r,h);

// The circular helix
triple f(real t){
  real a=r*cos(t);
  real b=r*sin(t);
  real c=t;
  return (a,b,c);

real k=7;
path3 plane=(k,k,0)--(k,-k,0)--(-k,-k,0)--(-k,k,0)--cycle;


guide3 g=graph(f,0,h,150);

triple P=f(1),overP=f(1+2pi);
triple P1=(P.x,P.y,0),P2=(0,0,P.z);



zaxis3(Label("$x^3=$ a",Relative(.6),2RightSide),h,h+4,Arrow3);

enter image description here

  • 1
    thanks a lot Nguyen VanChi 1998. i noticed that working with asymptote make everything easier and more elegant. Can i ask if you can add in the drow (sorry i'm not practicle with the code) the \gamma and \varphi? and last question: is it possible to have classicthesis font for the letters and symbols in the drow? this is not necessary but in case it would be wonderful (far above my expectations) thanks again a lot :D Oct 26, 2021 at 17:09
  • Nice! and h should be 2.5pi
    – Black Mild
    Oct 26, 2021 at 17:40
  • Excellent drawing: I like the tips of the vector of asymptote in 3D. Can you see the label $x^3=$ a, ? Peraphs there is a a out the $.
    – Sebastiano
    Oct 26, 2021 at 19:09
  • 1
    @Sebastiano Yes, that is my trick. :) Oct 26, 2021 at 19:24

Here is another non-TikZ effort, this time in Metapost. There is no built-in support for 3D drawing or transparency in MP, so this type of drawing can be tricky to get right, and requires some patience.

enter image description here


    path plane, base, cap;
    plane = unitsquare shifted -(1/2, 1/2) xscaled 300 yscaled 120 slanted 1/2;
    base = fullcircle xscaled 100 yscaled 42;
    cap = base shifted 144 up;

    path xx[];
    xx1 = origin -- 3/4 point 1/2 of plane;
    xx2 = origin -- 3/4 point 3/2 of plane;
    xx3 = origin -- 200 up;

    path spiral;
    (a, b) = base intersectiontimes xx1;
    n = 64;
    r = (16 - a) / n;
    spiral = point 0 of cap 
        for i=1 upto n:
            .. (i/n)[point 8-i*r of cap, point 8-i*r of base]

    path pole;
    pole = point 7 of base -- point 7 of cap cutafter subpath (0, n/2) of spiral;
    pair P;
    P = pole intersectionpoint subpath (50, 64) of spiral;

    def hidden_axis = dashed withdots scaled 1/2 withcolor 1/4 enddef;
    def hidden_line = dashed evenly withpen pencircle scaled 1/4 withcolor 1/2 enddef;

    fill plane withcolor 7/8;
    draw plane;

    fill cap withcolor 7/8;
    fill subpath (4,8) of base -- subpath (8, 4) of cap -- cycle
        withcolor 3/4;

    draw xx1 cutafter base hidden_axis;
    draw xx2 cutafter base hidden_axis;
    draw center base -- center cap hidden_axis;
    draw subpath(0, 4) of base hidden_line;
    draw point 4 of cap -- subpath (4, 8) of base -- point 0 of cap;
    draw cap;

    draw subpath(24, 50) of spiral hidden_line;
    draw subpath(0, 24) of spiral;
    draw subpath(50, infinity) of spiral;

    draw pole;

    ahangle := 30;
    drawarrow xx1 cutbefore base; label.llft("$x_1$", point 1 of xx1);
    drawarrow xx2 cutbefore base; label.urt ("$x_2$", point 1 of xx2);
    drawarrow center cap -- point 1 of xx3; label.rt("$x_3=a$", point 1 of xx3 shifted 8 down);

    draw center cap withpen pencircle scaled dotlabeldiam yscaled .4;

    label.urt("$\alpha$", point 0 of plane shifted (16, 8));

    draw origin -- point 0 of pole hidden_axis;
    draw P -- P - point 0 of pole hidden_axis;
    dotlabeldiam := 3/4 dotlabeldiam;
    dotlabel.lft("$O$", origin);
    dotlabel.ulft("$P$", P);
    dotlabel.lrt("$P_1$", point 0 of pole);
    dotlabel.ulft("$P_2$", P - point 0 of pole);
    dotlabel.lrt("$\bar{P}$", point 1 of pole);


This is wrapped up in luamplib so you need to compile it with lualatex. Follow the link at the top for more details about MP.


Another Asymptote version for fun! It is not "faithful" version of OP's figure. I am not trying to replicate that old fashioned one.

In this case, the hidden curve is can be easily determined via parameter t from .5pi to 1.5pi, so can be drawn with dashes. However I like to draw it naturally, using opacity(.5). Also, the base and the top disks are not necessary.

The point P on the spiral is at time s; and after a cycle surrounding the cylinder, it reaches to the point of time s+2 pi. The blue line reminds a social situation when people back to an old position at a higher level ^^.

enter image description here

// http://asymptote.ualberta.ca/
import graph3;
triple spiral(real t){return (cos(t),sin(t),t);}
real tmin=0,tmax=2.5pi;
path3 g=graph(spiral,tmin,tmax,operator..);

real s=1;
triple P=spiral(s);
triple Ptop=spiral(s+2pi);
triple P1=(P.x,P.y,0);
triple P2=(0,0,P.z);



Update: In this case, hidden part of the curve can be determined, corresponding to values from pi/2 to 3pi/2, so this is for ones who like dashes ^^

enter image description here

path3 g=graph(spiral,tmin,pi/2,operator..);
path3 g2=graph(spiral,pi/2,3pi/2,operator..);
path3 g3=graph(spiral,3pi/2,5pi/2,operator..);

Yet another non-tikz version. I hope you can stand it. I use MetaPost/MetaFun (see https://www.pragma-ade.com/general/manuals/metafun-p.pdf), but a slightly different approach than in Thruston's lovely answer. I think it was Troy Henderson who taught me the trick to use rgb colors in MetaPost to be able to draw 3D.

The file was compiled with context.

a decorated cylinder

path p[];
u:=1in;% overall unit
a:=4;% height of cylinder (radius=1)
tp:=40;% azimuthal angle for the points P
maxt:=450;% max parameter for the spiral

% (theta,phi) spherical coordinates for viewpoint direction

% scalar product
primarydef u cdotprod v =
    redpart u*redpart v + greenpart u*greenpart v + bluepart u*bluepart v

% Projection from 3D to 2D
vardef P primary x =
    save ct,st,sp;
    (x cdotprod (-st,ct,0),x cdotprod (-ct*sp,-st*sp,cosd(phi)))

path axis[],alpha,basecircle,topcircle, leftline,rightline,spiral;
pair ip[],pts[];

axis[1]=(origin--P(1.75,0,0)) scaled u;
axis[2]=(origin--P(0,1.75,0)) scaled u;
axis[3]=(origin--P(0,0,4.75)) scaled u;

alpha = (P(-2.5,-2.5,0)--P(2.5,-2.5,0)--P(2.5,2.5,0)--P(-2.5,2.5,0)--cycle) scaled u;
basecircle = (for t=0 step 10 until 360: P(cosd(t),sind(t),0) .. endfor cycle) 
scaled u; 
topcircle = (for t=0 step 10 until 360: P(cosd(t),sind(t),a) .. endfor cycle) 
scaled u;
leftline = (directionpoint down of basecircle) -- (directionpoint down of topcircle);
rightline = (directionpoint up of basecircle) -- (directionpoint up of topcircle);
spiral = (P(1,0,0) for t=0 step 10 until maxt: .. P(cosd(t),sind(t),a*t/maxt) endfor) scaled u;

% points where spiral meet vertical lines
ip[1]=spiral intersectionpoint rightline;
ip[2]=spiral intersectionpoint leftline;

% the P points
pts[0]=P(cosd(tp),sind(tp),0) scaled u;
pts[1]=P(cosd(tp),sind(tp),a*tp/maxt) scaled u;
pts[2]=P(cosd(tp),sind(tp),a*(tp+360)/maxt) scaled u;
pts[3]=P(0,0,a*tp/maxt) scaled u;

%drawing time!
draw alpha;
draw axis[1] cutafter (axis[1] intersectionpoint basecircle) dashed evenly;
drawarrow axis[1] cutbefore (axis[1] intersectionpoint basecircle);
draw axis[2] cutafter (axis[2] intersectionpoint basecircle) dashed evenly;
drawarrow axis[2] cutbefore (axis[2] intersectionpoint basecircle);
draw axis[3] cutafter (P(0,0,a) scaled u) dashed evenly;
drawarrow axis[3] cutbefore (P(0,0,a) scaled u);

draw basecircle cutafter point 0 of rightline;
draw basecircle cutbefore point 0 of leftline;
draw basecircle cutbefore point 0 of rightline cutafter point 0 of leftline dashed evenly;
draw topcircle;

draw leftline;
draw rightline;
draw spiral cutafter ip[1];
draw spiral cutbefore ip[1] cutafter ip[2] dashed evenly;
draw spiral cutbefore ip[2];

draw P(0,0,0)--pts[0]--pts[2] dashed evenly;
draw pts[1]--pts[3] dashed evenly;

drawpoints P(0,0,0);
drawpoints P(0,0,a) scaled u;

for i=0 upto 3:
  drawpoints pts[i];

label.ulft("$x^1$",point 1 along axis[1]);
label.bot("$x^2$",point 1 along axis[2]);
label.rt("$x^3=a$",P(0,0,a) scaled u);
label.urt("$\alpha$",P(2,-2,0) scaled u);
label("$\gamma$",0.25[point 0 of leftline,P(0,0,0)]);

Welcome to TeX.SE!!!

This is another TikZ option, an isometric one. It's easy to draw this way because we know beforehand the angles for the cylinder 'limit generatrices': 135 and 315.

I made a \helix macro to avoid repeating the same code over and over again, the rest is pretty straightforward, or so I hope.

The code:


\newcommand{\helix}[3] % domain=#1:#2, options=#3
  \draw[blue,thick,#3] plot[domain=#1:#2,samples={(#2-#1)/3+1}]

\begin{tikzpicture}[line cap=round,line join=round,isometric view]
% axes
\draw[-latex] (0,0,0) -- (-\r-1,0,0) node [left]  {$x$};
\draw[-latex] (0,0,0) -- (0,-\r-1,0) node [right] {$y$};
% cylinder, back
\draw[red,dashed]     (135:\r) arc (135:-45:\r);
\draw[red] (0,0,\h) + (135:\r) arc (135:-45:\r);
% helix, back
% z-axis
\draw[dashed] (0,0,0) -- (0,0,\h);
% cylinder, top
\fill[red!30,opacity=0.4] (0,0,\h) circle (\r);
% cylinder, front
\draw[red,left color=red!30,fill opacity=0.5]
  (135:\r) arc (135:315:\r) --++ (0,0,\h) arc (315:135:\r) -- cycle;
% helix, front
\helix{0}  {135}{}
% z-axis
\draw[-latex] (0,0,\h) --++ (0,0,1) node [above] {$z$};

And the picture:

enter image description here

  • Nice! I always forget that it is actually possible to draw (axonometric) 3D in TikZ. Nov 1, 2021 at 16:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .