Spirales coniques et cylindriques

Nov 25 2020

Je veux dessiner quelque chose comme ce qui suit dans Ti k Z, mais, malheureusement, je ne suis pas sûr de savoir comment obtenir le résultat souhaité . La figure montre le trajet des ions dans un spectromètre de masse quadripolaire. En dehors du quadripôle (ces 4 tiges), aucun champ électromagnétique ne s'applique aux ions et donc ils volent en ligne droite. S'ils entrent dans le quadripôle, ils peuvent soit entrer en résonance avec le champ électromagnétique et donc être sur un chemin en spirale cylindrique ou ne pas être en résonance et ainsi être sur un chemin en spirale conique et sortir tôt ou tard du quadripôle sur un côté.

Ma prise à ce problème était d'utiliser pgfplotspour dessiner les spirales en utilisant un tracé 3D avec la fonction {x*cos(deg(x))},{x*sin(deg(x)},{x}pour le tracé conique et {cos(deg(x))},{sin(deg(x)},{x}pour le tracé cylindrique. Malheureusement, je me trouve incapable de résoudre les problèmes suivants:

  • positionner correctement les spirales
  • tracez une ligne droite qui se transforme en spirale puis revenez en ligne droite après avoir quitté le quadripôle (uniquement pour le cylindrique)
  • arrêter l'hélice conique peu de temps après la sortie du chemin du quadripôle

Je suis bien conscient que cela pose beaucoup de problèmes et je suis donc heureux de tout indice.

Ma tentative actuelle (misérable)

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

Mise à jour 2020-11-26

J'ai trouvé cette réponse sur TeX.SX en aidant à dessiner la bobine cylindrique. Par quelques modifications, j'ai pu aller relativement loin dans le processus. Un problème restant est la ligne reliant le chemin horizontal à la spirale lorsque le code mark=at position #1 with \coordinate (#2);génère une Dimension too large.erreur, même si je ne comprends pas pourquoi. Les bobines sont petites et nettement inférieures à 19 pieds ...

Un autre problème qui demeure est la spirale conique. J'ai un point de départ, mais malheureusement, cela semble dégoûtant.

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

Réponses

3 hpekristiansen Nov 26 2020 at 23:08

Je ne vois aucune raison d'utiliser le code PGF - vous y êtes presque simplement en remarquant que la spirale peut être tracée {cos(deg(x))},{sin(deg(x)},{x}. J'aime normalement les PGFPlots, mais ce n'est pas un tracé (axe, échelle, graduations, étiquettes, ...). Je pense que la plotfonction dans TikZ est la bonne manière.

Pour redresser les extrémités de la spirale, je laisse décroître l'amplitude en même temps que la hauteur des boucles. Je ne sais pas comment vous voulez que le conique se termine - un moyen simple consiste simplement à laisser l'amplitude de la bobine monter rapidement et à ajuster le domaine.

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

Éditer:

Le vecteur z par défaut dans TikZ pointe vers (−3,85 mm, −3,85 mm). Pour changer la perspective, vous pouvez utiliser par exemple z={(-3.85mm, 3.85mm)}comme ceci:

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

Le pli dans la spirale rouge est dû au smoothfait que le ne fonctionne pas sur différentes parcelles. Je peux voir deux façons de corriger cela: Soit supprimer l' smoothoption et augmenter beaucoup les échantillons. -ou mieux: utilisez TikZ declare functionpour déclarer une fonction par morceaux et ne faire qu'un seul tracé.