35

If I draw a coil in tikz I usually do something like this:

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.pathmorphing,patterns}

\begin{document}

\begin{tikzpicture}
\draw[decoration={aspect=0.3, segment length=3.2mm, amplitude=3mm,coil},decorate,opacity=0.9] (1,0) -- (3,0);
\end{tikzpicture}
\end{document}

Which looks like this:

enter image description here

In some cases (for example in eletrodynamics) it might matter if the coil is right or left handed.

How can I modify the code above such that it looks like this:

enter image description here

If you have another, maybe better way to visualize the direction I am interested in it too.

  • 1
    The image quality of your second image is not very good. Can you clarify which aspect of it you'd like to replicate in your own image? There seem to be a change in line colour/line width as well as a small gap where the wire overlaps, but it is hard to see clearly in this pixelated image. – user36296 Sep 6 '18 at 12:43
  • It only matters in a schematic for transformers. One typically adds a dot toward one end of the coil to indicate polarity. – John Kormylo Sep 6 '18 at 12:52
  • @samcarter I want the line with change and the little gap. – Julia Sep 6 '18 at 13:27
  • Are you trying to draw DNAs by the way? :-) – pushpen.paul Jan 22 at 11:25
  • No, its about coils in EM-circuits for induction experiments. – Julia Feb 5 at 6:37
62

The starting point of all this is the code in pgflibrarydecorations.pathmorphing.code.tex. I acknowledge a comment by joojaa that pointed out that the halo was not quite right in the original answers. I also appreciate a comment by Robert Harvey, who encouraged me to clean up. What I did is to modify the coil decoration of the decorations.pathmorphing library. There is still a lot of room for improvement. The keys in the beginning allow you to adjust the color, opacity, width of coil and additional width of the halo, I hope the names I gave to these parameters are self-explanatory.

enter image description here

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{decorations.pathmorphing}
\pgfkeys{%
/pgf/decoration/.cd,
3d coil color/.store in=\TDCoilColor, 
3d coil color/.initial=black,
3d coil color=black,
3d coil width/.store in=\TDCoilWidth, 
3d coil width/.initial=0.4pt,
3d coil width=0.4pt,
3d coil dist/.store in=\TDCoilDist, 
3d coil dist/.initial=0.6pt,
3d coil dist=0.6pt,
3d coil opacity/.store in=\TDCoilOpacity, 
3d coil opacity/.initial=1,
3d coil opacity=1
}

\makeatletter % https://tex.stackexchange.com/a/219088/121799
\tikzset{get stroke color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedstrokecolor% Jump we have \global\let\pgf...
    \csname\string\color@pgfstrokecolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
    restore stroke color/.code={\pgf@setstrokecolor#1},
}
\def\pgfpoint@onthreedcoil#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%
  \advance\pgf@x by-\initialoffset pt%
}

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

