Projection of Circle onto Spherical Surface

Well, no prizes for speed (not just because there is some duplication of calculations: TikZ is slow for this kind of stuff), but this shows one way of doing it. I expect asymptote/PSTricks could do it quicker, but I don't see any other way of doing it in TikZ.

The maths is straightforward "back-of-the-envelope" trigonometry (in this case literally). The only "insight" is to draw the circles manually.

EDIT 1 inspired by Jake's missing (at the time of writing) PGF Plots answer, I've changed most of the \foreach statements to TikZ plot commands which makes things a bit quicker.

EDIT 2 changed the critical function to sqrt(\R^2-(\cx+\r*cos(\t))^2-(\cy+\r*sin(\t))^2) as this provides better accuracy than veclen when the circles get near to the edge.

EDIT 3 a second version has been added which uses layers to add both circles at the same time.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[x=(-30:4cm),y=(30:4cm),z=(90:4cm)]

\def\R{1}

\draw (-\R,0,0) -- (\R,0,0);
\draw (0,-\R,0) -- (0,\R,0);
\draw (0,0,0) -- (0,0,\R);
\draw plot [domain=0:360, samples=60, variable=\i] 
    (\R*cos \i, \R*sin \i, 0) -- cycle;

\def\r{0.075}

\foreach \cr in {0.3, 0.5, 0.7, 0.9}
    \foreach \ca [evaluate={\cx=\cr*cos \ca; \cy=\cr*sin \ca;}]in {-90,-60,-30,0,30, 60, 90}
        \draw [green!85!black, fill=green!85!black, fill opacity=0.25]
            plot [domain=0:360, samples=40, variable=\i] 
                (\cx+\r*cos \i, \cy+\r*sin \i, 0) -- cycle;

\foreach \i in {0, 30,...,150}
    \draw [dotted] plot [domain=-90:90, samples=30, variable=\j]        
        (\R*cos \i*sin \j,\R*sin \i*sin \j, \R*cos \j);

\foreach \j in {0, 15,...,90}
    \draw [dotted] plot [domain=0:360, samples=60, variable=\i]  
            (\R*cos \i*sin \j,\R*sin \i*sin \j, \R*cos \j);

\foreach \cr in {0.3, 0.5, 0.7, 0.9}
    \foreach \ca [evaluate={\cx=\cr*cos \ca; \cy=\cr*sin \ca;}]in {-90,-60,-30,0,30, 60, 90}
        \draw [red, fill=red, fill opacity=.25] 
            plot [domain=0:360, samples=40, variable=\t] 
                (\cx+\r*cos \t,\cy+\r*sin \t, {sqrt(\R^2-(\cx+\r*cos(\t))^2-(\cy+\r*sin(\t))^2)})
                    -- cycle;

\end{tikzpicture}

\end{document}

enter image description here

And here's a version using layers and Cartesian rather than polar coordinates for the circles:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}

\pgfdeclarelayer{dome floor}
\pgfdeclarelayer{dome}
\pgfdeclarelayer{dome surface}
\pgfsetlayers{dome floor,main,dome,dome surface}

