6

I am trying to draw the triangulation of a 2-sphere in $\R^3$ that is induced by a tetrahedron using tikz-3dplot.

What I got so far are the sphere and the corners of the tetrahedron as well as edges starting from the north pole. Since I use spherical coordinates, I tried to use rotation of my constructions to also get the edges on "the bottom of the tetrahedron", but I cannot come up with the right solution.

Here is my complete and minimal example:

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections}
\usepackage{tikz-3dplot}  
\newcommand{\sphToCart}[3]
        {
          \def\rpar{#1}
          \def\thetapar{#2}
          \def\phipar{#3}  
          \pgfmathsetmacro{\x}{\rpar*sin(\thetapar)*cos(\phipar)}
          \pgfmathsetmacro{\y}{\rpar*sin(\thetapar)*sin(\phipar)}
          \pgfmathsetmacro{\z}{\rpar*cos(\thetapar)}
        }  
\begin{document}
 \tdplotsetmaincoords{60}{120}
\begin{tikzpicture}[tdplot_main_coords, shift={(0,0)}]
  \coordinate (O) at (0,0,0);
% S^2
\draw[tdplot_screen_coords] (0,0,0) circle (3);
% Upper point in the tetraeder
    \def\thetaA{0}
    \def\phiA{0}
    \sphToCart{3}{\thetaA}{\phiA}
    \coordinate (A) at (\x,\y,\z) ;
    \filldraw (A) circle (2pt);
% 1st lower point
    \def\thetaA{109.5}
    \def\phiA{0}
    \sphToCart{3}{\thetaA}{\phiA}
    \coordinate (B) at (\x,\y,\z);
    \filldraw (B) circle (2pt);
\tdplotsetthetaplanecoords{\phiA}
\draw[tdplot_rotated_coords] (3,0,0) arc (0:109.5:3);
% 2nd lower point
    \def\thetaA{109.5}
    \def\phiA{120}
    \sphToCart{3}{\thetaA}{\phiA}
    \coordinate (C) at (\x,\y,\z);
    \filldraw (C) circle (2pt);
\tdplotsetthetaplanecoords{\phiA}
\draw[tdplot_rotated_coords] (3,0,0) arc (0:109.5:3);
% 3rd lower point
    \def\thetaA{109.5}
    \def\phiA{240}
    \sphToCart{3}{\thetaA}{\phiA}
    \coordinate (D) at (\x,\y,\z);
    \filldraw (D) circle (2pt);
\tdplotsetthetaplanecoords{\phiA}
\draw[tdplot_rotated_coords] (3,0,0) arc (0:109.5:3);
\end{tikzpicture}
\end{document}

enter image description here

Thanks in advance!

0
4

Welcome to TeX-SE! I do not know if this goes in the right direction but in my experience it is much easier to draw parametric curves, the more so tikz-3dplot autoloads the 3d library which has 3d spherical coordinates.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot}  
\begin{document}
 \tdplotsetmaincoords{60}{111}
\begin{tikzpicture}[tdplot_main_coords]
  \coordinate (O) at (0,0,0);
 % S^2
 \draw[tdplot_screen_coords] (0,0,0) circle (3);
 \path (xyz spherical cs:radius=3,latitude=90,longitude=00)
  node[fill,circle,inner sep=2pt]{}; 
 % the English word for tetraeder is tetrahedron ;-)
 \foreach \X in {0,1,2} 
 {\draw plot[variable=\t,domain=90:90-109.5,smooth] 
  (xyz spherical cs:radius=3,latitude=\t,longitude=\X*120) 
  node[fill,circle,inner sep=2pt]{};}
 \draw plot[variable=\t,domain=0:360,smooth] 
 (xyz spherical cs:radius=3,latitude={90-109.5-14*abs(sin(1.5*\t))},longitude=\t);
\end{tikzpicture}
\end{document}

enter image description here

Or with discerning paths on the foreground and back of the sphere automatically. Please see this answer for a cleaner way, which I did not choose because I was unable so far to teach pgfplots spherical coordinates.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot}
\makeatletter

