Premise
I was recently asked to print out a fabric pattern that could be used to cover a sphere, about the size of a ping pong ball, for the purposes of re-creating a favorite cat toy (quite important). Thinking this over, I realized that this was basically a map projection problem-- and could probably be solved by scaling an interrupted sinusoidal projection to match the geometry of a ping pong ball. Below are some R functions, and examples of how this endeavor evolved. Thanks to Greg Snow for this helpful post on the R-mailing list, describing how to preserve linear measurement when composing a figure in R. So far the pattern doesn't quite fit.

Update
It looks like it was not the printer's fault-- I had used the wrong radius for a ping pong ball: 16mm instead of 19mm or 20mm (there are 38mm and 40mm diameter ping pong balls). Updated files are attached.

Sinusoidal Projection
Figure: Sinusoidal Projection

Function Defs

# scale to C of ping pong ball:
# r = 16mm
# C = 2 * pi * 19  = 119.3805 mm (for a 38mm diameter ball)
# A = 4 * pi * r^2 = 4536.46 sq. mm
# n: number of slices
# circ: target circumference
# d: number of degrees per increment
sphere.slice <- function(n=4circd=10)
        {
       
        # define sinusoidal projection function, fully vectorized
        # http://en.wikipedia.org/wiki/Sinusoidal_projection
        f <- function(lonlatlon_0=0x_0=0)
                {
                x <- x_0 + ( (lon - lon_0) * cos((lat*pi/180)) )
                y <- lat
                d <- data.frame(xy)  
                return(d)
                }
       
        # temp lists used to store intermediate results
        l <- list()
        l.sin <- list()
       
        # sequences that define longitudinal slices:
        # slice edges
        s <- seq(from=-180to=180by=360/n)
        # slice centers
        s_lon_0 <- seq(from=-180to=180by=360/n) + (360/n)/2
        # slice false eastings
        s_x_0 <- seq(from=0to=360by=360/n)
       
       
        # generate slices
        for(i in 1:n)
                {
                l[[i]] <- rbind(data.frame(lon=s[i]lat=seq(-9090by=d))data.frame(lon=s[i+1]lat=seq(90-90by=-d)))  
                }
       
        # project slices
        for(i in 1:n)
                {
                l.sin[[i]] <- data.frame(f(l[[i]]$lonl[[i]]$latlon_0=s_lon_0[i]x_0=s_x_0[i])lon_0=s_lon_0[i])
                }
       
        # combine into DF
        g <- ldply(l.sin)
       
        # scale to user-supplied circumference
        g.scaled <- with(gdata.frame(x=x * circ/360y=y * circ/360lon_0=lon_0))
       
        # done!
        return(g.scaled)
        }
X

Try With Ping Pong Ball Geometry

# need these
library(lattice)
library(plyr)
library(sp)
# try it out
g.scaled <- sphere.slice(n=4circ=2*pi*19d=5)
#check visually: aspect is scaled properly
xyplot(y ~ xdata=g.scaledgroups=lon_0pch=4cex=0.5aspect='iso'type=c('p','g'))
## check circ: OK
sum(abs(range(g.scaled$x)))
sum(abs(range(g.scaled$y))) * 2
# check area, by converting to polygons
p.list <- by(g.scaledg.scaled$lon_0function(p) {
Polygon(round(p[,1:2]4))
})
# compute total area of leaves
sum(sapply(p.listfunction(i) i@area))
# this is only 3 sq.mm off
4533.58
X

Generate PDF Output at 1:1 Scale

## plot at 1:1 resolution for printing
# http://n4.nabble.com/plot-scale-td906260.html#a906260
# convert to inches
g.scaled.in <- with(g.scaleddata.frame(x=x * 0.03937008y=y * 0.03937008lon_0=lon_0))
dev.new()
tmp <- par('plt')
scale <- 1
dx <- diff(range(g.scaled.in$x))*1.08
wx <- grconvertX(dx/scalefrom='inches'to='ndc')
dy <- diff(range(g.scaled.in$y))*1.08
wy <- grconvertY(dy/scalefrom='inches'to='ndc')
par(plt = c(tmp[1]tmp[1]+wxtmp[3]tmp[3]+wy) )
# setup plot, but don't actually plot anything
plot(g.scaled.in$x,g.scaled.in$ytype='n')
# add a grid
grid()
# add each slice, as lines
by(g.scaled.ing.scaled.in$lon_0function(i)
{
lines(i$xi$y)
})
X

Attachment: sphere.pdf