% Copyright 2019 by an anonymous marmot
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.
\ProvidesFileRCS{tikzlibrary3dtools.code.tex}
\usetikzlibrary{3d,decorations,fpu}% to do: ability to switch on and off
\usepackage{calculator}% maybe drop
\makeatletter%
\def\extractpgfversionaux#1.#2.#3|#4#5#6;{\def#4{#1}\def#5{#2}\def#6{#3}}%
\def\checkversion{%
\edef\temp{\noexpand\extractpgfversionaux\pgfversion|\noexpand\myu\noexpand\myv\noexpand\myw;}%
\temp%
\pgfmathtruncatemacro{\itest}{ifthenelse(10*\myu+\myv<31,0,1)}%
\ifnum\itest=0%
\message{You are using a too old version of pgf (\pgfversion). You need at least
version 3.1.1 to use the features of this library.}%
\fi}%
\checkversion%
\newcommand{\orthmat}[3]{% the entries of this matrix keep track
\pgfmathparse{cos(#1)*cos(#2)}% of the current transformation
\xdef\tikz@td@matAA{\pgfmathresult}%
\pgfmathparse{cos(#2)*sin(#1)}% 
\xdef\tikz@td@matAB{\pgfmathresult}% 
\pgfmathparse{sin(#2)}% 
\xdef\tikz@td@matAC{\pgfmathresult}%
\pgfmathparse{-cos(#3)*sin(#1)-cos(#1)*sin(#2)*sin(#3)}%
\xdef\tikz@td@matBA{\pgfmathresult}%  
\pgfmathparse{cos(#1)*cos(#3)-sin(#1)*sin(#2)*sin (#3)}% 
\xdef\tikz@td@matBB{\pgfmathresult}%
\pgfmathparse{cos(#2)*sin (#3)}%
\xdef\tikz@td@matBC{\pgfmathresult}%
\pgfmathparse{sin(#1)*sin(#3)-cos(#1)*cos(#3)*sin(#2)}%
\xdef\tikz@td@matCA{\pgfmathresult}% 
\pgfmathparse{-cos(#3)*sin(#1)*sin(#2)-cos(#1)*sin(#3)}% 
\xdef\tikz@td@matCB{\pgfmathresult}%
\pgfmathparse{cos(#2)*cos(#3)}%
\xdef\tikz@td@matCC{\pgfmathresult}}%
\tikzset{3d/.cd,phi/.initial=0,psi/.initial=0,theta/.initial=0,
install view/.style={/utils/exec=\tikzset{3d/.cd,#1}%
\orthmat{\pgfkeysvalueof{/tikz/3d/phi}}{%
\pgfkeysvalueof{/tikz/3d/psi}}{\pgfkeysvalueof{/tikz/3d/theta}},%
/tikz/x={({\tikz@td@matAA*1cm},{\tikz@td@matBA*1cm})},%
/tikz/y={({\tikz@td@matAB*1cm},{\tikz@td@matBB*1cm})},%
/tikz/z={({\tikz@td@matAC*1cm},{\tikz@td@matBC*1cm})}}}%
\def\pgfmathparse@td@FPU#1{\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{#1}%
\pgfmathsmuggle\pgfmathresult\endgroup}%
%
\newlength\pgf@X% not clear if one should use lengths here at all
\newlength\pgf@Y% 
\newlength\pgf@Z% 
\newlength\pgf@Xa% 
\newlength\pgf@Ya% 
\newlength\pgf@Za% 
\newlength\pgf@Xb% 
\newlength\pgf@Yb% 
\newlength\pgf@Zb% 
\xdef\tikz@td@type{0}%0=linear combination,1=vector product
\long\def\RawCoord(#1){\csname tikz@dcl@coord@#1\endcsname}% 
\long\def\ParseCoord(#1){%
\pgfutil@tempcnta=0%
\pgfutil@for\pgf@tmp:={#1}\do{\advance\pgfutil@tempcnta by1}%
\ifnum\the\pgfutil@tempcnta=1
\edef\pgfutil@tmp{\csname tikz@dcl@coord@#1\endcsname}% 
\else%
\edef\pgfutil@tmp{(#1)}%
\fi%
\pgfmathparse@td@FPU{xcomp3(\pgfutil@tmp)}% 
\pgf@X=\pgfmathresult pt% 
\pgfmathparse@td@FPU{ycomp3(\pgfutil@tmp)}% 
\pgf@Y=\pgfmathresult pt% 
\pgfmathparse@td@FPU{zcomp3(\pgfutil@tmp)}% 
\pgf@Z=\pgfmathresult pt}%
\pgfmathdeclarefunction{TD}{1}{%
\begingroup%
\pgfmathtdparse{#1}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
% projections 
\pgfmathdeclarefunction{xcomp3}{3}{% x component of a 3-vector 
\begingroup% 
\pgfmathparse@td@FPU{#1}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
\pgfmathdeclarefunction{ycomp3}{3}{% y component of a 3-vector 
\begingroup% 
\pgfmathparse@td@FPU{#2}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
\pgfmathdeclarefunction{zcomp3}{3}{% z component of a 3-vector 
\begingroup% 
\pgfmathparse@td@FPU{#3}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
\pgfmathdeclarefunction{TDx}{1}{% x component of a 3-vector 
\begingroup% 
\edef\mycoord{\RawCoord(#1)}%
\pgfmathparse@td@FPU{xcomp3\mycoord}% 
\pgfmathsmuggle\pgfmathresult\endgroup}%
\pgfmathdeclarefunction{TDy}{1}{% x component of a 3-vector 
\begingroup% 
\edef\mycoord{\RawCoord(#1)}%
\pgfmathparse@td@FPU{ycomp3\mycoord}% 
\pgfmathsmuggle\pgfmathresult\endgroup}%
\pgfmathdeclarefunction{TDz}{1}{% x component of a 3-vector 
\begingroup% 
\edef\mycoord{\RawCoord(#1)}%
\pgfmathparse@td@FPU{zcomp3\mycoord}% 
\pgfmathsmuggle\pgfmathresult\endgroup}%
\def\scalprod#1=#2.#3;{% 
\edef\coordA{\RawCoord#2}% 
\edef\coordB{\RawCoord#3}% 
\pgfmathsetmacro\pgfutil@tmpa{scalarproduct({\coordA},{\coordB})}% 
\edef#1{\pgfutil@tmpa}}% 
\def\spaux#1#2#3#4#5#6{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}% 
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors 
\begingroup% 
\pgfmathparse@td@FPU{\spaux#1#2}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
% vector product 
% vector product auxiliary functions 
\def\vpauxx#1#2#3#4#5#6{(#2)*(#6)-(#3)*(#5)}% 
\def\vpauxy#1#2#3#4#5#6{(#4)*(#3)-(#1)*(#6)}% 
\def\vpauxz#1#2#3#4#5#6{(#1)*(#5)-(#2)*(#4)}% 
% vector product pgf functions 
\pgfmathdeclarefunction{vpx}{2}{% x component of vector product 
\begingroup% 
\pgfmathparse@td@FPU{\vpauxx#1#2}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
\pgfmathdeclarefunction{vpy}{2}{% y component of vector product 
\begingroup% 
\pgfmathparse@td@FPU{\vpauxy#1#2}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
\pgfmathdeclarefunction{vpz}{2}{% z component of vector product 
\begingroup% 
\pgfmathparse@td@FPU{\vpauxz#1#2}% 
\pgfmathsmuggle\pgfmathresult\endgroup} 
%
%
% the following is very much "inspired" by the calc library 
\long\def\pgfmathtdparse#1{% < and > really are placeholders for a later integration
\begingroup% into calc, which however requires changes both in
% tikzlibrarycalc.code.tex and in tikz.code.tex
% 
% tdparse main computation. It's a series of optional factors in front 
% of coordinates. It is very much copied from the calc library. 
% 
\pgf@Xa=0pt% We accumulate the result in here. 
\pgf@Ya=0pt% 
\pgf@Za=0pt% 
\tikz@td@cc@parse+#1% 
}% 

\def\tikz@td@cc@parse{% 
\pgfutil@ifnextchar>{% 
% Ok, we found the end... 
\tikz@td@cc@end% 
} 
{\pgfutil@ifnextchar+{% 
% Ok, we found a coordinate... 
\tikz@td@cc@add% 
}{% 
\pgfutil@ifnextchar-{% 
\tikz@td@cc@sub% 
}{% 
\pgfutil@ifnextchar x{% 
\tikz@td@cc@vecprod% 
}{% 
\pgfutil@ifnextchar o{% 
\tikz@td@cc@scalprod% 
}{% \tikzerror{+ or - expected}% 
\tikz@td@cc@end%
}% 
}% 
}% 
}% 
}%
}%
% 
% The end is reached with > at the moment but this should change 
% 
\def\tikz@td@cc@end{% 
\ifcase\tikz@td@type%
\pgfmathsetmacro{\pgftemp@x}{\pgf@Xa}% 
\pgfmathsetmacro{\pgftemp@y}{\pgf@Ya}% 
\pgfmathsetmacro{\pgftemp@z}{\pgf@Za}% 
\edef\pgfmathresult{\pgftemp@x,\pgftemp@y,\pgftemp@z}%
\or%
\pgfmathsetmacro{\myxa}{\pgf@Xa}%
\pgfmathsetmacro{\myya}{\pgf@Ya}%
\pgfmathsetmacro{\myza}{\pgf@Za}%
\pgfmathsetmacro{\myxb}{\pgf@Xb}%
\pgfmathsetmacro{\myyb}{\pgf@Yb}%
\pgfmathsetmacro{\myzb}{\pgf@Zb}%
\pgfmathsetmacro{\pgftemp@x}{\vpauxx{\myxb}{\myyb}{\myzb}{\myxa}{\myya}{\myza}}% 
\pgfmathsetmacro{\pgftemp@y}{\vpauxy{\myxb}{\myyb}{\myzb}{\myxa}{\myya}{\myza}}% 
\pgfmathsetmacro{\pgftemp@z}{\vpauxz{\myxb}{\myyb}{\myzb}{\myxa}{\myya}{\myza}}% 
%\typeout{P1=(\myxb,\myyb,\myzb),P2=(\myxa,\myya,\myza),P1xP2=(\pgftemp@x,\pgftemp@y,\pgftemp@z)}%
\edef\pgfmathresult{\pgftemp@x,\pgftemp@y,\pgftemp@z}%
\or%
\pgfmathsetmacro{\myxa}{\pgf@Xa}%
\pgfmathsetmacro{\myya}{\pgf@Ya}%
\pgfmathsetmacro{\myza}{\pgf@Za}%
\pgfmathsetmacro{\myxb}{\pgf@Xb}%
\pgfmathsetmacro{\myyb}{\pgf@Yb}%
\pgfmathsetmacro{\myzb}{\pgf@Zb}%
\pgfmathparse@td@FPU{\myxa*\myxb+\myya*\myyb+\myza*\myzb}%
%\typeout{P1=(\myxb,\myyb,\myzb),P2=(\myxa,\myya,\myza),P1.P2=(\pgmfmathresult)}%
\fi%
%\message{result = (\pgftemp@x,\pgftemp@y,\pgftemp@z)=\pgfmathresult^^J}%
\xdef\tikz@td@type{0}% reset type to linear combination
\pgfmathsmuggle\pgfmathresult\endgroup}% 
% 
\def\tikz@td@cc@add+{% 
\def\tikz@td@cc@factor{1}% 
\tikz@td@cc@factororcoordinate% 
}% 
\def\tikz@td@cc@sub-{% 
\def\tikz@td@cc@factor{-1}% 
\tikz@td@cc@factororcoordinate% 
}% 
\def\tikz@td@cc@vecprod x{% 
%\message{Ah, a vector product^^J}%
\xdef\tikz@td@type{1}%
\pgf@Xb=\pgf@Xa% store current vector in b
\pgf@Yb=\pgf@Ya%
\pgf@Zb=\pgf@Za%
\pgf@Xa=0pt% reset a
\pgf@Ya=0pt%
\pgf@Za=0pt%
\def\tikz@td@cc@factor{1}%
\tikz@td@cc@factororcoordinate% 
}%
\def\tikz@td@cc@scalprod o{% 
%\message{Ah, a scalar product^^J}%
\xdef\tikz@td@type{2}%
\pgf@Xb=\pgf@Xa% store current vector in b
\pgf@Yb=\pgf@Ya%
\pgf@Zb=\pgf@Za%
\pgf@Xa=0pt% reset a
\pgf@Ya=0pt%
\pgf@Za=0pt%
\def\tikz@td@cc@factor{1}%
\tikz@td@cc@factororcoordinate% 
}%
% 
% Check for a factor: If we see a (, its a coordinate... 
% 
\def\tikz@td@cc@factororcoordinate{% 
\pgfutil@ifnextchar({%) 
% Ok, found coordinate 
\tikz@td@cc@coordinate% 
}{% 
\tikz@td@cc@parse@factor% 
}% 
}% 
% 
% ... otherwise it's a factor. It ends at ...*( 
% 
\def\tikz@td@cc@parse@factor#1*({% 
\pgfmathparse@td@FPU{#1*\tikz@td@cc@factor}% 
\let\tikz@td@cc@factor=\pgfmathresult% 
\tikz@td@cc@coordinate(%) 
}% 
\def\tikz@td@cc@coordinate(#1){% 
\ParseCoord(#1)% 
\advance\pgf@Xa by\tikz@td@cc@factor\pgf@X 
\advance\pgf@Ya by\tikz@td@cc@factor\pgf@Y 
\advance\pgf@Za by\tikz@td@cc@factor\pgf@Z 
\tikz@td@cc@parse% 
}% 
\tikzset{declare function={torusx(\u,\v,\R,\r)=cos(\u)*(\R + \r*cos(\v)); 
torusy(\u,\v,\R,\r)=(\R + \r*cos(\v))*sin(\u);
torusz(\u,\v,\R,\r)=\r*sin(\v);
vcrit1(\u,\th)=atan(tan(\th)*sin(\u));% first critical v value
vcrit2(\u,\th)=180+atan(tan(\th)*sin(\u));% second critical v value
vtest(\u,\v,\az,\el)=sin(-vcrit1(\u-\az,\el)+\v);
disc(\th,\R,\r)=((pow(\r,2)-pow(\R,2))*pow(cot(\th),2)+% 
pow(\r,2)*(2+pow(tan(\th),2)))/pow(\R,2);% discriminant
umax(\th,\R,\r)=ifthenelse(disc(\th,\R,\r)>0,asin(sqrt(abs(disc(\th,\R,\r)))),0);
}}%
%
\tikzset{3d parse/.style={/utils/exec=\pgfmathtdparse{#1},%
insert path={(\pgfmathresult)}},3d coordinate/.style args={#1=#2}{%
/utils/exec=\pgfmathtdparse{#2},%
insert path={(\pgfmathresult) coordinate #1}}}%
\def\pgfmathprintvector#1{%
\pgfutil@tempcnta=0%
\pgfutil@for\pgf@tmp:={#1}\do{\advance\pgfutil@tempcnta by1}%
\pgfutil@tempcntb=1%
\pgfutil@for\pgf@tmp:={#1}\do{\advance\pgfutil@tempcntb by1%
\ifnum\the\pgfutil@tempcntb<\the\pgfutil@tempcnta
\pgfmathprintnumber\pgf@tmp,%
\else
\pgfmathprintnumber\pgf@tmp
\fi}%
}%
%%
%% predefined pics
% based on https://en.wikipedia.org/wiki/Circumscribed_circle
\tikzset{pics/3d circle through 3 points/.style={code={%
 \tikzset{3d/circle through 3 points/.cd,#1}%
 \edef\temp{\noexpand\path[overlay,
 3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)=\pgfkeysvalueof{/tikz/3d/circle through 3 points/A}-\pgfkeysvalueof{/tikz/3d/circle through 3 points/C}},
 3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)=\pgfkeysvalueof{/tikz/3d/circle through 3 points/B}-\pgfkeysvalueof{/tikz/3d/circle through 3 points/C}},
 3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}c)=\pgfkeysvalueof{/tikz/3d/circle through 3 points/A}-\pgfkeysvalueof{/tikz/3d/circle through 3 points/B}},
  3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)=(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)x(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)}];}%
 \temp    
 \pgfmathsetmacro{\lengthn}{sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)"))}
 \ifdim\lengthn pt<0.02pt
   \message{The points are (almost) on a line. Circle cannot be determined.}
  \else
   \pgfmathsetmacro{\tmpradius}{sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)"))*%
   	sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)"))*sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}c)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}c)"))/%
		(2*\lengthn)}
   \pgfmathsetmacro{\coeffa}{-1*TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)")/(2*TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)"))}		
   \pgfmathsetmacro{\coeffb}{TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)")/(2*TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)"))}
   \edef\temp{%
   \noexpand\path[overlay,3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}u)=\coeffa*(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)x(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)},
     3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}v)=\coeffb*(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}b)x(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)}];
   \noexpand\path[3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/center name})=\pgfkeysvalueof{/tikz/3d/circle through 3 points/C}+(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}u)+(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}v)}];
   }%
   \temp
   \pgfmathsetmacro{\normalizationa}{1/sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)"))}
   \pgfmathsetmacro{\normalizationn}{1/sqrt(TD("(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)o(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)"))}
   \edef\temp{%
   \noexpand\path[overlay,3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)=\normalizationa*(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)},
   3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)=\normalizationn*(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)},
   3d coordinate={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}c)=(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)x(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}n)}];
   }%
   \temp
   \edef\temp{%
	\noexpand\begin{scope}[plane x={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}a)},plane y={(\pgfkeysvalueof{/tikz/3d/circle through 3 points/auxiliary coordinate prefix}c)},canvas is plane]
	 \noexpand\draw[pic actions] (\pgfkeysvalueof{/tikz/3d/circle through 3 points/center name}) circle[radius=\tmpradius];
	\noexpand\end{scope}}%
   \temp	
  \fi 
}},3d/circle through 3 points/.cd,A/.initial={(1,0,0)},B/.initial={(0,1,0)},
C/.initial={(0,0,1)},
auxiliary coordinate prefix/.initial=tmp,center name/.initial=M}%
%%
%% decorations
%% 
\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
\endinput
