# Load packages
pacman::p_load(pacman, tidyverse, GGally, ggthemes, ggplot2, ggvis, httr, plotly, rio, rmarkdown, shiny, rgl)

# Define the parametric equations for a Klein bottle
klein_bottle <- function(u, v) {
  x <- -2/15 * cos(u) * (3*cos(v) - 30*sin(u) + 90*cos(u)^4*sin(u) - 60*cos(u)^6*sin(u) + 5*cos(u)*cos(v)*sin(u))
  y <- -1/15 * sin(u) * (3*cos(v) - 3*cos(u)^2*cos(v) - 48*cos(u)^4*cos(v) + 48*cos(u)^6*cos(v) - 60*sin(u) + 5*cos(u)*cos(v)*sin(u) - 5*cos(u)^3*cos(v)*sin(u) - 80*cos(u)^5*cos(v)*sin(u) + 80*cos(u)^7*cos(v)*sin(u))
  z <- 2/15 * (3 + 5*cos(u)*sin(u)) * sin(v)

  return(list(x = x, y = y, z = z))
}

# Generate the points for the Klein bottle
u <- seq(0, 2 * pi, length.out = 100)
v <- seq(0, 2 * pi, length.out = 100)
surface <- expand.grid(u = u, v = v)
coords <- vector("list", 3)
coords[[1]] <- matrix(0, nrow = nrow(surface), ncol = ncol(surface))
coords[[2]] <- matrix(0, nrow = nrow(surface), ncol = ncol(surface))
coords[[3]] <- matrix(0, nrow = nrow(surface), ncol = ncol(surface))
for (i in 1:nrow(surface)) {
  point <- klein_bottle(surface$u[i], surface$v[i])
  coords[[1]][i] <- point$x
  coords[[2]][i] <- point$y
  coords[[3]][i] <- point$z
}

# Save the coordinates to a CSV file, used for upload to Kaggle.
klein_coords <- data.frame(x = unlist(coords[[1]]), y = unlist(coords[[2]]), z = unlist(coords[[3]]))
write.csv(klein_coords, "klein_bottle_coordinates.csv", row.names = FALSE)

# Define a colour palette (e.g., rainbow, heat.colors, terrain.colors, topo.colors)
colours <- colorRampPalette(heat.colors(5))(length(u) * length(v))

# Now, you can use these colours when plotting: (Displayed in the viewer tab, when in posit.cloud)
open3d()
## null 
##    1
surface3d(coords[[1]], coords[[2]], coords[[3]], color = colours, alpha = 0.5)
rglwidget()