I want to draw something like the following in TikZ, but, unfortunately, I'm not sure how to get to the needed result. The figure shows the path of ions in a quadrupole mass spectrometer. Outside the quadrupole (those 4 rods) no electromagnetic field applies to the ions and thus they fly in a straight line. If they enter the quadrupole they can either come into resonance with the electromagnetic field and thus be on a cylindrical spiral path or not be in resonance and thus be on a conical spiral path and sooner or later exit the quadrupole at a side.
My take to this problem was to use pgfplots to draw the spirals using a 3D plot with the function {x*cos(deg(x))},{x*sin(deg(x)},{x} for the conical plot and {cos(deg(x))},{sin(deg(x)},{x} for the cylindrical one. Unfortunately, I find myself unable to solve the following issues:
- correctly position the spirals
- draw a straight line that transforms into a spiral and then back to a straight line after exiting the quadrupole (only for the cylindrical one)
- stop the conical helix shortly after the path has exited the quadrupole
I'm well aware that this is quite a lot of issues and thus I'm happy for any hints.
My current (miserable) attempt
\documentclass{standalone}
\usepackage{xparse}
\usepackage{ifthen}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{tikzpicture}
% General constants
% %%%%%%%%%%%%%%%%%
\coordinate (msOrigin) at (0,0);
\pgfmathsetmacro{\msY}{3}
\pgfmathsetmacro{\offsetX}{0.3}
\pgfmathsetmacro{\offsetY}{0.2}
\pgfmathsetmacro{\spacer}{0.75}
\pgfmathsetmacro{\arrowLength}{1}
\pgfmathsetmacro{\centerOffset}{0.3}
% Quadrupole constants
% %%%%%%%%%%%%%%%%%%%%
\pgfmathsetmacro{\quadrupoleRadiusHorizontal}{0.08}
\pgfmathsetmacro{\quadrupoleRadiusVertical}{0.2}
\pgfmathsetmacro{\quadrupoleLength}{3}
\pgfmathsetmacro{\quadrupolePathLength}{\quadrupoleLength - (2 * \quadrupoleRadiusHorizontal)}
\pgfmathsetmacro{\quadrupoleTopFrontY}{0.5 * \msY + \centerOffset + 2 * \quadrupoleRadiusVertical}
\pgfmathsetmacro{\quadrupoleTopBackY}{\quadrupoleTopFrontY + \offsetY}
\pgfmathsetmacro{\quadrupoleBottomBackY}{0.5 * \msY - \centerOffset}
\pgfmathsetmacro{\quadrupoleBottomFrontY}{\quadrupoleBottomBackY - \offsetY}
\NewDocumentCommand{\cylinder}{m m m m m m m m}{% coordX, coordY, length, radiusX, radiusY, colorCylinder, colorEllipse, opacity
\fill [#6, fill opacity = #8]
($ (msOrigin) + ({#1},{#2}) $)
--
++({#3},0)
arc
(90:270:-{#4} and {#5})
--
++(-{#3},0)
arc
(270:90:-{#4} and {#5});
\draw [fill = #7, fill opacity = #8]
($ (msOrigin) + ({#1},{#2}) + (0,{-#5}) $)
ellipse
({#4} and {#5});
\draw
($ (msOrigin) + ({#1},{#2}) $)
--
++({#3},0)
arc
(90:270:-{#4} and {#5})
--
++(-{#3},0);
}
\NewDocumentCommand{\quadrupoleRod}{m m m}{% segment, top/bottom, front/back
\ifthenelse{\equal{#2}{top} \AND \equal{#3}{front}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal + \offsetX}
\pgfmathsetmacro{\coordY}{\quadrupoleTopFrontY}
}{}
\ifthenelse{\equal{#2}{top} \AND \equal{#3}{back}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal}
\pgfmathsetmacro{\coordY}{\quadrupoleTopBackY}
}{}
\ifthenelse{\equal{#2}{bottom} \AND \equal{#3}{front}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal + \offsetX}
\pgfmathsetmacro{\coordY}{\quadrupoleBottomFrontY}
}{}
\ifthenelse{\equal{#2}{bottom} \AND \equal{#3}{back}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal}
\pgfmathsetmacro{\coordY}{\quadrupoleBottomBackY}
}{}
\cylinder
{\coordX}
{\coordY}
{\quadrupolePathLength}
{\quadrupoleRadiusHorizontal}
{\quadrupoleRadiusVertical}
{gray}
{white}
{1}
}
\NewDocumentCommand{\quadrupolePair}{m m}{% segment, front/back
\ifthenelse{\equal{#2}{front} \OR \equal{#2}{back}}{%
\quadrupoleRod{#1}{top}{#2}
\quadrupoleRod{#1}{bottom}{#2}
}{}
}
\quadrupolePair{1}{back}
\begin{axis}[
rotate around={-90:(current axis.origin)},
view = {30}{20},
axis line style = {draw = none},
tick style = {draw = none},
zmax = 60,
xtick=\empty,
ytick=\empty,
ztick=\empty
]
\addplot3+[
mark = none,
thick,
red,
domain = 0:50*pi,
samples = 1000,
samples y = 0,
]
% ({x*cos(deg(x))},{x*sin(deg(x)},{x});
({cos(deg(x))},{sin(deg(x)},{x});
\end{axis}
\quadrupolePair{1}{front}
\end{tikzpicture}
\end{document}
Update 2020-11-26
I found this answer on TeX.SX helping to draw the cylindrical coil. By some modifications, I was able to get relatively far in the process. One remaining issue is the line connecting the horizontal path with the spiral as the code mark=at position #1 with \coordinate (#2); throws a Dimension too large. error, even if I don't understand why. The coils are small and definitely below 19 feet...
Another issue that remains is the conical spiral. I have a starting point, but unfortunately, it looks gross.
\documentclass{standalone}
\usepackage{xparse}
\usepackage{ifthen}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings}
\tikzset{
mark position/.style args={#1(#2)}{
postaction={
decorate,
decoration={
markings,
mark=at position #1 with \coordinate (#2);
}
}
}
}
\NewDocumentCommand{\cylinder}{m m m m m m m m}{% coordX, coordY, length, radiusX, radiusY, colorCylinder, colorEllipse, opacity
\fill [#6, fill opacity = #8]
($ (msOrigin) + ({#1},{#2}) $)
--
++({#3},0)
arc
(90:270:-{#4} and {#5})
--
++(-{#3},0)
arc
(270:90:-{#4} and {#5});
\draw [fill = #7, fill opacity = #8]
($ (msOrigin) + ({#1},{#2}) + (0,{-#5}) $)
ellipse
({#4} and {#5});
\draw
($ (msOrigin) + ({#1},{#2}) $)
--
++({#3},0)
arc
(90:270:-{#4} and {#5})
--
++(-{#3},0);
}
\NewDocumentCommand{\quadrupoleRod}{m m m}{% segment, top/bottom, front/back
\ifthenelse{\equal{#2}{top} \AND \equal{#3}{front}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal + \offsetX}
\pgfmathsetmacro{\coordY}{\quadrupoleTopFrontY}
}{}
\ifthenelse{\equal{#2}{top} \AND \equal{#3}{back}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal}
\pgfmathsetmacro{\coordY}{\quadrupoleTopBackY}
}{}
\ifthenelse{\equal{#2}{bottom} \AND \equal{#3}{front}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal + \offsetX}
\pgfmathsetmacro{\coordY}{\quadrupoleBottomFrontY}
}{}
\ifthenelse{\equal{#2}{bottom} \AND \equal{#3}{back}}{%
\pgfmathsetmacro{\coordX}{\quadrupoleRadiusHorizontal}
\pgfmathsetmacro{\coordY}{\quadrupoleBottomBackY}
}{}
\cylinder
{\coordX}
{\coordY}
{\quadrupolePathLength}
{\quadrupoleRadiusHorizontal}
{\quadrupoleRadiusVertical}
{gray}
{white}
{1}
}
\NewDocumentCommand{\quadrupolePair}{m m}{% segment, front/back
\ifthenelse{\equal{#2}{front} \OR \equal{#2}{back}}{%
\quadrupoleRod{#1}{top}{#2}
\quadrupoleRod{#1}{bottom}{#2}
}{}
}
\begin{document}
% General constants
% %%%%%%%%%%%%%%%%%
\pgfmathsetmacro{\offsetX}{0.5}
\pgfmathsetmacro{\offsetY}{0.6}
\pgfmathsetmacro{\spacer}{0.75}
\pgfmathsetmacro{\centerOffset}{0.3}
% Quadrupole constants
% %%%%%%%%%%%%%%%%%%%%
\pgfmathsetmacro{\quadrupoleRadiusHorizontal}{0.08}
\pgfmathsetmacro{\quadrupoleRadiusVertical}{0.2}
\pgfmathsetmacro{\quadrupoleLength}{4}
\pgfmathsetmacro{\quadrupolePathLength}{\quadrupoleLength - (2 * \quadrupoleRadiusHorizontal)}
\pgfmathsetmacro{\quadrupoleTopFrontY}{\centerOffset + 2 * \quadrupoleRadiusVertical}
\pgfmathsetmacro{\quadrupoleTopBackY}{\quadrupoleTopFrontY + \offsetY}
\pgfmathsetmacro{\quadrupoleBottomBackY}{-\centerOffset}
\pgfmathsetmacro{\quadrupoleBottomFrontY}{\quadrupoleBottomBackY - \offsetY}
\begin{tikzpicture}
\coordinate (msOrigin) at (0,0);
% Define a formula for the coil.
% This is what the numbers mean:
% 0.25: the x offset
% 0.13: how far the rings are apart
% 0.30: how much from the side the rings are seen
% 0.75: radius of the rings
\def\coil#1{
{0.25 + 0.13 * (2 * #1 + \t) + 0.30 * sin(- \t * pi r))},
{0.75 * cos(-\t * pi r)}
}
% Draw the background-rods
\quadrupolePair{1}{back}
% Draw the part of the coil behind
\foreach \n in {1,...,14} {
\draw[domain={0:1},smooth,variable=\t,samples=15]
plot (\coil{\n});
}
% Draw the part of the coil in front
\foreach \n in {0,1,...,13} {
\ifthenelse{\equal{\n}{0} \OR \equal{\n}{13}}
{%
\ifthenelse{\equal{\n}{0}}{%
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15,
% mark position = 0(start)
]
plot (\coil{\n});
}{%
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15,
% mark position = 1(end)
]
plot (\coil{\n});
}
}{
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15
]
plot (\coil{\n});
}
}
% Draw the foreground-rods
\quadrupolePair{1}{front}
\draw
% (start) % to join the mark position "start"
(0.25, -0.75)
to [out = 180, in = 0]
++(-1, 0.75);
\draw
% (end) % to join the mark position "end"
(4, -0.75)
to [out = 0, in = 180]
++(1, 0.75);
\end{tikzpicture}
\hspace{1em}
\begin{tikzpicture}
\coordinate (msOrigin) at (0,0);
% Define a formula for the coil.
% This is what the numbers mean:
% 0.25: the x offset
% 0.13: how far the rings are apart
% 0.30: how much from the side the rings are seen
% 0.75: radius of the rings
\def\coil#1{
{0.25 + 0.13 * (2 * #1 + \t) + 0.30 * sin(- \t * pi r)},
{0.75 * #1/10 * \t * cos(-\t * pi r)}
}
% Draw the background-rods
\quadrupolePair{1}{back}
% Draw the part of the coil behind
\foreach \n in {1,...,14} {
\draw[domain={0:1},smooth,variable=\t,samples=15]
plot (\coil{\n});
}
% Draw the part of the coil in front
\foreach \n in {0,1,...,13} {
\ifthenelse{\equal{\n}{0} \OR \equal{\n}{13}}
{%
\ifthenelse{\equal{\n}{0}}{%
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15,
% mark position = 0(start)
]
plot (\coil{\n});
}{%
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15,
% mark position = 1(end)
]
plot (\coil{\n});
}
}{
\draw[
domain = {1:2},
smooth,
variable = \t,
samples = 15
]
plot (\coil{\n});
}
}
% Draw the foreground-rods
\quadrupolePair{1}{front}
\end{tikzpicture}
\end{document}




white, double=red. This does not work directly here as the line self intersect. Try it to see the result. A solution would be to split the plot into individual loops. It is a problem that I would like to investigate myself, so maybe I will ask a question on this site tomorrow. – hpekristiansen Nov 27 '20 at 22:00cliplike this: https://tex.stackexchange.com/a/568980/8650 or you can calculate the correct domain for each loop. – hpekristiansen Nov 27 '20 at 22:05\foreachexample to make your spiral. – hpekristiansen Nov 28 '20 at 16:44clip. – Sam Nov 28 '20 at 21:42