# Help on decorations: how to draw a spiral coiled tube in TikZ

Hi everybody I was trying to draw a spiral coiled tube

with TikZ decoration library. This is what i got so far:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations}

\pgfdeclaredecoration{example}{initial} {
\state{initial}[width=5mm, next state=mynext] {
%
\pgfpathmoveto{\pgfpoint{0cm   }{1cm   }}
\pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
}
\state{mynext}[width=5mm]{
\pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
}
\state{final} {
\pgfpathlineto{\pgfpointdecoratedpathlast}
}
}

\begin{document}

\tikz[decoration=example] {
\draw [decorate]    (0,0) -- (3,0);
\draw [blue!20!,decorate] (0,0) to [out=45,in=135] (3,0);
\draw [red,decorate] (0,-5) to [out=30,in=100] (3,-5);
}
\end{document}


This results in a good one for straight lines, but with some bending there is a gap between the segments. So this is what i expected since i'am not able to hand over two coordinates to the next repetition.

I tried to compute the end point (upper corner) by storing \pgfdecoratedangle and transforming it back to the last segments angel but \pgfdecoratedangle seems to be empty.

So how can i connect those segments properly and/or how could one draw such a tube ?

Update: another approach with an existing decorations:

\documentclass[border=1mm]{standalone}
% based on http://tex.stackexchange.com/questions/31707/how-to-raise-a-generic-curve-problem-with-pgfdeclaredecoration
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{decorations.pathmorphing}

\tikzset{forcedist/.style={decorate, decoration={markings,
mark=between positions 0 and 1 step 0.0999 with {\draw[thick] (0,-#1) to[bend left] (0,#1); }}}}

\begin{document}

\begin{tikzpicture}
\draw [double distance = 1cm,thick, double=red, decoration=snake]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);
% those lines should be wavy
\draw [forcedist=5mm]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);
\draw [double distance = 5mm,thick, double=red]  (0,3) --++(8,0);
\draw [forcedist=2.5mm ]  (0,3)--++(8,0);
\end{tikzpicture}

\end{document}


So this looks quite encouraging, although i'm not able to make those douled lines wavy so that there is a impression of a thicker spiral. The latter results in

-
\pgfdecoratedangle does indeed not work, strangely enough. Nevertheless you should post the code you tried. I guess you wanted to use the persistent pre/postcomputation options. Another approach would be to do something like this: tex.stackexchange.com/questions/31707/… –  canaaerus Jul 27 '12 at 5:24
Howdy thanks for the link this is quite close. But i can't get those double lines to be wavy. When i use persistent precomputation how can i store a point in such a way that i can refer on it after the transformation? –  bloodworks Aug 3 '12 at 9:03
@morbusg Ah, I was about the take a shot at this. Now it's even more appealing :-) I'll look into it after my fight with IEEE is over about my article. –  percusse Aug 3 '12 at 12:21
Allowing multiple bounties from multiple users at the same time might be an interesting game. –  Please don't touch Aug 3 '12 at 18:25
This may help. tex.stackexchange.com/a/43605/16062 –  Gustavo Aug 4 '12 at 12:56

Here's a small modification of your original code that remembers the key point on the previous computation (the outer-forward corner). It does this by defining a coordinate node at that point. Since there are a lot of transformations involved, this seemed the simplest method of achieving that end.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/64074/86}
\usepackage{tikz}
\usetikzlibrary{decorations}

\pgfdeclaredecoration{example}{initial} {
\state{initial}[width=5mm, next state=mynext] {
%
\pgfpathmoveto{\pgfpoint{0cm   }{1cm   }}
}}{\pgfpoint{0cm   }{0cm   }}
}}{\pgfpoint{.5cm   }{0cm   }}
}}{\pgfpoint{.5cm   }{1cm   }}
}}{\pgfpoint{0cm}{1cm}}
\pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
\pgfcoordinate{coil-tmp}{\pgfpoint{.5cm}{1cm}}
}
\state{mynext}[width=5mm]{
}{.5cm   }}{\pgfpoint{.5cm   }{1cm   }}
}}{\pgfpointanchor{coil-tmp}{center}}
\pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
\pgfcoordinate{coil-tmp}{\pgfpoint{.5cm}{1cm}}
}
\state{final} {
\pgfpathlineto{\pgfpointdecoratedpathlast}
}
}

