1

I'm new in using tikz/pgfplots to create graphics. It is quite powerful but therefore also complex.

My specific case deals with combining a single torus with an arc segment. The image below should give an impression

enter image description here

What I managed to do so far is this MWE

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[dvipsnames]{xcolor}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}[thkline/.style={thick, blue, <-, >=stealth}]
    \coordinate(O) at (-2.75,-1.35);
    \coordinate(A) at (1.25,-0.35);
    \begin{axis}[anchor=origin, xmax=15, ymax=15, zmax=6, axis lines = none, 
                 colormap={red}{color=(lightgray) color=(lightgray)}]
        \addplot3[domain=0:360,y domain=0:360, samples=25, surf, z buffer=sort]
            (
            {3 * sin(x)},
            {(4 + 3 * cos(x)) * sin(y)},
            {-(4 + 3 * cos(x)) * cos(y)});
    \end{axis}
%     \draw[thkline, rotate = 3] (O)  arc (-90:60:3 and 1.5) node [below right] {$e^-$} ;
    \draw[thkline, rotate = 0] (O)  arc (-90:90:3 and 1.) node [below right] {$e^-$} ;
\end{tikzpicture} 


\end{document}

I was hoping, an expert could point me in the right direction. Thanks in advance!

Edit I

According to the answer given below, I reworked the code using the first solution and came across a rather interesting issue, since the objects are misaligned: enter image description here

Could that behavior related to the pgf version? Since we're using \pgfplotsset{compat=1.16}

Edit II

The strange shift remains after adding \begin{scope}[canvas is xy plane at z=0,>=stealth, shift={(axis cs: 0,0,0)}] to both scopes. It seems to apply to the top line (annotated with 'acceleration'), the torus itself and part of the second scope (the short arc with arrow head): enter image description here

  • Did you compile the very code from below when you encountered the issue? It is true that the 3d library had a bug that got fixed about a year ago, but this bug should not lead to the displacement. What may, however, potentially explain the displacement is that the coordinate (axis cs:0,0,0) does not sit at (0pt,0pt) in the ambient tikzpicture. So you may resolve the issue by adding shift={(axis cs:0,0,0)} to the canvas scopes. –  Oct 24 '19 at 15:55
  • Yes, I made sure to compile it 1:1 (first I expected typos). See my second edit above. The situation shows now an enhanced shift to parts of different layers. – Number42 Oct 24 '19 at 16:51
  • Please note that the annotated line is not drawn in the scope. It is very weird since on my machine the problem does not arise. (I am using an updated TeXLive2019 installation and compile with pdflatex.) You may try exchanging the order: \begin{scope}[shift={(axis cs: 0,0,0)},canvas is xy plane at z=0,>=stealth] but to me this seems very mysterious. You can also use the second proposal, remove the \pgflowlevelsynccm and replace the line widths by those from the first example. Nonetheless I am really surprised and cannot reproduce the issue at the moment. –  Oct 24 '19 at 16:56
  • I expected that it might be related to the local setup on the machine. I may try to update to TeXLive2019, however it's probably not straight forward and therefore takes some time. Running either pdflatex or XeLaTeX doesn't make a difference on the result. Anyway - thanks a lot for your competent support! – Number42 Oct 25 '19 at 06:51

1 Answers1

2

Welcome! You were already close. In order to draw the stuff in the xy plane, it might be a good idea to load the TikZ library 3d.

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[dvipsnames]{xcolor}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{3d}
\begin{document}

