6

I am trying draw two circles are intersections of two planes and a sphere.

\documentclass[tikz,border=1mm, 12 pt]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{backgrounds}
\makeatletter
% retrieves the 3D coordinates
\def\RawCoord(#1){\csname tikz@dcl@coord@#1\endcsname}%
\def\scalprod#1=#2.#3;{%
    \edef\coordA{\RawCoord#2}%
    \edef\coordB{\RawCoord#3}%
    \pgfmathsetmacro\pgfutil@tmpa{scalarproduct({\coordA},{\coordB})}
    \edef#1{\pgfutil@tmpa}}%
\makeatother 
\newcommand{\spaux}[6]{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}  
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors
    \begingroup%
    \pgfmathparse{\spaux#1#2}%
    \pgfmathsmuggle\pgfmathresult\endgroup}  
\begin{document}

    \tdplotsetmaincoords{65}{70}
    \begin{tikzpicture}[scale=1/7,tdplot_main_coords,declare function={a=16;b=16;h=28;r=sqrt(a*a + b*b)/2;
        alpha1(\th,\ph,\b)=\ph+asin(cot(\th)*tan(\b));%
        alpha2(\th,\ph,\b)=-180+\ph-asin(cot(\th)*tan(\b));%
        beta1(\th,\ph,\a)=90+atan(cot(\th)/sin(\a-\ph));%
        beta2(\th,\ph,\a)=270+atan(cot(\th)/sin(\a-\ph));%
    }]
    \path (0,0,0) coordinate (O)
    (-a/2,-b/2,0) coordinate (A)
   (a/2,-b/2,0) coordinate (C)
     at (a/2,b/2,0) coordinate (B)
   (-a/2,b/2,0) coordinate (D)
    (0,0,h) coordinate (O')
    (-a/2,-b/2,h) coordinate (A')
    (a/2,-b/2,h) coordinate (C')
    at (a/2,b/2,h) coordinate (B')
    (-a/2,b/2,h) coordinate (D')
    (0,0,16/a) coordinate(Z);

    \begin{scope}[canvas is xy plane at z={0}]
    \draw[dashed] (O) circle (r);
    \scalprod\myz=(O).(Z); % z component of T
    \pgfmathsetmacro{\myel}{atan(-1*\myz/r)}
    \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
    arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
    {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;
    \end{scope}

    \begin{scope}[canvas is xy plane at z={h}]
    \scalprod\myz=(O).(Z); % z component of T
   \pgfmathsetmacro{\myel}{atan(-1*\myz/r)}
    \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
    arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
    {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;

    \end{scope}

    \coordinate (I) at ($ (O) !0.5!(O') $);
    \begin{scope}[tdplot_screen_coords, on background layer] 
    \draw[thick] (I) circle ({sqrt(a*a + b*b + h*h)/2}); 

    \end{scope}

    \foreach \v/\position in {A/below,B/below,C/below,D/below,A'/above,B'/above,C'/above,D'/above} {\draw[draw =black, fill=black] (\v) circle (1pt) node [\position=0.2mm] {$\v$};
    }

\foreach \X in {A,B,C,D} \draw[dashed]  (\X) -- (\X');
\draw[dashed]  (A) --(B)  -- (C) -- (D) -- cycle  
(A') --(B')  -- (C')-- (D') -- cycle
 ;

\end{tikzpicture}

\end{document} 

enter image description here

The lines of two circles incorrect. How can I get them correct?

  • The dashed lines would look nicer without dashes, just drawn in thick gray. – Benjamin McKay Sep 5 '19 at 7:52
7

The elevations of the planes are plus or minus h/2, respectively, and not the z-component of O (which is 0). Once you put this in, you get

\documentclass[tikz,border=1mm, 12 pt]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{backgrounds}
\makeatletter
% retrieves the 3D coordinates
\def\RawCoord(#1){\csname tikz@dcl@coord@#1\endcsname}%
\def\scalprod#1=#2.#3;{%
    \edef\coordA{\RawCoord#2}%
    \edef\coordB{\RawCoord#3}%
    \pgfmathsetmacro\pgfutil@tmpa{scalarproduct({\coordA},{\coordB})}
    \edef#1{\pgfutil@tmpa}}%
\makeatother 
\newcommand{\spaux}[6]{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}  
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors
    \begingroup%
    \pgfmathparse{\spaux#1#2}%
    \pgfmathsmuggle\pgfmathresult\endgroup}  
\begin{document}

    \tdplotsetmaincoords{65}{70}
    \begin{tikzpicture}[scale=1/7,tdplot_main_coords,
    declare function={a=16;b=16;h=28;r=sqrt(a*a + b*b)/2;
        R=sqrt(a*a + b*b + h*h)/2;
        alpha1(\th,\ph,\b)=\ph+asin(cot(\th)*tan(\b));%
        alpha2(\th,\ph,\b)=-180+\ph-asin(cot(\th)*tan(\b));%
        beta1(\th,\ph,\a)=90+atan(cot(\th)/sin(\a-\ph));%
        beta2(\th,\ph,\a)=270+atan(cot(\th)/sin(\a-\ph));%
    }]
    \path (0,0,0) coordinate (O)
    (-a/2,-b/2,0) coordinate (A)
   (a/2,-b/2,0) coordinate (C)
     at (a/2,b/2,0) coordinate (B)
   (-a/2,b/2,0) coordinate (D)
    (0,0,h) coordinate (O')
    (-a/2,-b/2,h) coordinate (A')
    (a/2,-b/2,h) coordinate (C')
    at (a/2,b/2,h) coordinate (B')
    (-a/2,b/2,h) coordinate (D')
    (0,0,16/a) coordinate(Z);

    \begin{scope}[canvas is xy plane at z={0}]
    \draw[dashed] (O) circle (r);
     \pgfmathsetmacro{\myel}{atan(-h/2/r)}
    \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
    arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
    {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;
    \end{scope}

    \begin{scope}[canvas is xy plane at z={h}]
    \pgfmathsetmacro{\myel}{atan(h/2/r)}
    \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
    arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
    {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;

    \end{scope}

    \coordinate (I) at ($ (O) !0.5!(O') $);
    \begin{scope}[tdplot_screen_coords, on background layer] 
    \draw[thick] (I) circle (R); 

    \end{scope}

    \foreach \v/\position in {A/below,B/below,C/below,D/below,A'/above,B'/above,C'/above,D'/above} {\draw[draw =black, fill=black] (\v) circle (1pt) node [\position=0.2mm] {$\v$};
    }

\foreach \X in {A,B,C,D} \draw[dashed]  (\X) -- (\X');
\draw[dashed]  (A) --(B)  -- (C) -- (D) -- cycle  
(A') --(B')  -- (C')-- (D') -- cycle
 ;

\end{tikzpicture}

\end{document} 

enter image description here

This works of course for any view angle. (The analytical expressions for alpha1 and alpha2 are derived on the assumption that a finite stretch but not the full stretch is visible. One has to check that this is the case, hence the \ifnum statements.)

\documentclass[tikz,border=1mm, 12 pt]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{backgrounds}
\makeatletter
% retrieves the 3D coordinates
\def\RawCoord(#1){\csname tikz@dcl@coord@#1\endcsname}%
\def\scalprod#1=#2.#3;{%
    \edef\coordA{\RawCoord#2}%
    \edef\coordB{\RawCoord#3}%
    \pgfmathsetmacro\pgfutil@tmpa{scalarproduct({\coordA},{\coordB})}
    \edef#1{\pgfutil@tmpa}}%
\makeatother 
\newcommand{\spaux}[6]{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}  
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors
    \begingroup%
    \pgfmathparse{\spaux#1#2}%
    \pgfmathsmuggle\pgfmathresult\endgroup}  
\begin{document}
\foreach \Angle in {24,26,...,84,82,80,...,26}
{\tdplotsetmaincoords{\Angle}{70}
    \begin{tikzpicture}[scale=1/7,tdplot_main_coords,
    declare function={a=16;b=16;h=28;r=sqrt(a*a + b*b)/2;
        R=sqrt(a*a + b*b + h*h)/2;
        alpha1(\th,\ph,\b)=\ph+asin(cot(\th)*tan(\b));%
        alpha2(\th,\ph,\b)=-180+\ph-asin(cot(\th)*tan(\b));%
        beta1(\th,\ph,\a)=90+atan(cot(\th)/sin(\a-\ph));%
        beta2(\th,\ph,\a)=270+atan(cot(\th)/sin(\a-\ph));%
    }]
    \path[use as bounding box,tdplot_screen_coords]
     (-1.2*R,-1.2*R+h/2) rectangle  (1.2*R,1.2*R+h/2);
    \path (0,0,0) coordinate (O)
    (-a/2,-b/2,0) coordinate (A)
   (a/2,-b/2,0) coordinate (C)
     at (a/2,b/2,0) coordinate (B)
   (-a/2,b/2,0) coordinate (D)
    (0,0,h) coordinate (O')
    (-a/2,-b/2,h) coordinate (A')
    (a/2,-b/2,h) coordinate (C')
    at (a/2,b/2,h) coordinate (B')
    (-a/2,b/2,h) coordinate (D')
    (0,0,16/a) coordinate(Z);

    \begin{scope}[canvas is xy plane at z={0}]
    \draw[dashed] (O) circle (r);
     \pgfmathsetmacro{\myel}{atan(-h/2/r)}
      \pgfmathparse{int(ifthenelse(abs(cot(\tdplotmaintheta)*tan(\myel))<1,1,0))}
      \ifnum\pgfmathresult>0
       \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
       arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
       {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;
      \fi 
    \end{scope}

    \begin{scope}[canvas is xy plane at z={h}]
    \draw[dashed] (O') circle (r);
     \pgfmathsetmacro{\myel}{atan(h/2/r)}
     \pgfmathparse{int(ifthenelse(abs(cot(\tdplotmaintheta)*tan(\myel))<1,1,0))}
     \ifnum\pgfmathresult>0 
      \draw[thick] ({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) 
      arc({alpha1(\tdplotmaintheta,\tdplotmainphi,{\myel})}: 
      {alpha2(\tdplotmaintheta,\tdplotmainphi,{\myel})}:r) ;
     \else 
      \draw[thick] (O') circle (r);
     \fi 
    \end{scope}

    \coordinate (I) at ($ (O) !0.5!(O') $);
    \begin{scope}[tdplot_screen_coords, on background layer] 
    \draw[thick] (I) node{$\theta=\tdplotmaintheta^\circ,\varphi=\tdplotmainphi^\circ$} circle (R); 

    \end{scope}

    \foreach \v/\position in {A/below,B/below,C/below,D/below,A'/above,B'/above,C'/above,D'/above} {\draw[draw =black, fill=black] (\v) circle (1pt) node [\position=0.2mm] {$\v$};
    }

\foreach \X in {A,B,C,D} \draw[dashed]  (\X) -- (\X');
\draw[dashed]  (A) --(B)  -- (C) -- (D) -- cycle  
(A') --(B')  -- (C')-- (D') -- cycle
 ;

\end{tikzpicture}}

\end{document} 

enter image description here

| improve this answer | |
  • Thank you. How can I get a node \Angle at each pdf page? – Thuy Nguyen Sep 5 '19 at 5:07
  • I tried \Angle = 50. I can not get the result. – Thuy Nguyen Sep 5 '19 at 5:07
  • @ThuyNguyen You could replace \draw[thick] (I) circle (R); by \draw[thick] (I) node{$\theta=\Angle^\circ$} circle (R);. – user194703 Sep 5 '19 at 5:09
  • Thank you very much. – Thuy Nguyen Sep 5 '19 at 5:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.