\begin{document}

\tikz[decoration=example] {
\draw [decorate]    (0,0) -- (3,0);
\draw [blue!20!,decorate] (0,0) to [out=45,in=135] (3,0);
\draw [red,decorate] (0,-5) to [out=30,in=100] (3,-5);
}
\end{document}


Result:

-
I guess one should amend this with the code from the questions about getting the coil decoration to end at the right place to get rid of the artefact at the end. –  Loop Space Aug 9 '12 at 8:40

Edit: I corrected my answer to avoid the bad practice of modifying a package file, following the suggestion of Paul Gaborit.

I made a few modifications to the code of this answer to get the following result:

\documentclass{article}

\usepackage{tikz}

\usetikzlibrary{decorations.pathmorphing}

\makeatletter

% Decorations based on
% http://tex.stackexchange.com/questions/32297/modify-tikz-coil-decoration/43605#43605

% coilup decoration
%
% Parameters: \pgfdecorationsegmentamplitude, \pgfdecorationsegmentlength,

\pgfdeclaredecoration{coilup}{coil}
{
\state{coil}[switch if less than=%
1.5\pgfdecorationsegmentlength+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude to last,
width=+\pgfdecorationsegmentlength]
{
\pgfpathcurveto
{\pgfpoint@oncoil{0    }{ 0.555}{1}}
{\pgfpoint@oncoil{0.445}{ 1    }{2}}
{\pgfpoint@oncoil{1    }{ 1    }{3}}
\pgfpathmoveto{\pgfpoint@oncoil{1    }{-1    }{9}}
\pgfpathcurveto
{\pgfpoint@oncoil{0.445}{-1    }{10}}
{\pgfpoint@oncoil{0    }{-0.555}{11}}
{\pgfpoint@oncoil{0    }{ 0    }{12}}
}
\state{last}[width=.5\pgfdecorationsegmentlength+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude,next state=final]
{
\pgfpathcurveto
{\pgfpoint@oncoil{0    }{ 0.555}{1}}
{\pgfpoint@oncoil{0.445}{ 1    }{2}}
{\pgfpoint@oncoil{1    }{ 1    }{3}}
\pgfpathmoveto{\pgfpoint@oncoil{1    }{ 1    }{3}}
% Uncomment the following lines to close the last loop
% \pgfpathcurveto
% {\pgfpoint@oncoil{1.555}{ 1    }{4}}
% {\pgfpoint@oncoil{2    }{ 0.555}{5}}
% {\pgfpoint@oncoil{2    }{ 0    }{6}}
% \pgfpathcurveto
% {\pgfpoint@oncoil{2    }{-0.555}{7}}
% {\pgfpoint@oncoil{1.555}{-1    }{8}}
% {\pgfpoint@oncoil{0    }{-1    }{9}}
}
\state{final}
{
\pgfpathmoveto{\pgfpointdecoratedpathlast}
}
}

% coildown decoration
%
% Parameters: \pgfdecorationsegmentamplitude, \pgfdecorationsegmentlength,

\pgfdeclaredecoration{coildown}{coil}
{
\state{coil}[switch if less than=%
1.5\pgfdecorationsegmentlength+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude to last,
width=+\pgfdecorationsegmentlength]
{
\pgfpathmoveto{\pgfpoint@oncoil{1    }{1    }{3}}
\pgfpathcurveto
{\pgfpoint@oncoil{1.555}{ 1    }{4}}
{\pgfpoint@oncoil{2    }{ 0.555}{5}}
{\pgfpoint@oncoil{2    }{ 0    }{6}}
\pgfpathcurveto
{\pgfpoint@oncoil{2    }{-0.555}{7}}
{\pgfpoint@oncoil{1.555}{-1    }{8}}
{\pgfpoint@oncoil{1    }{-1    }{9}}
}
\state{last}[width=.5\pgfdecorationsegmentlength+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
\pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude,next state=final]
{
% Comment the next 5 lines when closing the last loop
\pgfpathmoveto{\pgfpoint@oncoil{1    }{ 1    }{3}}
\pgfpathcurveto
{\pgfpoint@oncoil{1.555}{ 1    }{4}}
{\pgfpoint@oncoil{2    }{ 0.555}{5}}
{\pgfpoint@oncoil{2    }{ 0    }{6}}
}
\state{final}
{}
}