\pgfdeclaredecoration{3d coil}{initial}
{ 
    \state{initial}[width=0.25*\pgfdecorationsegmentlength+\pgfdecorationsegmentaspect*\pgfdecorationsegmentamplitude,
    next state=coil, persistent precomputation={
    \tikzset{get stroke color}
    \pgfmathsetmacro{\initialoffset}{0.25*\pgfdecorationsegmentlength+\pgfdecorationsegmentaspect*\pgfdecorationsegmentamplitude}
  }]
  {%
    \pgfpathmoveto{\pgfpointorigin} 
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfsetlinewidth{1.5*\TDCoilWidth} 
    \pgfpathcurveto
    {\pgfpoint@oncoil{0    }{ 0.555}{1}}
    {\pgfpoint@oncoil{0.445}{ 1    }{2}}
    {\pgfpoint@oncoil{1    }{ 1    }{3}}
    \pgfusepath{stroke}
    \pgfcoordinate{TD@coilast}{\pgfpoint@oncoil{1    }{ 1    }{3}} 
    }
  \state{coil}[switch if less than=%
    1.25\pgfdecorationsegmentlength+%
    \pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
    \pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude to last,
               width=+\pgfdecorationsegmentlength]
    { % line in the back
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpointanchor{TD@coilast}{center}}
    \pgfsetlinewidth{\TDCoilWidth} 
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{1.555}{ 1    }{4}}
    {\pgfpoint@onthreedcoil{2    }{ 0.555}{5}}
    {\pgfpoint@onthreedcoil{2    }{ 0    }{6}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{2    }{-0.555}{7}}
    {\pgfpoint@onthreedcoil{1.555}{-1    }{8}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke} 
    %
    % white background for front thick part
    %
    \pgfsetstrokeopacity{1}
    \pgfsetstrokecolor{white}
    \pgfsetfillcolor{white}
    \pgfsetlinewidth{1.5*\TDCoilWidth+1.5*\TDCoilDist}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    % draw forward
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} 
    % 
    % draw the thick foreground path
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
    \pgfsetlinewidth{\TDCoilWidth} 
    % forward shifted +
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back shfted -
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} % <- added
    \pgfcoordinate{TD@coilast}{\pgfpoint@onthreedcoil{1    }{ 1    }{15}} 
  }
  \state{last}[width=.25\pgfdecorationsegmentlength+%
    \pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude+%
    \pgfdecorationsegmentaspect\pgfdecorationsegmentamplitude,next state=final]
  {
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfsetlinewidth{\TDCoilWidth}
    \pgfpathmoveto{\pgfpointanchor{TD@coilast}{center}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{1.555}{ 1    }{4}}
    {\pgfpoint@onthreedcoil{2    }{ 0.555}{5}}
    {\pgfpoint@onthreedcoil{2    }{ 0    }{6}}
  }
  \state{final}
  {
    \pgfpathlineto{\pgfpointdecoratedpathlast}
    \pgfusepath{stroke}
    \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\draw[decoration={3d coil color=blue,aspect=0.35, segment length=3.1mm, amplitude=3mm,3d coil},
decorate] (0,0) -- (0,3);
\draw[decoration={3d coil color=red,3d coil opacity=0.9,aspect=0.45, segment length=3.1mm, amplitude=3mm,3d coil},
decorate] (2,3) -- (2,0);
\draw[decoration={3d coil color=green!60!black,3d coil opacity=0.9,aspect=0.35, segment length=3.1mm, amplitude=3mm,3d coil},
decorate] (4,3) to[out=0,in=90] (6,0);
\end{tikzpicture}
\end{document}

FUN: The mandatory animation can be made with the same preamble + \usepackage{tikzmarmots} and

\begin{document}
\foreach \X [evaluate=\X as \Y using {sin(\X)}]in {0,10,...,350}
{
\begin{tikzpicture}
\path[use as bounding box] (-1,-0.2) rectangle (1,4);
\draw[decoration={3d coil color=blue,aspect=0.35, segment
length={(1.2+0.7*\Y)*1mm}, amplitude=3mm,3d coil},
decorate] (0,0) -- (0,2);
\begin{scope}[shift={(-0.9,1+0.5*\Y)}]
\marmot[teeth,whiskers]
\end{scope}
\end{tikzpicture}}
\end{document}

enter image description here

BONUS: A "complete" version, i.e. an analog of Jake's complete sines with a "closed" option (analogous to the closed zigzags.)

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{decorations.pathmorphing}
\makeatletter
\newif\ifcoil@closed
\pgfkeys{%
/pgf/decoration/.cd,
3d coil color/.store in=\TDCoilColor, 
3d coil color/.initial=black,
3d coil color=black,
3d coil width/.store in=\TDCoilWidth, 
3d coil width/.initial=0.4pt,
3d coil width=0.4pt,
3d coil dist/.store in=\TDCoilDist, 
3d coil dist/.initial=0.6pt,
3d coil dist=0.6pt,
3d coil opacity/.store in=\TDCoilOpacity, 
3d coil opacity/.initial=1,
3d coil opacity=1,
3d coil closed/.code=\coil@closedtrue
}

 % https://tex.stackexchange.com/a/219088/121799
\tikzset{get stroke color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedstrokecolor% Jump we have \global\let\pgf...
    \csname\string\color@pgfstrokecolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
    restore stroke color/.code={\pgf@setstrokecolor#1},
}
\def\pgfpoint@onthreedcoil#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%
  \advance\pgf@x by-\generaloffset pt%
}

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

\pgfdeclaredecoration{3d complete coil}{initial}
{ 
    \state{initial}[width=0.5*\pgfdecorationsegmentlength,
    next state=coil, persistent precomputation={% from https://tex.stackexchange.com/a/25689/121799
    \pgfmathsetmacro\matchinglength{\pgfdecoratedinputsegmentlength / int(\pgfdecoratedinputsegmentlength/\pgfdecorationsegmentlength)}
    \setlength{\pgfdecorationsegmentlength}{\matchinglength pt}
    \tikzset{get stroke color}
    \pgfmathsetmacro{\generaloffset}{\pgfdecorationsegmentlength}
    \pgfmathsetmacro{\initialoffset}{1.5*\pgfdecorationsegmentlength}
    \pgfmathsetmacro{\auxoffset}{2.5*\pgfdecorationsegmentlength}
  }]    { 
    % line in the back
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfsetlinewidth{\TDCoilWidth}     
    \ifcoil@closed
     \begingroup
      \def\generaloffset{\auxoffset}
      \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
      \pgfpathcurveto
      {\pgfpoint@onthreedcoil{1.555}{ 1    }{16}}
      {\pgfpoint@onthreedcoil{2    }{ 0.555}{17}}
      {\pgfpoint@onthreedcoil{2    }{ 0    }{18}}
      \pgfcoordinate{TD@coilast}{\pgfpoint@onthreedcoil{2    }{ 0    }{18}}
      \pgfcoordinate{TD@coilfirst}{\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
      \pgfusepath{stroke} 
      \pgfsetstrokecolor{\TDCoilColor}
     \endgroup
    \fi
    \begingroup %
    \def\generaloffset{\initialoffset}
    \ifcoil@closed
     \pgfpathmoveto{\pgfpointanchor{TD@coilast}{center}}
    \else
     \pgfpathmoveto{\pgfpointorigin}
    \fi
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{2    }{-0.555}{7}}
    {\pgfpoint@onthreedcoil{1.555}{-1    }{8}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke} 
    %
    % white background for front thick part
    %
    \pgfsetstrokeopacity{1}
    \pgfsetstrokecolor{white}
    \pgfsetfillcolor{white}
    \pgfsetlinewidth{1.5*\TDCoilWidth+1.5*\TDCoilDist}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    % draw forward
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} 
    % 
    % draw the thick foreground path
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
    \pgfsetlinewidth{\TDCoilWidth} 
    % forward shifted +
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back shfted -
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} 
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{1.555}{ 1    }{16}}
    {\pgfpoint@onthreedcoil{2    }{ 0.555}{17}}
    {\pgfpoint@onthreedcoil{2    }{ 0    }{18}}
    \pgfcoordinate{TD@coilast}{\pgfpoint@onthreedcoil{2    }{ 0    }{18}} 
    \pgfusepath{stroke}     
    \endgroup
  }
  \state{coil}[switch if less than=%
    1.9*\pgfdecorationsegmentlength  to last,
               width=+\pgfdecorationsegmentlength]
    { % line in the back
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpointanchor{TD@coilast}{center}}
    \pgfsetlinewidth{\TDCoilWidth} 
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{2    }{-0.555}{7}}
    {\pgfpoint@onthreedcoil{1.555}{-1    }{8}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke} 
    %
    % white background for front thick part
    %
    \pgfsetstrokeopacity{1}
    \pgfsetstrokecolor{white}
    \pgfsetfillcolor{white}
    \pgfsetlinewidth{1.5*\TDCoilWidth+1.5*\TDCoilDist}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    % draw forward
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} 
    % 
    % draw the thick foreground path
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
    \pgfsetlinewidth{\TDCoilWidth} 
    % forward shifted +
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
    {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    % draw the curve back shfted -
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
    {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
    {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
    {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke,fill} 
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{1.555}{ 1    }{16}}
    {\pgfpoint@onthreedcoil{2    }{ 0.555}{17}}
    {\pgfpoint@onthreedcoil{2    }{ 0    }{18}}
    \pgfusepath{stroke} 
    \pgfcoordinate{TD@coilast}{\pgfpoint@onthreedcoil{2    }{ 0    }{18}} 
  }
  \state{last}[next state=final]
    { % line in the back
    %
    \pgfsetstrokecolor{\TDCoilColor}
    \pgfsetfillcolor{\TDCoilColor}
    \pgfsetstrokeopacity{\TDCoilOpacity}
    \pgfpathmoveto{\pgfpointanchor{TD@coilast}{center}}
    \pgfsetlinewidth{\TDCoilWidth} 
    \pgfpathcurveto
    {\pgfpoint@onthreedcoil{2    }{-0.555}{7}}
    {\pgfpoint@onthreedcoil{1.555}{-1    }{8}}
    {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
    \pgfusepath{stroke} 
    % 
    % draw the thick foreground path
    %
    \ifcoil@closed %\pgfpointanchor{TD@coilfirst}{center}
     %
     % white background for front thick part
     %
     \pgfsetstrokeopacity{1}
     \pgfsetstrokecolor{white}
     \pgfsetfillcolor{white}
     \pgfsetlinewidth{1.5*\TDCoilWidth+1.5*\TDCoilDist}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     % draw forward
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
     {\pgfpointanchor{TD@coilfirst}{center}}
     % draw the curve back
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfusepath{stroke,fill} 
     \pgfsetstrokecolor{\TDCoilColor}
     \pgfsetfillcolor{\TDCoilColor}
     \pgfsetstrokeopacity{\TDCoilOpacity}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
     \pgfsetlinewidth{\TDCoilWidth} 
     % forward shifted +
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
     {\pgfpointanchor{TD@coilfirst}{center}}
     % draw the curve back shifted 
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfusepath{stroke,fill} 
    \else
     %
     % white background for front thick part
     %
     \pgfsetstrokeopacity{1}
     \pgfsetstrokecolor{white}
     \pgfsetfillcolor{white}
     \pgfsetlinewidth{1.5*\TDCoilWidth+1.5*\TDCoilDist}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     % draw forward
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
     {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
     % draw the curve back
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfusepath{stroke,fill} 
     \pgfsetstrokecolor{\TDCoilColor}
     \pgfsetfillcolor{\TDCoilColor}
     \pgfsetstrokeopacity{\TDCoilOpacity}
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{3}}
     \pgfsetlinewidth{\TDCoilWidth} 
     % forward shifted +
     \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{0    }{-0.555}{11.25}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{12.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{13.25}}
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14.25}}
     {\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
     % draw the curve back shifted 
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0.445}{ 1    }{14}}
     {\pgfpoint@onthreedcoil{0    }{ 0.555}{12.75}}
     {\pgfpoint@onthreedcoil{0    }{ 0    }{11.5}}
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{0    }{-0.555}{10.75}}
     {\pgfpoint@onthreedcoil{0.445}{-1    }{10}}
     {\pgfpoint@onthreedcoil{1    }{-1    }{9}}
     \pgfusepath{stroke,fill} 
    \fi
    \pgfpathmoveto{\pgfpoint@onthreedcoil{1    }{ 1    }{15}}
    \ifcoil@closed %TD@coilfirst
    \else
     \pgfpathcurveto
     {\pgfpoint@onthreedcoil{1.555}{ 1    }{16}}
     {\pgfpoint@onthreedcoil{2    }{ 0.555}{17}}
     {\pgfpoint@onthreedcoil{2    }{ 0    }{18}}
    \fi
    \pgfusepath{stroke} 
    %\pgfcoordinate{TD@coilast}{\pgfpoint@onthreedcoil{2    }{ 0    }{18}} 
  }
  \state{final}
  {
    \pgfpathmoveto{\pgfpointdecoratedpathlast}
    \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\draw[decoration={3d coil color=red,aspect=0.35, segment length=3.1mm, 
amplitude=3mm,3d complete  coil},
decorate] (0,1) -- (0,6);
\draw[decoration={3d coil color=blue,3d coil opacity=0.9,aspect=0.5, 
segment length={2*pi*3cm/50}, amplitude=5mm,3d complete coil,
3d coil closed},
decorate] (5,3.5) circle (3);
\draw[decoration={3d coil color=green!60!black,aspect=0.5, segment length=3.1mm, 
amplitude=4mm,3d complete  coil},
decorate] (0,-1) -- (0,-6);
\draw[decoration={3d coil color=purple,3d coil opacity=0.9,aspect=0.5, 
segment length={2*pi*3cm/50}, amplitude=3mm,3d complete coil,
3d coil closed},
decorate] (5,-3.5) circle (3);
\end{tikzpicture}
\end{document}

enter image description here

  • 7
    The decorations in pgf, it's the most difficult, wonderful work, bravo! – AndréC Sep 6 '18 at 16:05
  • @AndréC Merci, but I am actually not really happy, What I would love to achieve is that it is not necessary to set the color, opacity and so on explicitly. And then there are more downsides. Assume I was able to achieve this, then the decomposition of the path in little segments has further downsides such as the fact that a dashed line will not look nice. So there is a lot of room for improvement... – marmot Sep 6 '18 at 16:09
  • 4
    Another beautiful piece of marmot magic! – Max Sep 7 '18 at 18:04
  • 1
    @Diaa Coil has a straight line because the length of one coil (i.e. the segment length) does not divide the length of the path. Coil2 uses a different approach in which the length of the coil is set to be 1/10 of the length of the path, which is why there is no straight line piece. To overcome the problem of leftovers you may use Jake's complete sines. – marmot Dec 17 '18 at 22:39
  • 1
    @Diaa One would have to rewrite the style. The "problem" (I use parentheses because this is not at all a criticism of the nice macros) is that the path starts with an offset. If you replace in his code (90: 0.2 and 0.4) by (90: 0.2 and 0.4) coordinate(coilaux1-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) and (0,0)++(90: 0.2 and 0.4) by (0,0)++(90: 0.2 and 0.4) coordinate(coilaux0-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}), you can access the start as (coilaux0-1) and the end as (coilaux1-n) with an appropriate n. – marmot Dec 17 '18 at 23:20
