Viviani curve with no self intersection

Compile on your computer with Asymptote.

settings.outformat="pdf"; 
settings.prc=false;
settings.render=0;
import x11colors;
import graph3;
size(8cm,0); 

/*      
      real h = 5; 
      triple[] axes = new triple[] {X, Y, Z};
      for(int i=0; i<axes.length; ++i){
        draw(O--h*axes[i],Arrow3());
      }
 */     
currentprojection = orthographic(0,-1,0.5); 
surface sphere=surface(new triple(pair p) {
  real t=p.x, s=p.y; 
  return (1+cos(t)*sin(s),sin(t)*sin(s),cos(s));},  (0,0),(2*pi,2*pi),Spline);
 draw(sphere,lightblue+opacity(.6),MidnightBlue+0.1bp); 

surface cylinder=surface(new triple(pair p) {
  real t=p.x, s=p.y;
  return (cos(t),sin(t),s);}, (0,-2),(2*pi,2),Spline);
draw(cylinder,  lightblue+opacity(.6),MidnightBlue+0.1bp); 

draw(graph(new triple(real t) {return 
       (cos(t),
        sin(t), 
        sqrt(2*cos(t)-1)); },
-pi/3,pi/3,300),red+1.5bp);
draw(graph(new triple(real t) {return 
       (cos(t),
        sin(t), 
        -sqrt(2*cos(t)-1)); },
-pi/3,pi/3,300),red+1.5bp);
shipout(bbox(2mm,invisible));

enter image description here

Compile the code above without

settings.outformat="pdf"; 
settings.prc=false;
settings.render=0;

and without shipout(bbox(2mm,invisible));

in http://asymptote.ualberta.ca/ to get an interaction.

enter image description here


This is what I got. You might want to fine-tune the z-buffer.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{compat=1.17}
\begin{document}

\def\CylinderLower[#1]{
    \addplot3[surf,z buffer=sort,
        domain=-180:180, samples=60,
        domain y=-1.2:0, samples y=2,
        #1
    ]({cos(x)}, {sin(x)}, {min(y, -sqrt(1-4*sin(x/2)^2) )});
}

\def\CylinderInner[#1]{
    \addplot3[surf,z buffer=sort,
        domain=-60:60, samples=30,
        domain y=-1:1, samples y=2,
        #1
    ]({cos(x)}, {sin(x)}, {y * sqrt(1-4*sin(x/2)^2)});
}

\def\CylinderUpper[#1]{
    \addplot3[surf,z buffer=sort,
        domain=-180:180, samples=60,
        domain y=0:1.2, samples y=2,
        #1
    ]({cos(x)}, {sin(x)}, {max(y, sqrt(1-4*sin(x/2)^2) )});
}

\pgfmathdeclarefunction{dual}1{\pgfmathparse{sqrt(1-(#1)^2)}}

\def\SphereInner[#1]{
    \addplot3[surf,z buffer=sort,
        domain=-1:1, samples=10,
        domain y=-1:1, samples y=20,
        #1
    ]({1 - cos(x*acos(dual(y)/2)) * dual(y)},
        {sin(x*acos(dual(y)/2)) * dual(y)},
            {y});
}

\def\SphereOuter[#1]{
    \addplot3[surf,z buffer=sort,
        domain=-1:1, samples=10,
        domain y=-1:1, samples y=20,
        #1
    ]({1 + cos(x*acos(-dual(y)/2)) * dual(y)},
        {sin(x*acos(-dual(y)/2)) * dual(y)},
            {y});
}


\tikz[cap=round,join=round]{
    \begin{axis}[axis equal,]
        \CylinderLower[point meta=x]
        \SphereInner[point meta=-z^2,opacity=.9]
        \CylinderInner[point meta=x,opacity=.5]
    \end{axis}
}

\end{document}