\def\addcircle#1#2#3#4{%
    \begingroup%
        \pgfmathparse{#1}\let\R=\pgfmathresult
        \pgfmathparse{#2}\let\cx=\pgfmathresult
        \pgfmathparse{#3}\let\cy=\pgfmathresult
        \pgfmathparse{#4}\let\r=\pgfmathresult
        \begin{pgfonlayer}{dome floor}
            \draw [blue!45!black, fill=blue!45, fill opacity=0.25]
                            plot [domain=0:360, samples=40, variable=\i] 
                                (\cx+\r*cos \i, \cy+\r*sin \i, 0) -- cycle;
        \end{pgfonlayer}
        \begin{pgfonlayer}{dome surface}
            \draw [red!75!black, fill=red!75, fill opacity=0.25] 
                plot [domain=0:360, samples=60, variable=\t] 
                    (\cx+\r*cos \t,\cy+\r*sin \t, {sqrt(max(\R^2-(\cx+\r*cos(\t))^2-(\cy+\r*sin(\t))^2, 0))})
                        -- cycle;
        \end{pgfonlayer}
    \endgroup%
}
\begin{tikzpicture}[x=(-30:1cm),y=(30:1cm),z=(90:1cm)]


\def\R{6}

\begin{pgfonlayer}{dome floor}
    \draw (-\R,0,0) -- (\R,0,0);
    \draw (0,-\R,0) -- (0,\R,0);
    \draw plot [domain=0:360, samples=90, variable=\i] 
        (\R*cos \i, \R*sin \i, 0) -- cycle;
\end{pgfonlayer}

\draw (0,0,0) -- (0,0,\R);

\begin{pgfonlayer}{dome surface}
    \foreach \i in {0, 30,...,150}
            \draw [dotted] plot [domain=-90:90, samples=60, variable=\j]        
                (\R*cos \i*sin \j,\R*sin \i*sin \j, \R*cos \j);
    \foreach \j in {0, 15,...,90}
            \draw [dotted] plot [domain=0:360, samples=60, variable=\i]  
                    (\R*cos \i*sin \j,\R*sin \i*sin \j, \R*cos \j);
\end{pgfonlayer}

\def\r{0.5}
\foreach \m [evaluate={\N=max(-4, \m-7);}]in {0,...,5}{
    \foreach \n in {0,-1,...,\N}
        {\addcircle{\R}{\m*sin 60}{\n-mod(abs(\m),2)*\r}{\r}}}


\end{tikzpicture}

\end{document}

enter image description here


enter image description here

Asymptote solution. It uses a function (from the Wiki) to calculate the curve of intersection. Adjust the placement of the circles as needed. s.asy:

size(300,300);
size3(300,300,300);
import graph3;
currentprojection=orthographic(-5,-4,2,center=true);

guide3 sphere_x_cyl(real a, real r, real R, int n=10){
// return a closed curve of the Sphere–cylinder intersection (top part)
// only for the case when a cylinder is completely inside
// except  special case when the x-shift a=0
  assert(a>0,"***** Positive a expected.");

  real b=(R^2-r^2-a^2)/(2a);  
  guide3 g;
  int n=30;
  real phi, dphi;

  phi=0;
  dphi=360/n;

  triple t;
  for(int i=0;i<n;++i){
    t=(r*Cos(phi),r*Sin(phi),sqrt(2a*(b+r*Cos(phi))));
    g=g--t;
    phi+=dphi;
  }
  g=g--cycle;
  return g;
}

void Draw3(guide3 g,pen p=currentpen){
  draw(project(g),p);
}

void FillDraw3(guide3 g,pen fillPen=currentpen, pen linePen=nullpen){
  filldraw(project(g),fillPen,linePen);
}

int nr=11;
real r=1;
real R=nr*r;

real a; // distance between the centers 

triple O=(0,0,0);

guide3 circ(triple sh=O, real r){
  guide3 uc=(r,0,0)..(0,r,0)..(-r,0,0)..(0,-r,0)..cycle;
  return shift(sh)*uc;
}

guide3 semicirc(triple sh=O, real r){
  guide3 uc=(r,0,0)..(0,r,0)..(-r,0,0);
  return shift(sh)*uc;
}

guide3 Parallel(real h, real R){
  return circ((0,0,h),sqrt(R^2-h^2));
}

pen dashed=linetype(new real[] {4,3}); // set up dashed pattern

pen dashCircPen=gray(0.4)+dashed+opacity(1)+0.32pt;
pen boldLine=darkblue+1.2pt;
pen floorCircPen=olive+opacity(0.75);
pen sphereSpotPen=blue+opacity(0.382);


Draw3(O--(0,0,R),boldLine);
Draw3(O--(R,0,0),boldLine);
Draw3(O--(0,R,0),boldLine);
Draw3(O--(-R,0,0),boldLine);
Draw3(O--(0,-R,0),boldLine);
Draw3(circ(R),boldLine);

real h=0;
real dphi=10;
real phi=dphi;
for(int i=1;i<9;++i){
  h=R*Sin(phi);
  Draw3(Parallel(h,R),dashCircPen);
  phi+=dphi;
}

for(int i=0;i<6;++i){
  Draw3(rotate(30*i,(0,0,1))*rotate(90,(1,0,0))*semicirc(R),dashCircPen);
}

int nd=floor((nr-1)/2);
transform3 tr;
for(int j=0;j<3;++j){ 
  a=2r;
  for(int i=0;i<nd;++i){
    tr=rotate(60*j,(0,0,1))*shift((-a,0,0));
    FillDraw3(tr*circ(r),floorCircPen,red);
    FillDraw3(tr*sphere_x_cyl(a,r,R),sphereSpotPen);
    a+=2r;
  }
}
FillDraw3(circ(r),floorCircPen,red);
FillDraw3(shift((0,0,sqrt(R^2-r^2)))*circ(r),sphereSpotPen);

To get a standalone s.pdf run asy -f pdf s.asy.


Here's a way of doing this using PGFPlots:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[hide axis, axis equal, samples=15]
\foreach \posx/\posy in {0/-0.1, 0.6/0.1, 0.6/-0.4, 0.1/-0.7}{
    \addplot3 [red, thick, domain=0:360, samples=20] (
        {cos(x)*0.2+\posx},
        {sin(x)*0.2+\posy},
        {0}
    );
}

\addplot3 [surf, gray, faceted color=gray, opacity=0.5, samples=20, z buffer=sort, domain=0:360, y domain=0:1] ({cos(x)*y},{sin(x)*y},
{sqrt(1-(cos(x)*y)^2-(sin(x)*y)^2))});
\foreach \posx/\posy in {0/-0.1, 0.6/0.1, 0.6/-0.4, 0.1/-0.7}{
    \addplot3 [red, thick, domain=0:360, samples=20] (
        {cos(x)*0.2+\posx},
        {sin(x)*0.2+\posy},
        {sqrt(1-((cos(x)*0.2+\posx))^2-((sin(x)*0.2+\posy))^2))}
    );
}
\end{axis}
\end{tikzpicture}
\end{document}