% from https://tex.stackexchange.com/a/375604/121799
%along x axis
\define@key{x sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{x sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{x sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{x spherical}{% 
    \setkeys{x sphericalkeys}{#1}%
    \pgfpointxyz{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}}

%along y axis
\define@key{y sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{y sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{y sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{y spherical}{% 
    \setkeys{y sphericalkeys}{#1}%
    \pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*sin(\myphi)}}


%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}{% 
    \setkeys{z sphericalkeys}{#1}%
    \pgfmathsetmacro{\Xtest}{sin(\tdplotmaintheta)*cos(\tdplotmainphi-90)*sin(\mytheta)*cos(\myphi)
    +sin(\tdplotmaintheta)*sin(\tdplotmainphi-90)*sin(\mytheta)*sin(\myphi)
    +cos(\tdplotmaintheta)*cos(\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
    \xdef\MCheatOpa{0.3}
    \else
    \xdef\MCheatOpa{1}
    \fi
    %\typeout{\mytheta,\tdplotmaintheta;\myphi,\tdplotmainphi:\ntest}
    \pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}{\myradius*cos(\mytheta)}}

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

\pgfdeclareplothandler{\pgfplothandlercurveto}{}{%
  point macro=\pgf@plot@curveto@handler@initial,
  jump macro=\pgf@plot@smooth@next@moveto,
  end macro=\pgf@plot@curveto@handler@finish
}

\def\pgf@plot@smooth@next@moveto{%
  \pgf@plot@curveto@handler@finish%
  \global\pgf@plot@startedfalse%
  \global\let\pgf@plotstreampoint\pgf@plot@curveto@handler@initial%
}

\def\pgf@plot@curveto@handler@initial#1{%
  \pgf@process{#1}%
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \pgf@plot@first@action{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
  \xdef\pgf@plot@curveto@first{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
  \global\let\pgf@plot@curveto@first@support=\pgf@plot@curveto@first%
  \global\let\pgf@plotstreampoint=\pgf@plot@curveto@handler@second%
}

\def\pgf@plot@curveto@handler@second#1{%
  \pgf@process{#1}%
  \xdef\pgf@plot@curveto@second{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
  \global\let\pgf@plotstreampoint=\pgf@plot@curveto@handler@third%
  \global\pgf@plot@startedtrue%
}

\def\pgf@plot@curveto@handler@third#1{%
  \pgf@process{#1}%
  \xdef\pgf@plot@curveto@current{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
  % compute difference vector:
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \pgf@process{\pgf@plot@curveto@first}
  \advance\pgf@xa by-\pgf@x%
  \advance\pgf@ya by-\pgf@y%
  % compute support directions:
  \pgf@xa=\pgf@plottension\pgf@xa%
  \pgf@ya=\pgf@plottension\pgf@ya%
  % first marshal:
  \pgf@process{\pgf@plot@curveto@second}%
  \pgf@xb=\pgf@x%
  \pgf@yb=\pgf@y%
  \pgf@xc=\pgf@x%
  \pgf@yc=\pgf@y%
  \advance\pgf@xb by-\pgf@xa%
  \advance\pgf@yb by-\pgf@ya%
  \advance\pgf@xc by\pgf@xa%
  \advance\pgf@yc by\pgf@ya%
  \@ifundefined{MCheatOpa}{}{%
  \pgf@plotstreamspecial{\pgfsetstrokeopacity{\MCheatOpa}}}
  \edef\pgf@marshal{\noexpand\pgfsetstrokeopacity{\noexpand\MCheatOpa}
  \noexpand\pgfpathcurveto{\noexpand\pgf@plot@curveto@first@support}%
    {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgf@plot@curveto@second}
    \noexpand\pgfusepathqstroke
    \noexpand\pgfpathmoveto{\noexpand\pgf@plot@curveto@second}}%
  {\pgf@marshal}%
  %\pgfusepathqstroke%
  % Prepare next:
  \global\let\pgf@plot@curveto@first=\pgf@plot@curveto@second%
  \global\let\pgf@plot@curveto@second=\pgf@plot@curveto@current%
  \xdef\pgf@plot@curveto@first@support{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
}

\def\pgf@plot@curveto@handler@finish{%
  \ifpgf@plot@started%
    \pgfpathcurveto{\pgf@plot@curveto@first@support}{\pgf@plot@curveto@second}{\pgf@plot@curveto@second}%
  \fi%
}


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


\tdplotsetmaincoords{60}{131}
\begin{tikzpicture}[tdplot_main_coords]
  \coordinate (O) at (0,0,0);
 % S^2
 \draw[tdplot_screen_coords,ball color=gray,fill opacity=0.3] (0,0,0) circle (3);
 \path (xyz spherical cs:radius=\RadiusSphere,latitude=90,longitude=00)
  node[fill,circle,inner sep=2pt]{}; 
 % the English word for tetraeder is tetrahedron ;-)
 \foreach \X in {0,1,2} 
 {\draw plot[variable=\t,domain=0:0-109.5,smooth] 
  (z spherical cs:radius=\RadiusSphere,theta=\t,phi=\X*120) 
  \ifnum\X=2
  node[fill,circle,inner sep=2pt]{}
  \else
  node[fill,circle,inner sep=2pt,opacity=0.3]{}
  \fi;}
 \draw plot[variable=\t,domain=0:360,smooth,samples=121] 
 (z spherical cs:radius=\RadiusSphere,theta={-109.5-14*abs(sin(1.5*\t))},phi=\t);
\end{tikzpicture}
\end{document}

enter image description here

I should also add that I did not compute the lower boundary from first principles, it is only an educated guess.

1
  • That looks like a great solution and I agree that your solution is easier. Thank you!
    – Timo
    Jul 2 '19 at 6:46

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.