28

If you put negative values for aspect and amplitude, you can get the mirrored coil, add this in the @marmot's answer may complete the desired output; also I added an option using markings to get some similar drawing that uses scope and yscale to invert the marking, then a new variable to control the coil color,when the path is straight it has good result, markings path lacks bending good results.

EDIT: Added a control for marking step to improve bending results.

RESULT:

enter image description here

MWE:

\documentclass[tikz,border=20pt]{standalone}
\usetikzlibrary{decorations.pathmorphing,decorations.markings}

\begin{document}

\begin{tikzpicture}[
    CoilColor/.store in=\coilcolor,CoilColor=black,
    Step/.store in=\Step,Step=0.1,
    Coil/.style={
        double=black,
        draw=gray!50,
        decoration={
            #1,
            segment length=3mm,
            coil
            },
            decorate,
    },
    Coil2/.style={
        decorate,
        decoration={
            markings,
            mark= between positions 0 and 1 step \Step
            with {
                \begin{scope}[yscale=#1]
                \draw[xshift=9.2,fill,\coilcolor!70!black]
                    (0,0)++(-135: 0.2 and 0.4) 
                        .. controls +(-0.2,0) and +(-0.3,0) .. (90: 0.2 and 0.4)
                        .. controls +(-0.33,0) and +(-0.23,0) .. (-135: 0.2 and 0.4);                       
                \draw[white,line width=2pt]
                    (0,0)++(90: 0.2 and 0.4) 
                        .. controls +(0.3,0) and +(0.2,0) .. (-45: 0.2 and 0.4);
                \draw[fill=\coilcolor,\coilcolor]
                    (0,0)++(90: 0.2 and 0.4) 
                        .. controls +(0.3,0) and +(0.2,0) .. (-45: 0.2 and 0.4)
                        .. controls +(0.25,0) and +(0.35,0) .. (90: 0.2 and 0.4);
                \end{scope}                     
                    }
              }
        }
]
\draw[Coil={aspect=-0.3,amplitude=-3mm},blue] (0,0) -- ++ (0,-3);
\draw[Coil={aspect=0.3,amplitude=3mm},red] (1.5,0) -- ++ (0,-3);
\draw[Coil={aspect=0.3,amplitude=3mm},green!50!black] (3,0) arc (90:0:3);
\draw[Coil={aspect=-0.3,amplitude=-3mm}] (3,1) arc (90:0:4);

\draw[Coil2=-1,CoilColor=blue] (0,-4) -- ++ (0,-3);
\draw[Coil2=1,CoilColor=red] (1.5,-4) -- ++ (0,-3);
\draw[Coil2=-1,CoilColor=green!50!black,Step=0.065] (3,-4) arc (90:0:3);
\draw[Coil2=1,Step=0.048] (3,-3) arc (90:0:4);

\end{tikzpicture}
\end{document}

UPDATE: Acording to @marmot's suggestion closing the gaps and drawing all the variations, using \pgfdecoratedpathlength, /pgf/decoration/mark info/sequence number.

RESULT: enter image description here

MWE:

\documentclass[tikz,border=20pt]{standalone}
\usetikzlibrary{decorations.markings}

\begin{document}

\begin{tikzpicture}[
    CoilColor/.store in=\coilcolor,CoilColor=black,
    Step/.store in=\Step,Step=0.1,
    Width/.store in=\Width,Width=0.4,
    Coil2/.style={
        decorate,
        decoration={
            markings,
            mark= between positions 0 and 1 step \Step 
            with {
                \begin{scope}[yscale=#1]
                    \pgfmathparse{int(\pgfdecoratedpathlength/28.45*100*\Step)}
                    \edef\Hight{\pgfmathresult}
                    \ifnum\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}=1
                        \path (0,0)++(90: \Hight/200 and \Width) coordinate (b);
                    \fi
                    \ifnum\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}>1
                        \coordinate (b) at (d);
                    \fi
                    \path (b) arc (90:-135: \Hight/200 and \Width) coordinate (a);
                    \path (b) arc (90:-45: \Hight/200 and \Width) coordinate (c);
                    \path (b)++(\Hight/100,0) coordinate (d);
                    \draw[fill,\coilcolor!70!black]
                        (c)
                            .. controls +(-0.175,0) and +(-0.275,0) .. (d)
                            .. controls +(-0.325,0) and +(-0.225,0) .. (c);
                    \draw[white,line width=2pt]
                        (b)
                            .. controls +(0.3,0) and +(0.2,0) .. (c);
                    \draw[fill,\coilcolor]
                        (b)
                            .. controls +(0.275,0) and +(0.175,0) .. (c)
                            .. controls +(0.225,0) and +(0.325,0) .. (b);
                \end{scope}
            }
        }
    }
]

\draw[Coil2=-1,CoilColor=red,Step=0.15] (0.5,0) -- ++ (0,-3);
\draw[Coil2=1.5,CoilColor=magenta] (1.5,0) -- ++ (0,-3);

\draw[Coil2=1,CoilColor=green!70!black,Step=0.02] (0,-4) 
    to [in=90,out=0] ++(2.5,-1)
    to [in=180,out=-90] ++(2.5,-1)
    to [in=-90,out=0] ++(2,1.5)
    to [in=-90,out=90] ++(0.5,3) arc (0:90:2);

\draw[Coil2=-1,CoilColor=green!50!cyan,Step=0.02] (0,-5) 
    to [in=90,out=0] ++(1.5,-1)
    to [in=180,out=-90] ++(4,-1)
    to [in=-90,out=0] ++(3,2.5)
    to [in=-90,out=90] ++(0.5,4.5) arc (0:90:2);

\draw[Coil2=1,CoilColor=cyan!30!blue,Step=0.05] (5.7,-2) arc (360:0:1.5);
\draw[Coil2=-1,CoilColor=cyan!70!blue,Step=0.05] (6.5,-2) arc (360:0:1.5);

\end{tikzpicture}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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