2

I am creating a document explaining the concept of a solid angle in Astronomy to students. I would like to create a graphic as shown below in TikZ to illustrate the concept clearly, but I have no idea where to start. It is supposed to illustrate a sphere of radius r and a solid D whose projection onto the sphere gives the area A. Any help is appreciated!

enter image description here

  • Surely we have done this already? tex.stackexchange.com/questions/108915/… – Thruston Jul 9 '18 at 9:17
  • The lines of projection and labelling of the solid before projection are not present, and the formatting is quite different since my solid is outside the sphere. – Teyyf Jul 9 '18 at 9:52
  • All you need to do is to draw a circle on a sphere. This can be done with pgfplots or without. – marmot Jul 9 '18 at 10:25
2
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{backgrounds}
\usepackage{tikz-3dplot}

\makeatletter

%along z axis
\define@key{z sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{z sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{z sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{z spherical visible}{% 
    \setkeys{z sphericalkeys}{#1}%
    \pgfmathsetmacro{\Xtest}{cos(90-\tdplotmaintheta)*cos(\tdplotmainphi-90)*cos(\mytheta)*cos(\myphi)
    +cos(90-\tdplotmaintheta)*sin(\tdplotmainphi-90)*cos(\mytheta)*sin(\myphi)
    +sin(90-\tdplotmaintheta)*sin(\mytheta)}
    % \Xtest is the projection of the coordinate on the normal vector of the visible plane
    \pgfmathsetmacro{\ntest}{ifthenelse(\Xtest<0,0,1)}
    \ifnum\ntest=0
      \pgfmathsetmacro{\myx}{\myradius*cos(\mytheta)*cos(\myphi)*\raarot
      +\myradius*cos(\mytheta)*sin(\myphi)*\rabrot+\myradius*sin(\mytheta*\racrot}
      \pgfmathsetmacro{\myy}{\myradius*cos(\mytheta)*cos(\myphi)*\rbarot
      +\myradius*cos(\mytheta)*sin(\myphi)*\rbbrot+\myradius*sin(\mytheta*\rbcrot}  
      \pgfpoint{\RadiusSphere*cos(atan2(\myy,\myx))*1cm}{\RadiusSphere*sin(atan2(\myy,\myx))*1cm}
    \else
      \pgfpointxyz{\myradius*cos(\mytheta)*cos(\myphi)}{%
      \myradius*cos(\mytheta)*sin(\myphi)}{\myradius*sin(\mytheta)}
    \fi
}

\tikzdeclarecoordinatesystem{z spherical invisible}{% 
    \setkeys{z sphericalkeys}{#1}%
    \pgfmathsetmacro{\Xtest}{cos(90-\tdplotmaintheta)*cos(\tdplotmainphi-90)*cos(\mytheta)*cos(\myphi)
    +cos(90-\tdplotmaintheta)*sin(\tdplotmainphi-90)*cos(\mytheta)*sin(\myphi)
    +sin(90-\tdplotmaintheta)*sin(\mytheta)}
    % \Xtest is the projection of the coordinate on the normal vector of the visible plane
    %\typeout{\raarot,\rbarot,\rabrot,\rbbrot,\racrot, \rbcrot}
    \pgfmathsetmacro{\ntest}{ifthenelse(\Xtest<0,0,1)}
    \ifnum\ntest=1
      \pgfmathsetmacro{\myx}{\myradius*cos(\mytheta)*cos(\myphi)*\raarot
      +\myradius*cos(\mytheta)*sin(\myphi)*\rabrot+\myradius*sin(\mytheta*\racrot}
      \pgfmathsetmacro{\myy}{\myradius*cos(\mytheta)*cos(\myphi)*\rbarot
      +\myradius*cos(\mytheta)*sin(\myphi)*\rbbrot+\myradius*sin(\mytheta*\rbcrot}  
      \pgfpoint{\RadiusSphere*cos(atan2(\myy,\myx))*1cm}{\RadiusSphere*sin(atan2(\myy,\myx))*1cm}
    \else
      \pgfpointxyz{\myradius*cos(\mytheta)*cos(\myphi)}{%
      \myradius*cos(\mytheta)*sin(\myphi)}{\myradius*sin(\mytheta)}
    \fi
}

%%%%%%%%%%%%%%%%%

\makeatother
% decoration
\begin{document}
\pgfmathsetmacro{\RadiusSphere}{3}

\foreach \X in {30}
{\begin{tikzpicture}
% \path[use as bounding box] ({-1.2*\RadiusSphere},{-1.2*\RadiusSphere}) rectangle
% ({1.2*\RadiusSphere},{1.2*\RadiusSphere});
\shade[ball color = gray!40, opacity = 0.5]  (0,0) circle (\RadiusSphere);

\tdplotsetmaincoords{110}{\X}
\begin{scope}[tdplot_main_coords,samples=60]
%
% \draw[-latex,orange] (0,0,0) -- (z spherical cs: radius=\RadiusSphere,
% phi={\tdplotmainphi-90},theta={90-\tdplotmaintheta});
% \draw[-latex] (0,0,0) -- (\RadiusSphere,0,0) node[below]{$x$};
% \draw[-latex] (0,0,0) -- (0,\RadiusSphere,0) node[left]{$y$};
% \draw[-latex] (0,0,0) -- (0,0,\RadiusSphere) node[left]{$z$};
\pgfmathtruncatemacro{\Dis}{ifthenelse(\X<50,1,0)+ifthenelse(\X>130,1,0)}
\ifnum\Dis=0
\else
\draw[opacity=0.3,fill opacity=0.2,fill=blue] plot[smooth,variable=\x,domain=-180:180] 
(z spherical invisible cs: radius=\RadiusSphere,phi={15*sin(\x)},theta={15*cos(\x)});
\fi

\pgfmathtruncatemacro{\Dis}{ifthenelse(\X<230,1,0)+ifthenelse(\X>320,1,0)}
\ifnum\Dis=0
\else
\draw[fill opacity=0.5,fill=blue] plot[smooth,variable=\x,domain=-180:180] 
(z spherical visible cs: radius=\RadiusSphere,phi={15*sin(\x)},theta={15*cos(\x)});
\fi
\coordinate (C) at (z spherical visible cs: radius=2.5*\RadiusSphere,phi=0,theta=0);
\coordinate (CT) at (z spherical visible cs:
radius=2.5*\RadiusSphere,phi={-15*sin(\X)},theta={15*cos(\X)});
\coordinate (CB) at (z spherical visible cs:
radius=2.5*\RadiusSphere,phi={15*sin(\X/2)},theta={-15*cos(\X/2)});
% \draw[gray] plot[smooth,variable=\x,domain=-180:180] 
% (z spherical visible cs: radius=2.5*\RadiusSphere,phi={15*sin(\x)},theta={15*cos(\x)});
\draw[black] plot[smooth,variable=\x,domain=-180:180] 
(z spherical visible cs: radius=\RadiusSphere,phi={90},theta={\x});
\draw[gray] plot[smooth,variable=\x,domain=-180:180] 
(z spherical invisible cs: radius=\RadiusSphere,phi={90},theta={\x});
\end{scope}
\begin{scope}[on background layer]
\shade[ball color = blue!40, opacity = 1]  (C) circle (0.66*\RadiusSphere);
\draw (0,0) -- (CT) (0,0) -- (CB);
\end{scope}
\end{tikzpicture}
}
\end{document}

enter image description here

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.