getwd()
setwd('~/set/to/some/directory')

library(ggplot2)
library(rgl)
library(png)
library(cowplot)


spheres3d(x=0,y=0,z=0,radius=100)

# This lead to a "sphere" with not enough sampled points, so it looks like a 
# polygon representation of a polyhedron.
# Further searching lead me to a Stack Overflow question "How to increase 
# smoothness of spheres3d in rgl" 
# (https://stackoverflow.com/questions/39778093/how-to-increase-smoothness-of-spheres3d-in-rgl)

# The code here is taken from solutions provided there.


# What follows are several balls in the Official UofM Colors
# Note, some of these lines take a little while to run, depending on the 
# resources available to your computer.

sphere <- subdivision3d(dodecahedron3d(),depth=6)
sphere$vb[4,] <- apply(sphere$vb[1:3,], 2, function(x) sqrt(sum(x^2)))
open3d()
shade3d(sphere, col=c("#898D8D","#003087"))

rgl.snapshot("Ball_1.png")

sphere <- subdivision3d(dodecahedron3d(),depth=6)
sphere$vb[4,] <- apply(sphere$vb[1:3,], 2, function(x) sqrt(sum(x^2)))
open3d()
shade3d(sphere, col=c("#003087"))

rgl.snapshot("Ball_Blue.png")

sphere <- subdivision3d(dodecahedron3d(),depth=6)
sphere$vb[4,] <- apply(sphere$vb[1:3,], 2, function(x) sqrt(sum(x^2)))
open3d()
shade3d(sphere, col=c("#898D8D"))

rgl.snapshot("Ball_Gray.png")


sphere.f <- function(x0 = 0, y0 = 0, z0 = 0, r = 1, n = 101, ...){
  f <- function(s, t) cbind(r * cos(s) * cos(t) + x0,
                            r * sin(s) * cos(t) + y0, 
                            r * sin(t) + z0)
  persp3d(f, slim = c(0, pi), tlim = c(0, 2*pi), n = n, add = T, ...)
}

sphere.f(col=c("#898D8D","#003087","#898D8D","#003087","#898D8D","#003087"))

open3d()
rgl.snapshot("Ball_2.png")

sphere.f <- function(x0 = 0, y0 = 0, z0 = 0, r = 1, n = 101, ...){
  f <- function(s, t) cbind(r * cos(s) * cos(t) + x0,
                            r * sin(s) * cos(t) + y0, 
                            r * sin(t) + z0)
  persp3d(f, slim = c(0, pi), tlim = c(0, 2 * pi), n = n, add = T, ...)
}

open3d()
sphere.f(col=c("#898D8D","#003087","#898D8D","#003087","#898D8D","#003087"))

# Here is how the tinsel was produced; it reduces to an application of a the 
# random walk, where each strand of tinsel begins from a the center, and then is
# allowed to go a random distance up or down and right and left.  

# These mimic the randomness in the arrangement of tinsel, and the
# different in distance from the center give lend a quasi-three-dimensional feel
# to the border.

# Each strand alternates between the University Blue and University Gray.

# A sinusoidal wave was then added to all the point. 

# Note that every time this code is run, it will generate a different border 
# design.

n <- 4000

tinsel <- data.frame(x = rep(0,n),
                     xend = sample(size = n, seq(-3,3, by = 0.25), 
                                   replace = TRUE),
                     y = c(1:n), 
                     yend = c(1:n) + sample(size = n, seq(-10,10, by = 0.05), 
                                            replace = TRUE),
                     color = c("#898D8D","#003087"))

tinsel$x <- 1.75 * sin(2 * pi * c(1:n)  / 250)
tinsel$xend <- 1.75 * sin(2 * pi * c(1:n)  / 250)  + tinsel$xend

tinsel_plot <- ggplot(tinsel) + 
  geom_segment(aes(x = x, 
                   xend = xend,
                   y = y,
                   yend = yend),
               color = tinsel$color) + 
  coord_cartesian(xlim = c(-5,5)) +
  theme_bw() + 
  theme(panel.grid = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank(),
        panel.border = element_blank())

tinsel_plot

Ball_1 <- png::readPNG("Ball_1_nobg.png", native = TRUE)
Ball_2 <- png::readPNG("Ball_2_nobg.png", native = TRUE)
Ball_B <- png::readPNG("Ball_Blue_nobg.png", native = TRUE)
Ball_G <- png::readPNG("Ball_Gray_nobg.png", native = TRUE)
ball_1 <- grid::rasterGrob(Ball_1, interpolate=TRUE)
ball_2 <- grid::rasterGrob(Ball_2, interpolate=TRUE)
ball_b <- grid::rasterGrob(Ball_B, interpolate=TRUE)
ball_g <- grid::rasterGrob(Ball_G, interpolate=TRUE)


ggplot2::ggsave(filename = "tinsel.png", width = 0.375, height = 10,
                units = "in", dpi = 600)
tinsel_plot

final_plot <- ggdraw() +
  draw_plot(tinsel_plot) +
  draw_image(Ball_1,  x = 0, y =  0.42, scale = 1) +
  draw_image(Ball_2,  x = 0, y =  0.36, scale = 1) +
  draw_image(Ball_B,  x = 0, y =  0.30, scale = 1) +
  draw_image(Ball_G,  x = 0, y =  0.24, scale = 1) +
  draw_image(Ball_1,  x = 0, y =  0.18, scale = 1) +
  draw_image(Ball_2,  x = 0, y =  0.12, scale = 1) +
  draw_image(Ball_B,  x = 0, y =  0.06, scale = 1) +
  draw_image(Ball_G,  x = 0, y =  0.00, scale = 1) +
  draw_image(Ball_B,  x = 0, y = -0.06, scale = 1) +
  draw_image(Ball_2,  x = 0, y = -0.12, scale = 1) +
  draw_image(Ball_1,  x = 0, y = -0.18, scale = 1) +
  draw_image(Ball_G,  x = 0, y = -0.24, scale = 1) +
  draw_image(Ball_B,  x = 0, y = -0.30, scale = 1) +
  draw_image(Ball_2,  x = 0, y = -0.36, scale = 1) +
  draw_image(Ball_1,  x = 0, y = -0.42, scale = 1) 


final_plot

ggplot2::ggsave(final_plot, filename = "tinsel2.png", width = 0.375, height = 10,
                units = "in", dpi = 600)

520 / 457 * 300