Tell me more ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Torus wrapped with helix

How can I generate the above image using TikZ (possibly other methods will work if they produce better looking results)?
I would like to have a nicely shaded (not so dark image) without gridlines and possibly enough opacity on the torus to see the hidden part of the helix.

The image given is very close to what I want though and I would just try to make it visually a little better.

share|improve this question
1  
Just in case it might be useful, here's the Maple worksheet that I used to generate that image. – Scott H. Sep 7 '12 at 7:31
@ScottH. Thanks – Jubao Sep 8 '12 at 18:15

3 Answers

up vote 31 down vote accepted
+100

Here's a Sketch/TikZ approach.

Running sketch on this file:

def helix {
    def n_segs 600
  sweep [draw=orange] { n_segs, rotate(24*360 / n_segs, (1.5,0,0), [0,0,1]), rotate(1*360/n_segs, (0,0,0), [0,1,0]) } (2.01,0,0)
}

def torus {
    def n_segs 60
    sweep [draw=none, fill=cyan, fill opacity=0.75] {n_segs, rotate(360/n_segs, (0,0,0), [0,1,0])}
        sweep {n_segs, rotate(360/n_segs, (1.5,0,0), [0,0,1])}
        (2,0,0)
}

put { view((10,4,2)) } {{helix} {torus}}

global { language tikz }

generates a .tex file which can be compiled using pdflatex.

The helix winding around the helix winding around a torus

can be generated using

def helix {
    def n_segs 10000
  sweep [draw=orange] {
    n_segs,
    rotate(1000*360 / n_segs, (2,0,0), [0,1,0]),
    rotate(24*360 / n_segs, (1.5,0,0), [0,0,1]),
    rotate(1*360/n_segs, (0,0,0), [0,1,0])
  } (2.04,0,0)
}

def torus {
    def n_segs 50
    sweep [draw=none, fill=cyan, fill opacity=0.75] {n_segs, rotate(360/n_segs, (0,0,0), [0,1,0])}
        sweep {n_segs, rotate(360/n_segs, (1.5,0,0), [0,0,1])}
        (1.9,0,0)
}

put { view((10,4,2)) } {{torus} {helix}}

global { language tikz }
share|improve this answer
1  
How big is the TikZ file? :-) – Joseph Wright Sep 10 '12 at 15:56
@JosephWright: Hehe, I tried posting it, but the system wouldn't let me. It's about 250kB, so not much fun to edit by hand. The resulting PDF is 47kB. – Jake Sep 10 '12 at 16:04
I'm impressed: draws faster than the PSTrick one! – Joseph Wright Sep 10 '12 at 16:13
2  
OK. Thanks for your effort. I am still waiting for the pure TikZ. If it is impossible then I will assign you the bounty. – Click Me Sep 10 '12 at 16:13
4  
Wow. The helix winding around the other winding around the torus is incredible. This is most likely impossible in a 'normal' graphics program such as Illustrator or Inkscape and quite hard even in Blender or other 3D programs. – Alexander Sep 10 '12 at 16:49
show 2 more comments

it shows the function

 x(u,v)=(R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)
 y(u,v)=(R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)
 z(u,v)=(R0 + RL*sin(u))*cos(k*v)

with the parameter setting shown in the example. RL: radius of the coil line; R1: Torus outer; R0: Torus inner radius; k:number of coils

run it with xelatex or latex>dvips>ps2pdf (takes some time to run!)

\documentclass{minimal}
\usepackage{pst-solides3d}
\pagestyle{empty}
\begin{document}

\begin{pspicture}[solidmemory](-6,-4)(6,4)
\psset{viewpoint=30 0 15 rtp2xyz,Decran=30,lightsrc=viewpoint}
\psSolid[object=tore,r1=5,r0=1,ngrid=36 36,
    fillcolor=blue!30,action=none,name=Torus]%
%\axesIIID(4.5,4.5,0)(5,5,4)
\codejps{/R1 5 def /RL 0.05 def /R0 1.1 def /k 25 def}%
\defFunction[algebraic]{helix}(u,v)
    {(R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)}
    {(R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)}
    {(R0 + RL*sin(u))*cos(k*v)}
\psSolid[object=surfaceparametree,
       base=0 6.2831853 0 6.2831853,
       linecolor=blue,linewidth=0.01,fillcolor=yellow,
       ngrid=0.8 0.01,function=helix,action=none,name=Helix]%
\psSolid[object=fusion,base=Torus Helix,grid=false]
%\gridIIID[Zmin=-3,Zmax=3,showAxes=false](-2,2)(-2,2)
\end{pspicture}

\begin{pspicture}[solidmemory](-6,-6)(6,6)
\psset{viewpoint=30 0 90 rtp2xyz,Decran=30,lightsrc=viewpoint}
\psSolid[object=tore,r1=5,r0=1,ngrid=36 36,
    fillcolor=blue!30,action=none,name=Torus]%
%\axesIIID(4.5,4.5,0)(5,5,4)
\codejps{/R1 5 def /RL 0.05 def /R0 1.1 def /k 25 def}%
\defFunction[algebraic]{helix}(u,v)
    {(R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)}
    {(R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)}
    {(R0 + RL*sin(u))*cos(k*v)}
\psSolid[object=surfaceparametree,
       base=0 6.2831853 0 6.2831853,
       linecolor=blue,linewidth=0.01,fillcolor=yellow,
       ngrid=0.8 0.01,function=helix,action=none,name=Helix]%
\psSolid[object=fusion,base=Torus Helix,grid=false]
%\gridIIID[Zmin=-3,Zmax=3,showAxes=false](-2,2)(-2,2)
\end{pspicture}

