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?

1
  • The dashed lines would look nicer without dashes, just drawn in thick gray. Commented Sep 5, 2019 at 7:52

1 Answer 1

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

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .