2

I'm trying to reproduce 3D diagrams like these of quadrilateralized spheres (taken from here) using TikZ:

enter image description here

It's important that I use specific celestial coordinates (lat/lon can be substituted without a problem) so that I can draw individual bins as well as label them. More generally, the problem is how to draw arcs of great circles from provided coordinates (all lines of the scheme are great circles). My aim is to do this while working in native coordinates, e.g. "draw an arc from (0°,-45°) to (0°,45°) to (45°,45°) to (45°,0°)".

I have found all of the pieces to solve this problem from these sources:

The first link is in Metapost but contain the maths, which are used in the second two links. However, the latter two approaches are just different enough that I've not been able to generalize the solution. One uses \tdplotsetmaincoords to set the viewing angle and rotate the coordinate system, while the other uses \begin{scope} to modify the frame. I've tried to reconstruct each plot from basics, but have not been able to sufficiently abstract away the geometry while being able to arbitrarily rotate the sphere and use my "native" coordinates (and keeping the ability to have the "hidden" dashed lines drawn). There are a lot of moving parts! (The visual quality of the examples above are preferred over the above diagrams.)

Any help greatly appreciated.

  • 1
    Welcome! This looks like a job for the unofficial circleofsphere package. Any chance you can make your question a bit more specific. Just saying that the math is described in the metapost link may not suffice. If it is just to draw great circles, this is definitely covered in the above-mentioned package. – user194703 Apr 9 at 7:07
  • Perhaps this answer is the easiest way to go after all. – user194703 Apr 9 at 9:04
  • I like to do the math. See tex.stackexchange.com/questions/408245/… for example. – John Kormylo Apr 9 at 18:32
  • Thanks for the pointers! These are great leads. It will take me a few days to absorb the material... – Demitri Apr 10 at 23:12
3

Let's start with a discussion on how to construct a solution. It is done in LaTeX, of course, since one needs a few equations.

\documentclass[fleqn]{beamer}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{tikz-3dplot} 
\usetikzlibrary{overlay-beamer-styles}
\makeatletter
\newcommand*{\currentoverlaynumber}{\number\beamer@slideinframe}
\makeatother
\newcommand{\Explain}[1]{\only<.(1)>{\begin{enumerate}
 \item[\currentoverlaynumber.] #1
\end{enumerate}}}
\begin{document}
\begin{frame}[t]
\frametitle{How to construct a great circle arc}
\begin{center}
\begin{tikzpicture}[declare function={R=3;},bullet/.style={circle,inner
sep=1.5pt,fill},>=stealth]
 \shade[ball color = black!80,transform canvas={rotate=-35},
 visible on=<1-2>] (0,0,0) coordinate (O) circle[radius=R];
 \tdplotsetmaincoords{70}{0}
 \tdplotsetrotatedcoords{0}{20}{0}
 \begin{scope}[tdplot_rotated_coords]
  \path[blue,visible on=<2>] 
  ({R*cos(-130)},{R*sin(-130)},0) node[bullet,label=above:$\vec A$](A){}
  ({R*cos(-30)},{R*sin(-30)},0) node[bullet,label=above:$\vec B$](B){};
  \begin{scope}[visible on=<3->,thick]
   \begin{scope}
    \clip plot[variable=\t,domain=-180:170,smooth cycle,samples=36] 
    ({R*cos(\t)},{R*sin(\t)},0);
    \shade[tdplot_screen_coords,ball color = gray!50,
     transform canvas={rotate=-215}] (0,0,0) circle[radius=R];
   \end{scope}  
   \begin{scope}
    \clip plot[variable=\t,domain=-180:00,smooth,samples=19] ({R*cos(\t)},{R*sin(\t)},0)
    -- plot[variable=\t,domain=00:-180,smooth,samples=19] ({R*cos(\t)},{0},{R*sin(\t)})
    --cycle;
    \shade[tdplot_screen_coords,ball color = black!80,
     transform canvas={rotate=-35}] (0,0,0) circle[radius=R];
   \end{scope}  
   \draw[blue,->] (O) -- (A);
   \draw[blue,->] (O) -- (B);
   \path[red] (O) node[bullet,label=above left:$\vec O$]{};
   \draw[red,->,visible on=<4->] (O) -- (0,0,2) node[above left]{$\vec n$};
  \end{scope}
  \path[blue] 
  ({R*cos(-130)},{R*sin(-130)},0) node[bullet,label=above:$\vec A$]{}
  ({R*cos(-30)},{R*sin(-30)},0) node[bullet,label=above:$\vec B$]{};
  \draw[orange,visible on=<5->]
   plot[variable=\t,domain=-130:-30,smooth,samples=19] ({cos(\t)},{sin(\t)},0)
   ({cos(-80)},{sin(-80)},0) node[below] {$\alpha$};
  \draw[magenta,visible on=<5->,->] (O) -- ({R*cos(-130+90)},{R*sin(-130+90)},0) coordinate[label=below:$\vec y$]
      (y);
  \draw[magenta,visible on=<5->,->] (O) -- (A) coordinate[label=below:$\vec x$]
      (y);
 \end{scope}
\end{tikzpicture}
\end{center}
\Explain{Consider a sphere of radius $R$.}\pause
\Explain{Consider two points on the sphere, $\vec A$ and $\vec B$.}\pause
\Explain{We know of course the center of the sphere, $\vec O$.}\pause
\Explain{The normal of the plane in which the great circle lies is 
 $\vec n=\vec A\times\vec B$.}\pause
\Explain{The angle $\alpha$ between $\vec A$ and $\vec B$ is 
$\displaystyle\sphericalangle(\vec A,\vec B)=\arccos\left(\frac{\vec A\cdot\vec
B}{R^2}\right)$.}\pause
\Explain{So all we need to do is to draw an arc of angle $\alpha$ in a plane
spanned by $\vec x:=\vec A$ and and a normalized version of $\vec y=\vec n\times
\vec A$.}\pause
\Explain{What remains to do is to check whether a given point is on the fore or
back side of the sphere.}
\end{frame}

\begin{frame}[t,allowframebreaks]
\frametitle{Visibility check and sceen depth}
\begin{enumerate}
 \item Orthographic projections are obtained by truncating the column vectors of
 a 3d rotatinon matrix,
 \begin{equation} O=\begin{pmatrix}
   O_{11} & O_{12} & O_{13} \\
   O_{21} & O_{22} & O_{23} \\
   O_{31} & O_{32} & O_{33} \\
 \end{pmatrix}
 \end{equation}
 so that 
 \begin{subequations}
 \begin{align}
 \vec e_x&=\begin{pmatrix}O_{11}\\ O_{21}\end{pmatrix}
 =\begin{pmatrix}\texttt{\textbackslash pgf@xx}\\ 
 \texttt{\textbackslash pgf@xy}\end{pmatrix}\;,\\
 \vec e_y&=\begin{pmatrix}O_{21}\\ O_{22}\end{pmatrix}
 =\begin{pmatrix}\texttt{\textbackslash pgf@yx}\\ 
 \texttt{\textbackslash pgf@yy}\end{pmatrix}\;,\\
 \vec e_z&=\begin{pmatrix}O_{13}\\ O_{23}\end{pmatrix}
 =\begin{pmatrix}\texttt{\textbackslash pgf@zx}\\ 
 \texttt{\textbackslash pgf@zy}\end{pmatrix}\;,
\end{align}
\end{subequations}
where we indicate the internal pgf dimensions these components get stored in.
\pause
 \item The third row of $O$ can be (almost trivially) reconstructed via
 \begin{align}
  \vec n=\begin{pmatrix}
   O_{31} \\  O_{32} \\ O_{33}\\
  \end{pmatrix}
  &=
  \begin{pmatrix}
   O_{11} \\  O_{12} \\ O_{13}\\
  \end{pmatrix}\times
  \begin{pmatrix}
   O_{21} \\  O_{22} \\ O_{23}\\
  \end{pmatrix}\notag\\
  &=
  \begin{pmatrix}
   \texttt{\textbackslash pgf@xx} \\ 
   \texttt{\textbackslash pgf@yx} \\ 
   \texttt{\textbackslash pgf@zx}\\
  \end{pmatrix}\times
  \begin{pmatrix}
   \texttt{\textbackslash pgf@xy} \\  
   \texttt{\textbackslash pgf@yy} \\ 
   \texttt{\textbackslash pgf@zx}\\
  \end{pmatrix}\;.\label{eq:d_screen}
 \end{align}
\pause
 \item The screen depth, i.e.\ the amount by which a point $\vec P=(x,y,z)$ is above or below the
  screen zero plane, is thus given by
  \begin{equation}
   d_\mathsf{screen}=\vec P\cdot \vec n\;.
  \end{equation}
  The zero of $d_\mathsf{screen}$ depends on conventions. However, the larger 
  $d_\mathsf{screen}$ is, the further ``above'' is $\vec P$ of the screen. This
  means that points with larger  $d_\mathsf{screen}$ are closer to the
  ``observer''. Proper 3d ordering ``only'' means drawing objects with larger
  $d_\mathsf{screen}$ later. As is evident from \eqref{eq:d_screen}, one can
  compute $d_\mathsf{screen}$ in a package--independent way, i.e.\ without
  knowing whether the 3d view got installed with \texttt{tikz-3dplot},
  the official \texttt{perspective} library or the inofficial 
  \texttt{3dtools} library.
\pause
 \item With regards to the visbility on a sphere, since by convention the center
 of the sphere is at the origin, only points with nonnegative 
 $d_\mathsf{screen}$ are on the foreside of the sphere, i.e.\ visible. As
 explained before, establishing the visibility can thus be done in a package- or
 convention--independent way. Of course, if the user does not use an
 orthographic projection, none of this applies in full generality.
\end{enumerate}
\end{frame}
\end{document}

enter image description here

Now to the actual answer of the question. Here is something that connects two points on a sphere by an arc along a great circle. These can have arbitrary polar coordinates. Even though I am working tikz-3dplot here you can use any tool that installs an orthographic view.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{fpu}
\makeatletter
\pgfmathdeclarefunction{isfore}{3}{%
\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{%
sign(((\the\pgf@yx)*(\the\pgf@zy)-(\the\pgf@yy)*(\the\pgf@zx))*(#1)+
((\the\pgf@zx)*(\the\pgf@xy)-(\the\pgf@xx)*(\the\pgf@zy))*(#2)+
((\the\pgf@xx)*(\the\pgf@yy)-(\the\pgf@yx)*(\the\pgf@xy))*(#3))}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\tikzset{great circle arc/.cd,
    theta1/.initial=0,phi1/.initial=0,theta2/.initial=0,phi2/.initial=30,
    r/.initial=R,fore/.style={draw=white,semithick},back/.style={draw=gray,very thin}}

\newcommand\GreatCircleArc[2][]{%
\tikzset{great circle arc/.cd,#2}%
\def\pv##1{\pgfkeysvalueof{/tikz/great circle arc/##1}}%
 % Cartesian coordinates of the first point (A) 
\pgfmathsetmacro\tikz@td@Ax{\pv{r}*cos(\pv{theta1})*cos(\pv{phi1})}%
\pgfmathsetmacro\tikz@td@Ay{\pv{r}*cos(\pv{theta1})*sin(\pv{phi1})}%
\pgfmathsetmacro\tikz@td@Az{\pv{r}*sin(\pv{theta1})}%
 % Cartesian coordinates of the second point (B) 
\pgfmathsetmacro\tikz@td@Bx{\pv{r}*cos(\pv{theta2})*cos(\pv{phi2})}%
\pgfmathsetmacro\tikz@td@By{\pv{r}*cos(\pv{theta2})*sin(\pv{phi2})}%
\pgfmathsetmacro\tikz@td@Bz{\pv{r}*sin(\pv{theta2})}%
 % cross product C=AxB 
\pgfmathsetmacro\tikz@td@Cx{(\tikz@td@Ay)*(\tikz@td@Bz)-(\tikz@td@By)*(\tikz@td@Az)}%
\pgfmathsetmacro\tikz@td@Cy{(\tikz@td@Az)*(\tikz@td@Bx)-(\tikz@td@Bz)*(\tikz@td@Ax)}%
\pgfmathsetmacro\tikz@td@Cz{(\tikz@td@Ax)*(\tikz@td@By)-(\tikz@td@Bx)*(\tikz@td@Ay)}%
 % normalize C to have length r
\pgfmathsetmacro\pgfutil@tempa{sqrt((\tikz@td@Cx)*(\tikz@td@Cx)+(\tikz@td@Cy)*(\tikz@td@Cy)+(\tikz@td@Cz)*(\tikz@td@Cz))/\pv{r}}%
\pgfmathsetmacro\tikz@td@Cx{\tikz@td@Cx/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Cy{\tikz@td@Cy/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Cz{\tikz@td@Cz/\pgfutil@tempa}%
 % angle between A and B
\pgfmathsetmacro\tikz@td@AdotB{((\tikz@td@Ax)*(\tikz@td@Bx)+
    (\tikz@td@Ay)*(\tikz@td@By)+(\tikz@td@Az)*(\tikz@td@Bz))/(\pv{r}*\pv{r})}% 
\pgfmathsetmacro\tikz@td@angle{acos(\tikz@td@AdotB)}%   
 % cross product D=AxC
\pgfmathsetmacro\tikz@td@Dx{(\tikz@td@Ay)*(\tikz@td@Cz)-(\tikz@td@Cy)*(\tikz@td@Az)}%
\pgfmathsetmacro\tikz@td@Dy{(\tikz@td@Az)*(\tikz@td@Cx)-(\tikz@td@Cz)*(\tikz@td@Ax)}%
\pgfmathsetmacro\tikz@td@Dz{(\tikz@td@Ax)*(\tikz@td@Cy)-(\tikz@td@Cx)*(\tikz@td@Ay)}%
\pgfmathsetmacro\pgfutil@tempa{sqrt((\tikz@td@Dx)*(\tikz@td@Dx)+(\tikz@td@Dy)*(\tikz@td@Dy)+(\tikz@td@Dz)*(\tikz@td@Dz))/\pv{r}}%
\pgfmathsetmacro\tikz@td@Dx{\tikz@td@Dx/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Dy{\tikz@td@Dy/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Dz{\tikz@td@Dz/\pgfutil@tempa}%
 %\typeout{A=(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az),B=(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz),C=(\tikz@td@Cx,\tikz@td@Cy,\tikz@td@Cz)}
 %\typeout{\tikz@td@AdotB,\tikz@td@angle}
\edef\pgfutil@tempa{0}%
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\edef\tikz@td@lstviscoords{}%
\else
\edef\tikz@td@lsthidcoords{}%
\edef\tikz@td@lstviscoords{(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\fi
\pgfmathtruncatemacro\pgfutil@tempb{acos(\tikz@td@AdotB)}%
\pgfmathtruncatemacro\pgfutil@tempc{sign(\pgfutil@tempb)}%
\loop
\pgfmathsetmacro{\tmpx}{cos(\pgfutil@tempa)*\tikz@td@Ax-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dx}%
\pgfmathsetmacro{\tmpy}{cos(\pgfutil@tempa)*\tikz@td@Ay-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dy}%
\pgfmathsetmacro{\tmpz}{cos(\pgfutil@tempa)*\tikz@td@Az-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dz}%
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tmpx,\tmpy,\tmpz)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{\tikz@td@lsthidcoords\space(\tmpx,\tmpy,\tmpz)}%
\else
\edef\tikz@td@lstviscoords{\tikz@td@lstviscoords\space(\tmpx,\tmpy,\tmpz)}%
\fi
\edef\pgfutil@tempa{\the\numexpr\pgfutil@tempa+1}%
\ifnum\pgfutil@tempa<\the\numexpr\pgfutil@tempc*\pgfutil@tempb\relax
\repeat
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{\tikz@td@lsthidcoords\space(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\else
\edef\tikz@td@lstviscoords{\tikz@td@lstviscoords\space(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\fi
\ifx\tikz@td@lsthidcoords\pgfutil@empty%
\else
\draw[great circle arc/back] plot coordinates {\tikz@td@lsthidcoords};%
\fi
\ifx\tikz@td@lstviscoords\pgfutil@empty%
\else
\draw[great circle arc/fore] plot coordinates {\tikz@td@lstviscoords};%
\fi
}
\makeatother

\begin{document}

\begin{tikzpicture}[declare function={R=3;},bullet/.style={circle,fill,inner
sep=2pt}]
\shade[ball color = black!80,transform canvas={rotate=-35}] (0,0,0) circle[radius=R];
\tdplotsetmaincoords{70}{110}

\begin{scope}[tdplot_main_coords]
\GreatCircleArc{theta1=-40,phi1=5,theta2=-40,phi2=100}
\GreatCircleArc{theta1=-40,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=0,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=40,phi2=100}
\GreatCircleArc{theta1=-40,phi1=5,theta2=40,phi2=5}
\GreatCircleArc{theta1=-40,phi1=100,theta2=40,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=40,phi2=-90}
\end{scope}

\end{tikzpicture}
\end{document}

enter image description here

The view is freely adjustable.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{fpu}
\makeatletter
\pgfmathdeclarefunction{isfore}{3}{%
\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{%
sign(((\the\pgf@yx)*(\the\pgf@zy)-(\the\pgf@yy)*(\the\pgf@zx))*(#1)+
((\the\pgf@zx)*(\the\pgf@xy)-(\the\pgf@xx)*(\the\pgf@zy))*(#2)+
((\the\pgf@xx)*(\the\pgf@yy)-(\the\pgf@yx)*(\the\pgf@xy))*(#3))}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\tikzset{great circle arc/.cd,
    theta1/.initial=0,phi1/.initial=0,theta2/.initial=0,phi2/.initial=30,
    r/.initial=R,fore/.style={draw=white,semithick},back/.style={draw=gray,very thin}}

\newcommand\GreatCircleArc[2][]{%
\tikzset{great circle arc/.cd,#2}%
\def\pv##1{\pgfkeysvalueof{/tikz/great circle arc/##1}}%
 % Cartesian coordinates of the first point (A) 
\pgfmathsetmacro\tikz@td@Ax{\pv{r}*cos(\pv{theta1})*cos(\pv{phi1})}%
\pgfmathsetmacro\tikz@td@Ay{\pv{r}*cos(\pv{theta1})*sin(\pv{phi1})}%
\pgfmathsetmacro\tikz@td@Az{\pv{r}*sin(\pv{theta1})}%
 % Cartesian coordinates of the second point (B) 
\pgfmathsetmacro\tikz@td@Bx{\pv{r}*cos(\pv{theta2})*cos(\pv{phi2})}%
\pgfmathsetmacro\tikz@td@By{\pv{r}*cos(\pv{theta2})*sin(\pv{phi2})}%
\pgfmathsetmacro\tikz@td@Bz{\pv{r}*sin(\pv{theta2})}%
 % cross product C=AxB 
\pgfmathsetmacro\tikz@td@Cx{(\tikz@td@Ay)*(\tikz@td@Bz)-(\tikz@td@By)*(\tikz@td@Az)}%
\pgfmathsetmacro\tikz@td@Cy{(\tikz@td@Az)*(\tikz@td@Bx)-(\tikz@td@Bz)*(\tikz@td@Ax)}%
\pgfmathsetmacro\tikz@td@Cz{(\tikz@td@Ax)*(\tikz@td@By)-(\tikz@td@Bx)*(\tikz@td@Ay)}%
 % normalize C to have length r
\pgfmathsetmacro\pgfutil@tempa{sqrt((\tikz@td@Cx)*(\tikz@td@Cx)+(\tikz@td@Cy)*(\tikz@td@Cy)+(\tikz@td@Cz)*(\tikz@td@Cz))/\pv{r}}%
\pgfmathsetmacro\tikz@td@Cx{\tikz@td@Cx/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Cy{\tikz@td@Cy/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Cz{\tikz@td@Cz/\pgfutil@tempa}%
 % angle between A and B
\pgfmathsetmacro\tikz@td@AdotB{((\tikz@td@Ax)*(\tikz@td@Bx)+
    (\tikz@td@Ay)*(\tikz@td@By)+(\tikz@td@Az)*(\tikz@td@Bz))/(\pv{r}*\pv{r})}% 
\pgfmathsetmacro\tikz@td@angle{acos(\tikz@td@AdotB)}%   
 % cross product D=AxC
\pgfmathsetmacro\tikz@td@Dx{(\tikz@td@Ay)*(\tikz@td@Cz)-(\tikz@td@Cy)*(\tikz@td@Az)}%
\pgfmathsetmacro\tikz@td@Dy{(\tikz@td@Az)*(\tikz@td@Cx)-(\tikz@td@Cz)*(\tikz@td@Ax)}%
\pgfmathsetmacro\tikz@td@Dz{(\tikz@td@Ax)*(\tikz@td@Cy)-(\tikz@td@Cx)*(\tikz@td@Ay)}%
\pgfmathsetmacro\pgfutil@tempa{sqrt((\tikz@td@Dx)*(\tikz@td@Dx)+(\tikz@td@Dy)*(\tikz@td@Dy)+(\tikz@td@Dz)*(\tikz@td@Dz))/\pv{r}}%
\pgfmathsetmacro\tikz@td@Dx{\tikz@td@Dx/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Dy{\tikz@td@Dy/\pgfutil@tempa}%
\pgfmathsetmacro\tikz@td@Dz{\tikz@td@Dz/\pgfutil@tempa}%
 %\typeout{A=(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az),B=(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz),C=(\tikz@td@Cx,\tikz@td@Cy,\tikz@td@Cz)}
 %\typeout{\tikz@td@AdotB,\tikz@td@angle}
\edef\pgfutil@tempa{0}%
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\edef\tikz@td@lstviscoords{}%
\else
\edef\tikz@td@lsthidcoords{}%
\edef\tikz@td@lstviscoords{(\tikz@td@Ax,\tikz@td@Ay,\tikz@td@Az)}%
\fi
\pgfmathtruncatemacro\pgfutil@tempb{acos(\tikz@td@AdotB)}%
\pgfmathtruncatemacro\pgfutil@tempc{sign(\pgfutil@tempb)}%
\loop
\pgfmathsetmacro{\tmpx}{cos(\pgfutil@tempa)*\tikz@td@Ax-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dx}%
\pgfmathsetmacro{\tmpy}{cos(\pgfutil@tempa)*\tikz@td@Ay-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dy}%
\pgfmathsetmacro{\tmpz}{cos(\pgfutil@tempa)*\tikz@td@Az-\pgfutil@tempc*sin(\pgfutil@tempa)*\tikz@td@Dz}%
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tmpx,\tmpy,\tmpz)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{\tikz@td@lsthidcoords\space(\tmpx,\tmpy,\tmpz)}%
\else
\edef\tikz@td@lstviscoords{\tikz@td@lstviscoords\space(\tmpx,\tmpy,\tmpz)}%
\fi
\edef\pgfutil@tempa{\the\numexpr\pgfutil@tempa+1}%
\ifnum\pgfutil@tempa<\the\numexpr\pgfutil@tempc*\pgfutil@tempb\relax
\repeat
\pgfmathtruncatemacro{\pgfutil@tempd}{isfore(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\ifnum\pgfutil@tempd=-1\relax
\edef\tikz@td@lsthidcoords{\tikz@td@lsthidcoords\space(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\else
\edef\tikz@td@lstviscoords{\tikz@td@lstviscoords\space(\tikz@td@Bx,\tikz@td@By,\tikz@td@Bz)}%
\fi
\ifx\tikz@td@lsthidcoords\pgfutil@empty%
\else
\draw[great circle arc/back] plot coordinates {\tikz@td@lsthidcoords};%
\fi
\ifx\tikz@td@lstviscoords\pgfutil@empty%
\else
\draw[great circle arc/fore] plot coordinates {\tikz@td@lstviscoords};%
\fi
}
\makeatother

\begin{document}
\foreach \Angle in {5,15,...,355}
{\tdplotsetmaincoords{90+20*cos(\Angle)}{\Angle}
\begin{tikzpicture}[declare function={R=3;},bullet/.style={circle,fill,inner
sep=2pt}]
\shade[ball color = black!80,transform canvas={rotate=-35}] (0,0,0) circle[radius=R];


\begin{scope}[tdplot_main_coords]
\GreatCircleArc{theta1=-40,phi1=5,theta2=-40,phi2=100}
\GreatCircleArc{theta1=-40,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=0,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=0,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=40,phi2=100}
\GreatCircleArc{theta1=-40,phi1=5,theta2=40,phi2=5}
\GreatCircleArc{theta1=-40,phi1=100,theta2=40,phi2=100}
\GreatCircleArc{theta1=40,phi1=5,theta2=40,phi2=-90}
\end{scope}
\end{tikzpicture}}
\end{document}

enter image description here

| improve this answer | |
  • Almost only you answer 3D questions. – minhthien_2016 Apr 11 at 5:20
  • @minhthien_2016 You're right. I adde a long explanation on what's going on here, hoping that this will enable others to write similar answers (which are conceptually all very similar). – user194703 Apr 12 at 0:01
  • Thank you so much for this fantastic answer! Definitely above and beyond. The diagram I created is here. @schrödingers-cat I think there is an opportunity to create a package of macros to abstract much of the drawing; this was my first TikZ diagram and I would have struggled coming up with this answer. I'd be happy to collaborate on one if there is interest. I think it would be broadly useful! – Demitri Apr 20 at 23:36
  • @Demitri You're welcome and glad you like it. Some more efforts to make TikZ more versatile in 3d are collected here. IMHO one would only need to add a rather minor addition to TikZ to have access to many more features in a very simple way, see here. But I do not think that the maintainer(s) of TikZ will ever do that :-( – user194703 Apr 20 at 23:42
  • @schrödingers-cat I think even an external file of definitions would go a long way; modifying TikZ doesn't seem necessary as the code above demonstrates. Happy to chat off line; I can be reached at "github" at my username dot com. – Demitri Apr 21 at 0:48

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.