\begin{tikzpicture}[thkline/.style={thick, blue, >=stealth},font=\sffamily]
    \begin{axis}[anchor=origin, xmax=15, ymax=15, zmax=6, axis lines = none, 
                 colormap={red}{color=(lightgray) color=(lightgray)},
                 clip=false]
        %background stuff        
        \draw[ultra thick] (0,0,0) coordinate(O) -- (-25,0,0)  
            node[pos=2/3,above,sloped]{acceleration};
        \begin{scope}[canvas is xy plane at z=0,>=stealth]
         \draw[ultra thick,->]  (0,0) -- (-25,0);
         \draw[very thick,->] (0,30) -- (0,0);
         \draw[->] (0,0) coordinate(O) -- (0,-7);
         \draw[very thick] (0,0) arc(0:-30:50);
        \end{scope}      
        % torus
        \addplot3[domain=0:360,y domain=0:360, samples=25, surf, z buffer=sort,
            opacity=0.6]
            (
            {3 * sin(x)},
            {(4 + 3 * cos(x)) * sin(y)},
            {-(4 + 3 * cos(x)) * cos(y)});
        % foreground    
        \begin{scope}[canvas is xy plane at z=0,>=stealth]
         \draw[->] (0,-7) -- (0,-30);
         \draw[very thick,->,overlay] (-50,0)+(-8:50) arc(-8:-20:50);
         \draw (0,-10) arc(-90:-180:10) node[midway,left]{$\mathsf{90}^\circ$}; 
        \end{scope}      
        \end{axis}
\end{tikzpicture} 
\end{document}

Unfortunately there is no real 3d engine coming with TikZ/pgfplots, so one has to draw the things in the appropriate order. I indicate this in the code. There is an angle of 8 which I estimated.

enter image description here

It is also possible to project the arrows on the planes with \pgflowlevelsynccm. However, the transformations pgfplots performs prevent me from adding this to the scopes inside the axis. Therefore, one may export the view and scaling from the axis and add the scopes outside, with the stuff behind the torus on the background layer.

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[dvipsnames]{xcolor}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{3d,backgrounds,calc}
\begin{document}

\begin{tikzpicture}[thkline/.style={thick, blue, >=stealth},font=\sffamily]
    \begin{axis}[anchor=origin, xmax=15, ymax=15, zmax=6, axis lines = none, 
                 colormap={red}{color=(lightgray) color=(lightgray)},
                 clip=false]
        %background stuff        
        \draw[ultra thick] (0,0,0) coordinate(O) -- (-25,0,0)  
            node[pos=2/3,above,sloped]{acceleration};
        \path let \p1=($(1,0,0)-(0,0,0)$),\p2=($(0,1,0)-(0,0,0)$),
            \p3=($(0,0,1)-(0,0,0)$) in
            \pgfextra{\xdef\myxx{\x1}\xdef\myxy{\y1}
            \xdef\myyx{\x2}\xdef\myyy{\y2}
            \xdef\myzx{\x3}\xdef\myzy{\y3}};
        % torus
        \addplot3[domain=0:360,y domain=0:360, samples=25, surf, z buffer=sort,
            opacity=0.6]
            (
            {3 * sin(x)},
            {(4 + 3 * cos(x)) * sin(y)},
            {-(4 + 3 * cos(x)) * cos(y)});
        % foreground    
        \begin{scope}[canvas is xy plane at z=0,>=stealth]
         \draw (0,-10) arc(-90:-180:10) node[midway,left]{$\mathsf{90}^\circ$}; 
        \end{scope} 
        \end{axis}
        \begin{scope}[x={(\myxx,\myxy)},y={(\myyx,\myyy)},z={(\myzx,\myzy)},
            canvas is xy plane at z=0,>=stealth,on background layer]
         \pgflowlevelsynccm 
         \draw[line width=0.7cm,->]  (0,0) -- (-10,0);
         \draw[line width=0.5cm] (0,30) -- (0,0);
         \draw[line width=0.5cm,->] (0,30) -- (0,20);
         \draw[line width=0.1cm,->] (0,0) coordinate(O) -- (0,-7);
         \draw[line width=0.5cm] (0,0) arc(0:-30:50);
        \end{scope}      
        % foreground    
        \begin{scope}[x={(\myxx,\myxy)},y={(\myyx,\myyy)},z={(\myzx,\myzy)},
            canvas is xy plane at z=0,>=stealth]
         \pgflowlevelsynccm     
         \draw[line width=0.1cm,->] (0,-7) -- (0,-30);
         \draw[line width=0.5cm,->,overlay] (-50,0)+(-8:50) arc(-8:-20:50);
        \end{scope}      
\end{tikzpicture} 
\end{document}

enter image description here

  • Thanks for welcoming me and your sophisticated answer - really nice! The key was to use the 3D library and combine it with scopes. Solution number 2 worked for me. Solution number 1 has an issue, as can be seen in my edit. – Number42 Oct 24 '19 at 15:52