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