\end{document}

enter image description here

enter image description here

an animation is here: http://tug.org/PSTricks/main.cgi?file=Animation/gif/gif

With \psSolid[object=fusion,base=Torus Helix,grid=false,opacity=0.5]
 (setting transparency) and a thinner helix (decrease /RL) one gets

enter image description here

and just for fun with

\documentclass{minimal}
\usepackage{pst-solides3d}
\begin{document}
\begin{pspicture}[solidmemory](-6.5,-3.5)(6.5,3)
\psset{viewpoint=30 0 15 rtp2xyz,Decran=30,lightsrc=viewpoint}
\psSolid[object=tore,r1=5,r0=1,ngrid=36 36,tablez=0 0.05 1 {} for,
          zcolor= 1 .5 .5 .5 .5 1,action=none,name=Torus]
\pstVerb{/R1 5 def /R0 1.2 def /k 20 def /RL 0.15 def /kRL 40 def}%
\defFunction[algebraic]{helix}(t)
     {(R1+R0*cos(k*t))*sin(t)+RL*sin(kRL*k*t)}
     {(R1+R0*cos(k*t))*cos(t)+RL*cos(kRL*k*t)}
     {R0*sin(k*t)+RL*sin(kRL*k*t)}
\psSolid[object=courbe,
        resolution=7800,
        fillcolor=black,incolor=black,
        r=0,
        range=0 6.2831853,
        function=helix,action=none,name=Helix]%
\psSolid[object=fusion,base=Torus Helix,grid]
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
Is there any way to fix the artifacts where the yellow helix seems to be missing in the first picture? I would also like to use a parameteric curve instead of a solid(I tried to modify the code but always get errors). I'd like the yellow helix to look more like a grid line on the torus rather than a separate object. – Jubao Sep 8 '12 at 18:18
Undefined kRL found. – Click Me Sep 11 '12 at 14:53
\pstVerb{/R1 5 def /R0 1.2 def /k 20 def /RL 0.1 def /kRL 40 def}% – Herbert Sep 11 '12 at 14:55
1  
The submitted code for the nested helix does not produce the same result as your uploaded image. – Click Me Sep 19 '12 at 13:39
then you have not the current pst-solides3d.tex|pro files. Compare with the ones from texnik.dante.de – Herbert Sep 19 '12 at 13:52

Here's a work-in-progress. It's missing the most important thing: the visibility of the helix. At first I thought that the points where it becomes (in)visible are evenly spaced, but they are not quite. I think I'll have to do some vector algebra to (hopefully) find a solution. The torus is not a 3D object, it's made from many almost transparent circular rings.

Code

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

\begin{document}

\newcommand{\xangle}{-30}
\newcommand{\yangle}{210}
\newcommand{\zangle}{90}

\newcommand{\xlength}{1}
\newcommand{\ylength}{1}
\newcommand{\zlength}{1}

\pgfmathsetmacro{\xx}{\xlength*cos(\xangle)}
\pgfmathsetmacro{\xy}{\xlength*sin(\xangle)}
\pgfmathsetmacro{\yx}{\ylength*cos(\yangle)}
\pgfmathsetmacro{\yy}{\ylength*sin(\yangle)}
\pgfmathsetmacro{\zx}{\zlength*cos(\zangle)}
\pgfmathsetmacro{\zy}{\zlength*sin(\zangle)}

\begin{tikzpicture}
[   x={(\xx cm,\xy cm)},
    y={(\yx cm,\yy cm)},
    z={(\zx cm,\zy cm)},
]

\pgfmathsetmacro{\RO}{1.1}
\pgfmathsetmacro{\RI}{5}
\pgfmathsetmacro{\K}{10}

\pgfmathsetmacro{\doubleRO}{2*\RO}

\foreach \h in {0,0.01,...,\doubleRO}
{   \pgfmathsetmacro{\pm}{sqrt(\h*(\doubleRO-\h))}
    \fill[opacity=0.007,blue,even odd rule] (0,0,\h-\RO) circle (\RI+\pm) (0,0,\h-\RO) circle (\RI-\pm);
}

\xdef\initialx{\RI}
\xdef\initialy{0}
\xdef\initialz{\RO}

\foreach \v in {0.1,0.2,...,360.1}
{   \pgfmathsetmacro{\newx}{(\RI + \RO*sin(\K*\v))*cos(\v)}
    \pgfmathsetmacro{\newy}{(\RI + \RO*sin(\K*\v))*sin(\v)}
    \pgfmathsetmacro{\newz}{\RO*cos(\K*\v)}
    \pgfmathsetmacro{\mycolor}{cos(\v)*50+50}
    \draw[red!\mycolor!green,thick] (\initialx,\initialy,\initialz) -- (\newx,\newy,\newz);
    \xdef\initialx{\newx}
    \xdef\initialy{\newy}
    \xdef\initialz{\newz}

}

\end{tikzpicture}

\end{document}

(insufficient) Result

enter image description here

share|improve this answer
if you want hidden lines and surfaces then you have to build small line or polygon segments of all objects, then build the direction vector and sort all calculated vectors. And in the end you have to fill the canvas with the line and polygon segments depending to the sorted list of direction vectors. – Herbert Sep 11 '12 at 13:17
1  
see my deleted answer for the same limitations using pgfplots – cmhughes Sep 11 '12 at 18:58
The torus is nice and you got the windings. Maybe put a solid black torus behind the blue one so it looks shaded rather than glowing – Jubao Sep 16 '12 at 19:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.