Spirale stożkowe i cylindryczne
Chcę narysować coś takiego w Ti k Z, ale niestety nie jestem pewien, jak dojść do pożądanego wyniku. Rysunek przedstawia ścieżkę jonów w kwadrupolowym spektrometrze mas. Poza kwadrupolem (tymi 4 prętami) żadne pole elektromagnetyczne nie działa na jony i dlatego lecą one w linii prostej. Jeśli wejdą do kwadrupola, mogą albo wejść w rezonans z polem elektromagnetycznym, a tym samym znajdować się na cylindrycznej spiralnej ścieżce lub nie znajdować się w rezonansie, a zatem znajdować się na stożkowej spiralnej ścieżce i prędzej czy później wyjść z kwadrupola z boku.

Moje podejście do tego problemu polegało na pgfplots
narysowaniu spirali za pomocą wykresu 3D z funkcją {x*cos(deg(x))},{x*sin(deg(x)},{x}
wykresu stożkowego i {cos(deg(x))},{sin(deg(x)},{x}
cylindrycznego. Niestety nie mogę rozwiązać następujących problemów:
- prawidłowo ustawić spirale
- narysuj linię prostą, która zamienia się w spiralę, a następnie z powrotem w linię prostą po wyjściu z kwadrupola (tylko dla cylindrycznego)
- zatrzymaj stożkową helisę wkrótce po wyjściu ścieżki z kwadrupola
Doskonale zdaję sobie sprawę, że jest to sporo problemów, dlatego cieszę się z wszelkich wskazówek.
Moja obecna (żałosna) próba
\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}
Aktualizacja 2020-11-26
Znalazłem tę odpowiedź w TeX.SX pomagając narysować cewkę cylindryczną. Dzięki pewnym modyfikacjom udało mi się zajść stosunkowo daleko w tym procesie. Pozostała jedna kwestia jest linia łącząca poziomy odcinek spirali jako kod mark=at position #1 with \coordinate (#2);
generuje Dimension too large.
błąd, nawet jeśli nie rozumiem dlaczego. Cewki są małe i zdecydowanie poniżej 19 stóp ...
Kolejną kwestią, która pozostaje, jest spirala stożkowa. Mam punkt wyjścia, ale niestety wygląda to obrzydliwie.

\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}
Odpowiedzi
Nie widzę powodu, aby używać kodu PGF - jesteś prawie na miejscu, zauważając, że spirala może być wykreślona przez {cos(deg(x))},{sin(deg(x)},{x}
. Zwykle uwielbiam PGFPlots, ale to nie jest fabuła (oś, skala, znaczniki, etykiety, ...). Uważam, że plot
funkcja w TikZ jest właściwa.
Aby wyprostować końce spirali, pozwoliłem, aby amplituda zanikała w tym samym stopniu co pętle. Nie jestem pewien, jak chcesz, aby stożek się kończył - prostym sposobem jest po prostu pozwolić amplitudzie cewki szybko wzrosnąć i dostosować domenę.
\documentclass[tikz, border=1cm]{standalone}
\begin{document}
\begin{tikzpicture}[ultra thick]
\newcommand{\domA}{-pi}
\newcommand{\domB}{0}
\newcommand{\domC}{2*pi}
\newcommand{\domD}{4*pi}
\newcommand{\domE}{\domC+0.5}
\newcommand{\pitch}{10}
\newcommand{\ampA}{(1/(1+\domB-\x))}
\newcommand{\ampB}{(1/(1-\domC+\x))}
\newcommand{\ampC}{(0.1*(\x-\domB)+1)}
\draw[red, domain={\domA:\domB}, smooth, samples=100] plot (\x, {\ampA*cos((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)}, {\ampA*sin((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)} );
\draw[green, domain={\domB:\domC}, smooth, samples=200] plot (\x, {cos(\pitch*\x r)} , {sin(\pitch*\x r)} );
\draw[blue, domain={\domC:\domD}, smooth, samples=100] plot (\x, {\ampB*cos((\ampB*\pitch*\x+(1-\ampB)*\pitch*\domC) r)}, {\ampB*sin((\ampB*\pitch*\x+(1-\ampB)*\pitch*\domC) r)} );
\begin{scope}[yshift=-4cm]
\draw[teal, domain={\domA:\domB}, smooth, samples=100] plot (\x, {cos((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)}, {sin((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)} );
\draw[orange, domain={\domB:\domC}, smooth, samples=200] plot (\x, {\ampC*cos(\pitch*\x r)} , {\ampC*sin(\pitch*\x r)} );
\draw[violet, domain={\domC:\domE}, smooth, samples=100] plot (\x, {\ampC*1/\ampB*cos(\pitch*\x r)} , {\ampC*1/\ampB*sin(\pitch*\x r)} );
\end{scope}
\end{tikzpicture}
\end{document}

Edytować:
Domyślny wektor z w TikZ wskazuje na (−3,85 mm, −3,85 mm). Aby zmienić perspektywę, możesz użyć np. W z={(-3.85mm, 3.85mm)}
ten sposób:
\documentclass[tikz, border=1cm]{standalone}
\begin{document}
\begin{tikzpicture}[z={(-3.85mm, 3.85mm)}]
\newcommand{\domA}{-pi}
\newcommand{\domB}{0}
\newcommand{\domC}{2*pi}
\newcommand{\domD}{4*pi}
\newcommand{\domE}{\domC+0.5}
\newcommand{\pitch}{10}
\newcommand{\ampA}{(1/(1+\domB-\x))}
\newcommand{\ampB}{(1/(1-\domC+\x))}
\newcommand{\ampC}{(0.1*(\x-\domB)+1)}
\draw[fill=gray] (-1,1.2,1) -- (7,1.2,1) arc[start angle=90, end angle=-90, x radius=0.1cm, y radius=0.2cm] -- (-1,0.8,1);
\draw[fill=white](-1,1,1) circle[x radius=0.1cm, y radius=0.2cm];
\draw[fill=gray] (-1,-1.2,1) -- (7,-1.2,1) arc[start angle=-90, end angle=90, x radius=0.1cm, y radius=0.2cm] -- (-1,-0.8,1);
\draw[fill=white](-1,-1,1) circle[x radius=0.1cm, y radius=0.2cm];
\draw[red, thick, domain={\domA:\domB}, smooth, samples=100] plot (\x, {\ampA*cos((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)}, {\ampA*sin((\ampA*\pitch*\x+(1-\ampA)*\pitch*\domB) r)} );
\draw[red, thick, domain={\domB:\domC}, smooth, samples=200] plot (\x, {cos(\pitch*\x r)} , {sin(\pitch*\x r)} );
\draw[red, thick, domain={\domC:\domD}, smooth, samples=100] plot (\x, {\ampB*cos((\ampB*\pitch*\x+(1-\ampB)*\pitch*\domC) r)}, {\ampB*sin((\ampB*\pitch*\x+(1-\ampB)*\pitch*\domC) r)} );
\draw[fill=gray] (-1,1.2,-1) -- (7,1.2,-1) arc[start angle=90, end angle=-90, x radius=0.1cm, y radius=0.2cm] -- (-1,0.8,-1);
\draw[fill=white](-1,1,-1) circle[x radius=0.1cm, y radius=0.2cm];
\draw[fill=gray] (-1,-1.2,-1) -- (7,-1.2,-1) arc[start angle=-90, end angle=90, x radius=0.1cm, y radius=0.2cm] -- (-1,-0.8,-1);
\draw[fill=white](-1,-1,-1) circle[x radius=0.1cm, y radius=0.2cm];
\end{tikzpicture}
\end{document}

Załamanie czerwonej spirali jest spowodowane tym, smooth
że nie działa na różnych działkach. Widzę dwa sposoby, aby to naprawić: albo usuń smooth
opcję i znacznie zwiększ próbki. -lub lepiej: użyj TikZ declare function
do zadeklarowania funkcji odcinkowej i wykonaj tylko jeden wykres.