|
| 1 | +library(plotly) |
| 2 | + |
| 3 | +storms <- sf::st_read(system.file("shape/storms_xyz.shp", package = "sf"), quiet = TRUE) |
| 4 | + |
| 5 | +empty_axis <- list( |
| 6 | + showgrid = FALSE, |
| 7 | + zeroline = FALSE, |
| 8 | + showticklabels = FALSE, |
| 9 | + title = "" |
| 10 | +) |
| 11 | + |
| 12 | +# even grid of lat/lons along the whole globe |
| 13 | +nlat <- 200 |
| 14 | +nlon <- 100 |
| 15 | +lat <- seq(-180, 180, length.out = nlat) |
| 16 | +lon <- seq(-90, 90, length.out = nlon) |
| 17 | +lat <- matrix(rep(lat, nlon), nrow = nlat) |
| 18 | +lon <- matrix(rep(lon, each = nlat), nrow = nlat) |
| 19 | + |
| 20 | +# helper function for converting polar -> cartesian |
| 21 | +degrees2radians <- function(degree) degree * pi / 180 |
| 22 | + |
| 23 | +plot_ly() %>% |
| 24 | + add_sf( |
| 25 | + data = sf::st_as_sf(maps::map("world", plot = FALSE, fill = TRUE)), |
| 26 | + x = ~ 1.001 * cos(degrees2radians(x)) * cos(degrees2radians(y)), |
| 27 | + y = ~ 1.001 * sin(degrees2radians(x)) * cos(degrees2radians(y)), |
| 28 | + z = ~ 1.001 * sin(degrees2radians(y)), |
| 29 | + color = I("black"), hoverinfo = "none", size = I(1), |
| 30 | + showlegend = FALSE |
| 31 | + ) %>% |
| 32 | + add_sf( |
| 33 | + data = storms, |
| 34 | + name = "storm paths", |
| 35 | + x = ~ cos(degrees2radians(x)) * cos(degrees2radians(y)), |
| 36 | + y = ~ sin(degrees2radians(x)) * cos(degrees2radians(y)), |
| 37 | + # TODO: this is just a guess, the rescaling range is not actually [0, 0.2]... |
| 38 | + z = ~ sin(degrees2radians(y)) + scales::rescale(z, to = c(0, 0.2)) |
| 39 | + ) %>% |
| 40 | + add_surface( |
| 41 | + x = cos(degrees2radians(lon)) * cos(degrees2radians(lat)), |
| 42 | + y = sin(degrees2radians(lon)) * cos(degrees2radians(lat)), |
| 43 | + z = sin(degrees2radians(lat)), |
| 44 | + # TODO: perhaps there is a better way to specify a constant surfacecolor? |
| 45 | + surfacecolor = matrix(rep(0.5, nlat * nlon), nrow = nlat), |
| 46 | + colorscale = data.frame(c(0, 0.5, 1), c("red", "white", "blue")), |
| 47 | + showscale = FALSE, |
| 48 | + hoverinfo = "none" |
| 49 | + ) %>% |
| 50 | + # TODO: is there a way to turn on the spikelines? |
| 51 | + layout( |
| 52 | + scene = list( |
| 53 | + xaxis = empty_axis, |
| 54 | + yaxis = empty_axis, |
| 55 | + zaxis = empty_axis, |
| 56 | + aspectratio = list(x = 1, y = 1, z = 1), |
| 57 | + camera = list(eye = list(x = .41, y = -.71, z = 0.57)) |
| 58 | + ) |
| 59 | + ) |
| 60 | + |
0 commit comments