Spirali coniche e cilindriche

Nov 25 2020

Voglio disegnare qualcosa di simile a Ti k Z, ma, sfortunatamente, non sono sicuro di come ottenere il risultato desiderato. La figura mostra il percorso degli ioni in uno spettrometro di massa quadrupolare. Al di fuori del quadrupolo (quelle 4 aste) nessun campo elettromagnetico si applica agli ioni e quindi volano in linea retta. Se entrano nel quadrupolo possono entrare in risonanza con il campo elettromagnetico e quindi trovarsi su un percorso a spirale cilindrico oppure non essere in risonanza e quindi trovarsi su un percorso a spirale conico e prima o poi uscire dal quadrupolo su un lato.

La mia interpretazione di questo problema è stata quella di utilizzare pgfplotsper disegnare le spirali utilizzando un grafico 3D con la funzione {x*cos(deg(x))},{x*sin(deg(x)},{x}per il grafico conico e {cos(deg(x))},{sin(deg(x)},{x}per quello cilindrico. Purtroppo non riesco a risolvere i seguenti problemi:

  • posizionare correttamente le spirali
  • tracciare una linea retta che si trasforma in spirale e poi tornare in linea retta dopo essere usciti dal quadrupolo (solo per quello cilindrico)
  • fermare l'elica conica poco dopo che il percorso è uscito dal quadrupolo

Sono ben consapevole che si tratta di un bel po 'di problemi e quindi sono felice di eventuali suggerimenti.

Il mio attuale (miserabile) tentativo

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

Aggiornamento 2020-11-26

Ho trovato questa risposta su TeX.SX che aiuta a disegnare la bobina cilindrica. Con alcune modifiche, sono stato in grado di arrivare relativamente lontano nel processo. Un problema rimanente è la linea che collega il percorso orizzontale con la spirale mentre il codice mark=at position #1 with \coordinate (#2);genera un Dimension too large.errore, anche se non capisco perché. Le bobine sono piccole e decisamente sotto i 19 piedi ...

Un altro problema che rimane è la spirale conica. Ho un punto di partenza, ma sfortunatamente sembra disgustoso.

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

Risposte

3 hpekristiansen Nov 26 2020 at 23:08

Non vedo alcun motivo per usare il codice PGF: sei quasi arrivato solo notando che la spirale può essere tracciata {cos(deg(x))},{sin(deg(x)},{x}. Normalmente adoro PGFPlots, ma questa non è una trama (asse, scala, tick, etichette, ...). Credo che la plotfunzione in TikZ sia la strada giusta.

Per raddrizzare le estremità della spirale ho lasciato decadere l'ampiezza allo stesso tempo con l'altezza dei loop. Non sono sicuro di come vuoi che finisca il conico: un modo semplice è lasciare che l'ampiezza della bobina salga velocemente e regolare il dominio.

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

Modificare:

Il vettore z predefinito in TikZ punta a (−3,85 mm, −3,85 mm). Per cambiare la prospettiva, puoi usare ad z={(-3.85mm, 3.85mm)}esempio in questo modo:

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

Il nodo nella spirale rossa è perché smoothnon funziona su trame diverse. Posso vedere due modi per correggere questo: o rimuovere l' smoothopzione e aumentare molto i campioni. -o meglio: usa TikZ declare functionper dichiarare una funzione a tratti e fai un solo grafico .