10

Based on the equation at here, I use another way to draw. My code

\documentclass[border=2mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot-circleofsphere}
\usepackage{fouriernc}
\makeatletter
\tikzset{
    reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\tikzset{even odd clip/.code={\pgfseteorule},
    protect/.code={
        \clip[overlay,even odd clip,reuse path=#1]
        (-6383.99999pt,-6383.99999pt) rectangle (6383.99999pt,6383.99999pt);
}}
\makeatother
\begin{document}
    \tdplotsetmaincoords{70}{80}
    \begin{tikzpicture}[tdplot_main_coords,scale=1,line join = round, line cap = round,declare function={R=5;r=4;h=sqrt(R^2 - r^2);myx= 2; myy=sqrt(R*R-h*h- myx*myx); k=-1; Angle=k*acos(r/R);}]
    \path
    (0,0,0) coordinate (O)
    (0,0,k*h) coordinate (H)
    (myx,myy,k*h) coordinate (M)
    ;
    \begin{scope}
    \draw[save path=\sphere,thick,tdplot_screen_coords] (O) circle (R);
    \end{scope}
    \begin{scope} [canvas is xy plane at z=k*h]
    \path[save path=\rectA] (-R,-R) rectangle (R,R);
    \begin{scope}
    \clip[use path=\sphere];
    \draw[dashed,use path=\rectA];
    \end{scope}
    \tikzset{protect=\sphere}
    \draw[thick,use path=\rectA];
    \end{scope}
        \begin{scope}[shift={(O)}]
    \tdplotCsDrawLatCircle[blue, thick]{R}{{Angle}}
    \end{scope}
    \foreach \p in {H,M,O}
    {\draw[fill=black] (\p) circle (1.5pt);}
    \foreach \p/\g in {M/90,O/-135,H/30}
    {\path (\p)+(\g:3mm) node{$\p$}; }
    \draw[dashed] (O) -- (H) -- (M) --cycle;
    \end{tikzpicture}
\end{document}

I get

enter image description here

How can I get like this picture by using \usepackage{tikz-3dplot} to get result enter image description here

1 Answer 1

11

You can "hack" the macros from tikz-3dplot-circleofsphere. Here I "hack" \tdplotCsDrawLatCircle by storing the foreground arc in a macro called \pathFG:

 \tdplotCsDrawLatCircle[tdplotCsFront/.style={draw=none,save path=\pathFG},
        tdplotCsBack/.style={draw=none}]{R}{Angle}  

This gives us access to this stretch for clipping utilizing reuse path=\pathFG. (Note that use path does not do what we want here.) Then one can clip and protect the relevant areas.

\documentclass[border=2mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot-circleofsphere}
\usepackage{fouriernc}
\makeatletter
\tikzset{
    reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\tikzset{even odd clip/.code={\pgfseteorule},
    protect/.code={
        \clip[overlay,even odd clip,reuse path=#1]
        (-6383.99999pt,-6383.99999pt) rectangle (6383.99999pt,6383.99999pt);
}}
\makeatother
\begin{document}
    \tdplotsetmaincoords{70}{80}
    \begin{tikzpicture}[tdplot_main_coords,scale=1,line join = round, 
        line cap = round,
        declare function={R=5;r=4;h=sqrt(R^2 - r^2);%
        myx= 2; myy=sqrt(R*R-h*h- myx*myx); k=-1; Angle=k*acos(r/R);}]
    \path
    (0,0,0) coordinate (O)
    (0,0,k*h) coordinate (H)
    (myx,myy,k*h) coordinate (M)
    ;
    \tdplotCsDrawLatCircle[tdplotCsFront/.style={draw=none,save path=\pathFG},
        tdplotCsBack/.style={draw=none}]{R}{Angle}  
    \begin{scope}
    \path[save path=\sphere,thick,tdplot_screen_coords] (O) circle[radius=R];
    \end{scope}
    \begin{scope} [canvas is xy plane at z=k*h]
     \path[save path=\rectA] (-R,-R) rectangle (R,R);
     \begin{scope}
      \clip[reuse path=\pathFG,save path=\pathFGB] -- (R,R)  -- (R,-R) -- cycle;
      \draw[dashed,use path=\sphere]; 
     \end{scope}
     \begin{scope}
      \clip[use path=\sphere];
      \draw[dashed,use path=\rectA];
     \end{scope}
     \begin{scope}
      \tikzset{protect=\pathFGB}    
      \draw[thick,use path=\sphere]; 
     \end{scope}
     \draw[thick] (R,R)  -- (R,-R);
     \tikzset{protect=\sphere}
      \draw[thick,use path=\rectA];
    \end{scope}
    \tdplotCsDrawLatCircle[blue, thick]{R}{Angle}
    \foreach \p in {H,M,O}
    {\draw[fill=black] (\p) circle (1.5pt);}
    \foreach \p/\g in {M/90,O/-135,H/30}
    {\path (\p)+(\g:3mm) node{$\p$}; }
    \draw[dashed] (O) -- (H) -- (M) --cycle;
    \end{tikzpicture}
\end{document}

enter image description here

Note that this trick is not limited to tikz-3dplot-circleofsphere. Whenever a package draws a path with a macro we can access and use it this way. For instance, one can hack the tikzlings package to provide our friends with cloths.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikzlings}
\newcounter{savedpath}
\makeatletter
\tikzset{reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}},
save paths/.code={\setcounter{savedpath}{0}%
\edef\tikz@path@name{#1}%
\tikzset{every path/.append style={autosave path}}},
autosave path/.code={\stepcounter{savedpath}%
\edef\temp{\noexpand\tikzset{save path=\csname\tikz@path@name\roman{savedpath}\endcsname}}%
\temp
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{scope}[save paths=mpath]
\marmot
\end{scope}
\begin{scope}
\clip[reuse path=\mpathvii];
\fill[blue] (-1,1.4) to[bend right=10] (1,1.4) -- (1,0.5) to[bend left=10] (-1,0.5) --
cycle;
\fill[brown!30!black,reuse path=\mpathix];
\fill[brown!30!black,reuse path=\mpathx];
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

As can be seen, these reused paths can be used for clipping and filling. They can also be used for drawing. For some reason they cannot be used for shading, though, even though you can use them to clip some shading which yields the equivalent result. One can also combine them. It is conceivable that these are some steps towards solving this issue.

ADDENDUM: Some animation. No, this does not work for arbitrary view angles but for some nontrivial subset of them.

\documentclass[border=2mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot-circleofsphere}
\usepackage{fouriernc}
\makeatletter
\tikzset{
    reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\tikzset{even odd clip/.code={\pgfseteorule},
    protect/.code={
        \clip[overlay,even odd clip,reuse path=#1]
        (-6383.99999pt,-6383.99999pt) rectangle (6383.99999pt,6383.99999pt);
}}
\makeatother
\begin{document}
\foreach \Angle in {5,15,...,355} 
{\tdplotsetmaincoords{70}{\Angle}
\begin{tikzpicture}[tdplot_main_coords,scale=1,line join = round, 
        line cap = round,
        declare function={R=5;L=5.5;r=4;h=sqrt(R^2 - r^2);%
        myx= 2; myy=sqrt(R*R-h*h- myx*myx); k=-1; Angle=k*acos(r/R);}]
    \path[tdplot_screen_coords,use as bounding box] (-9,-9) rectangle (9,9);
    \path
    (0,0,0) coordinate (O)
    (0,0,k*h) coordinate (H)
    (myx,myy,k*h) coordinate (M)
    ;
    \pgfmathtruncatemacro{\itest}{(abs(sin(\tdplotmainphi)*cos(\tdplotmainphi))<0.3 ? 0 : 1)}
    \tdplotCsDrawLatCircle[tdplotCsFront/.style={draw=none,save path=\pathFG},
        tdplotCsBack/.style={draw=none}]{R}{Angle}  
    \begin{scope}
    \path[save path=\sphere,thick,tdplot_screen_coords] (O) circle[radius=R];
    \end{scope}
    \begin{scope} [canvas is xy plane at z=k*h]
     \path[save path=\rectA] (-L,-L) rectangle (L,L);
     \begin{scope}
      \path ({(cos(\tdplotmainphi)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi)<0 ? -1 : 1)*L}) coordinate (p1)
         ({(cos(\tdplotmainphi-90+0)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi-90+0)<0 ? -1 : 1)*L})  coordinate (p2)
         ({(cos(\tdplotmainphi-180+0)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi-180+0)<0 ? -1 : 1)*L})     
         coordinate (p3);
      \clip[overlay,reuse path=\pathFG,save path=\pathFGB] 
         --(p1) -- (p2)  -- (p3) -- cycle;
      \draw[dashed,use path=\sphere]; 
     \end{scope}
     \begin{scope}
      \clip[use path=\sphere];
      \draw[dashed,use path=\rectA];
     \end{scope}
     \begin{scope}
      \tikzset{protect=\pathFGB}    
      \draw[thick,use path=\sphere]; 
     \end{scope}
     \draw[thick] (p1) -- (p2)  -- (p3);
     \tikzset{protect=\sphere}
     \draw[thick,use path=\rectA];
    \end{scope}
    \tdplotCsDrawLatCircle[blue, thick]{R}{Angle}
    \foreach \p in {H,M,O}
    {\draw[fill=black] (\p) circle (1.5pt);}
    \foreach \p/\g in {M/90,O/-135,H/30}
    {\path (\p)+(\g:3mm) node{$\p$}; }
    \draw[dashed] (O) -- (H) -- (M) --cycle;
\end{tikzpicture}}
\end{document}

enter image description here

And here is another animation.

\documentclass[border=2mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot-circleofsphere}
\usepackage{fouriernc}
\makeatletter
\tikzset{
    reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\tikzset{even odd clip/.code={\pgfseteorule},
    protect/.code={
        \clip[overlay,even odd clip,reuse path=#1]
        (-6383.99999pt,-6383.99999pt) rectangle (6383.99999pt,6383.99999pt);
}}
\makeatother
\begin{document}
\foreach \Z in {4,3,...,-4,-3,-2,...,3} 
{\tdplotsetmaincoords{70}{80}
\begin{tikzpicture}[tdplot_main_coords,scale=1,line join = round, 
        line cap = round,
        declare function={R=5;L=5.5;h=abs(\Z);r=sqrt(R*R-\Z*\Z);%
        myx= 2; myy=sqrt(R*R-h*h- myx*myx); k=sign(\Z); Angle=k*acos(r/R);}]
    \path[tdplot_screen_coords,use as bounding box] (-9,-9) rectangle (9,9);
    \path
    (0,0,0) coordinate (O)
    (0,0,k*h) coordinate (H)
    (myx,myy,k*h) coordinate (M)
    ;
    \pgfmathtruncatemacro{\itest}{(abs(sin(\tdplotmainphi)*cos(\tdplotmainphi))<0.3 ? 0 : 1)}
    \tdplotCsDrawLatCircle[tdplotCsFront/.style={draw=none,save path=\pathFG},
        tdplotCsBack/.style={draw=none}]{R}{Angle}  
    \begin{scope}
    \path[save path=\sphere,thick,tdplot_screen_coords] (O) circle[radius=R];
    \end{scope}
    \begin{scope} [canvas is xy plane at z=k*h]
     \path[save path=\rectA] (-L,-L) rectangle (L,L);
     \begin{scope}
      \path ({(cos(\tdplotmainphi)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi)<0 ? -1 : 1)*L}) coordinate (p1)
         ({(cos(\tdplotmainphi-90+0)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi-90+0)<0 ? -1 : 1)*L})  coordinate (p2)
         ({(cos(\tdplotmainphi-180+0)<0 ? -1 : 1)*L},
        {(sin(\tdplotmainphi-180+0)<0 ? -1 : 1)*L})     
         coordinate (p3);
      \clip[overlay,reuse path=\pathFG,save path=\pathFGB] 
         --(p1) -- (p2)  -- (p3) -- cycle;
      \draw[dashed,use path=\sphere]; 
     \end{scope}
     \begin{scope}
      \clip[use path=\sphere];
      \draw[dashed,use path=\rectA];
     \end{scope}
     \begin{scope}
      \tikzset{protect=\pathFGB}    
      \draw[thick,use path=\sphere]; 
     \end{scope}
     \draw[thick] (p1) -- (p2)  -- (p3);
     \tikzset{protect=\sphere}
     \draw[thick,use path=\rectA];
    \end{scope}
    \tdplotCsDrawLatCircle[blue, thick]{R}{Angle}
    \foreach \p in {H,M,O}
    {\draw[fill=black] (\p) circle (1.5pt);}
    \foreach \p/\g in {M/90,O/-135,H/30}
    {\path (\p)+(\g:3mm) node{$\p$}; }
    \draw[dashed] (O) -- (H) -- (M) --cycle;
\end{tikzpicture}}
\end{document}

enter image description here

9
  • How about anamination of the plane and the circle? Commented Apr 22, 2020 at 5:33
  • 3
    @ThuyNguyen It is difficult because there are so many cases. If you vary the angles only moderately, you can use this code, but for strong variations it does not work without distinguishing many cases. Maybe the animation here will do.
    – user194703
    Commented Apr 22, 2020 at 5:44
  • 1
    @minhthien_2016 Yes, of course. It is just that this has been done several times already and there is a lot of repetition. That's why I am interested in more general solutions.
    – user194703
    Commented Apr 22, 2020 at 6:02
  • 1
    @ThuyNguyen It is not a particularly well-defined statement to say that the plane is parallel to Oxy since, given a plane, you can always choose your coordinate axis in such a way that this is the case. What is more important is the information in which domains the view angles will be varied.
    – user194703
    Commented Apr 24, 2020 at 2:48
  • 2
    @minhthien_2016 That one is much easier, please see the answer,
    – user194703
    Commented Apr 24, 2020 at 6:31

You must log in to answer this question.

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