\def\pgfpoint@oncoil#1#2#3{%
\pgf@x=#1\pgfdecorationsegmentamplitude%
\pgf@x=\pgfdecorationsegmentaspect\pgf@x%
\pgf@y=#2\pgfdecorationsegmentamplitude%
\pgf@xa=0.083333333333\pgfdecorationsegmentlength%
}

\makeatother

\begin{document}

\begin{tikzpicture}
\draw [thin, decorate, decoration={coildown,
amplitude=3, segment length=1}, color=black]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\draw [double distance = 5, thin, double=white, color=white]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\draw [thin, decorate, decoration={coilup,
amplitude=3, segment length=1}, color=black]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\end{tikzpicture}
\begin{tikzpicture}
\draw [thin, decorate, decoration={coildown,
amplitude=3, segment length=1}, color=black]
(0,0) to (2,0);
\draw [double distance = 5, rounded corners, thin, double=white, color=white] (0,0) to (2,0);
\draw [thin, decorate, decoration={coilup,
amplitude=3, segment length=1}, color=black]
(0,0) to (2,0);
\end{tikzpicture}

\begin{tikzpicture}
\draw [thin, decorate, decoration={coildown,
amplitude=3, segment length=1}, color=green!40!yellow]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\draw [double distance = 5, thin, double=black!50!green,
color=black!50!green]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\draw [thin, decorate, decoration={coilup,
amplitude=3, segment length=1}, color=green!40!yellow]
(0,0) .. controls++(1,1) and (1,-1).. (2,0);
\end{tikzpicture}
\begin{tikzpicture}
\draw [thin, decorate, decoration={coildown,
amplitude=3, segment length=1}, color=green!40!yellow]
(0,0) to (2,0);
\draw [double distance = 5, rounded corners, thin,
double=black!50!green, color=black!50!green] (0,0) to (2,0);
\draw [thin, decorate, decoration={coilup,
amplitude=3, segment length=1}, color=green!40!yellow]
(0,0) to (2,0);
\end{tikzpicture}

\end{document}


If you use a white background it looks nice IMHO, but when using a colored background it looks a bit strange. Also, I didn't succeed to make the coil start from the bottom, as it would look nicer that way.

You need to comment/uncomment the parts indicated in the code if you want the las loop to be closed or not.

I hope this helps.

-
I know that this answer is almost identical to the one I cited. I decided to post it as maybe the OP can get some idea by seeing the pictures of what can he achieve with this method and decide wether he would like to spend some time perfectig it or not. –  Gustavo Aug 4 '12 at 21:40
You also can get a nice effect by only using half of the coil, something like (((((((((, but if the lines are close enough it looks good. –  Gustavo Aug 4 '12 at 21:44
Nice pictures. But never suggest to modify the original files of a package. Create your own TikZ library (as in the answer that you cite) or directly integrate this code in the preamble of a document (via \makeatletter ... \makeatother if necessary). –  Paul Gaborit Aug 5 '12 at 6:53
Thanks for the suggestion, I will correct my answer. –  Gustavo Aug 5 '12 at 7:10
If you prefix each of your states with \pgfsetcornersarced{\pgfpoint{0mm}{0mm}}, you can use path like [rounded corners=10mm] (0,0) -- (1,1) -- (2,-1) -- (3,0). –  Paul Gaborit Aug 5 '12 at 7:18

A promising alternative:

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-solides3d}
\begin{document}
\psset{unit=0.75}
\begin{pspicture}(-3,-3)(3,4)
\psset[pst-solides3d]{viewpoint=20 10 15,Decran=20,
lightsrc=20 10 10}
% Parametric Surfaces
\defFunction{helix}(u,v)
{1 .4 v Cos mul sub u Cos mul 2 mul}
{1 .4 v Cos mul sub u Sin mul 2 mul}
{.4 v Sin mul u .3 mul add}
\psSolid[object=surfaceparametree,linewidth=0.5\pslinewidth,
base=-10 10 0 6.28,fillcolor=yellow!50,incolor=green!50,
function=helix,
ngrid=60 0.4]%
\end{pspicture}

\end{document}

-