13

Hi everybody I was trying to draw a spiral coiled tube

enter image description here

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   }}
    \pgfpathquadraticcurveto{\pgfpoint{.6cm   }{.5cm   }}{\pgfpoint{0cm   }{0cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.1cm   }}{\pgfpoint{.5cm   }{0cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{1.2cm   }{.5cm   }}{\pgfpoint{.5cm   }{1cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.9cm   }}{\pgfpoint{0cm}{1cm}}
    \pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
    } 
\state{mynext}[width=5mm]{
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.1cm   }}{\pgfpoint{.5cm   }{0cm   }}\pgfpathquadraticcurveto{\pgfpoint{1.2cm   }{.5cm   }}{\pgfpoint{.5cm   }{1cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.9cm   }}{\pgfpoint{0cm}{1cm}}
    \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}

enter image description here

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 enter image description here

7
  • \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/…
    – bodo
    Jul 27, 2012 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, 2012 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, 2012 at 12:21
  • Allowing multiple bounties from multiple users at the same time might be an interesting game. Aug 3, 2012 at 18:25
  • 2
    This may help. tex.stackexchange.com/a/43605/16062
    – Gustavo
    Aug 4, 2012 at 12:56

3 Answers 3

5

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   }}
    \pgfpathquadraticcurveto{\pgfpoint{.6cm   }{.5cm  
}}{\pgfpoint{0cm   }{0cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.1cm  
}}{\pgfpoint{.5cm   }{0cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{1.2cm   }{.5cm  
}}{\pgfpoint{.5cm   }{1cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.9cm  
}}{\pgfpoint{0cm}{1cm}}
    \pgfpathmoveto{\pgfpoint{.5cm   }{0cm   }}
    \pgfcoordinate{coil-tmp}{\pgfpoint{.5cm}{1cm}}
    } 
\state{mynext}[width=5mm]{
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.1cm  
}}{\pgfpoint{.5cm   }{0cm   }}\pgfpathquadraticcurveto{\pgfpoint{1.2cm  
}{.5cm   }}{\pgfpoint{.5cm   }{1cm   }}
    \pgfpathquadraticcurveto{\pgfpoint{.25cm   }{.9cm  
}}{\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:

Joined-up spiral

1
  • 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. Aug 9, 2012 at 8:40
12
+300

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:

enter image description here

enter image description here

\documentclass{article}

\usepackage{tikz}

\usetikzlibrary{decorations.pathmorphing}

\makeatletter

% Decorations based on
% https://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%
  \advance\pgf@x by#3\pgf@xa%
}

\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.

6
  • 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, 2012 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, 2012 at 21:44
  • 2
    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). Aug 5, 2012 at 6:53
  • 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). Aug 5, 2012 at 7:18
  • It seems I am confused, I could not make that work. Also, using that approach, I guess one would also need to incorporate parameters like segment length, amplitude and so on to have control over the appearance of the tube, am I right?
    – Gustavo
    Aug 5, 2012 at 7:41
6

A promising alternative:

enter image description here

\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}

You must log in to answer this question.

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