-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from BalintKomjati/master
Added 3D elevation plot - Fixes #47
- Loading branch information
Showing
6 changed files
with
229 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,11 @@ Authors@R: | |
person(given = "Megan", | ||
family = "Beckett", | ||
role = c("ctb"), | ||
email = "[email protected]")) | ||
email = "[email protected]"), | ||
person(given = "Bálint", | ||
family = "Komjáti", | ||
role = c("ctb"), | ||
email = "[email protected]")) | ||
Description: Creates artistic visualisations with Strava data. | ||
Depends: | ||
R (>= 3.4.3), | ||
|
@@ -34,7 +38,12 @@ Imports: | |
packcircles, | ||
ggforce, | ||
tidyr, | ||
viridis | ||
viridis, | ||
rayshader, | ||
geoviz, | ||
magick, | ||
raster, | ||
terra | ||
License: MIT + file LICENSE | ||
Encoding: UTF-8 | ||
LazyData: true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
#' Create 3D interactive elevation map from gpx tracklogs | ||
#' | ||
#' @param tracklog_file A path to a gpx file to be read by strava::process_data. | ||
#' If the file covers a big area plot_3D() can slow down significantly. | ||
#' @param cache_folder Directory to store the downloaded elevation data and overlay image for reuse | ||
#' @param elevation_scale Horizontal vs vertical ratio of the plot. Could be estimated with geoviz::raster_zscale(dem). | ||
#' @param elevation_scale_tracklog_corr Raises elevation_scale for the tracklog by the specified percentage. | ||
#' Useful if tracklog occasionally disappears into the ground. | ||
#' @param buffer_around_tracklog_km Buffer distance around the tracklog in km. Scene is cut outside this. | ||
#' @param render_high_quality If set to TRUE the function downloads higher resolution elevation and overlay data. | ||
#' All steps are very time and resource consuming. | ||
#' @param sunangle The direction of the light source of the scene | ||
#' @param sunaltitude The angle, in degrees (as measured from the horizon) from which the light originates. | ||
#' @param color_tracklog Color of the tracklog on the scene. | ||
#' @param color_background Color of the scene's background. | ||
#' @param water_detect If set to TRUE rayshader will look for flat surfaces in the scene and render them in blue | ||
#' | ||
#' @export | ||
#' @import geoviz rayshader magick | ||
#' @importFrom raster raster writeRaster extract extent | ||
#' | ||
#' @examples | ||
#' \dontrun{ | ||
#' # Generate a built in demo by simply running | ||
#' strava::plot_3D() | ||
#' } | ||
plot_3D <- function( | ||
tracklog_file = "gpx/mtb", | ||
cache_folder = "~/cache_plot_3D", | ||
elevation_scale = 6, # | ||
elevation_scale_tracklog_corr = .01, | ||
buffer_around_tracklog_km = 1, | ||
render_high_quality = FALSE, | ||
sunangle = 250, | ||
sunaltitude = 75, | ||
color_tracklog = 'blue', | ||
color_background = 'lightskyblue1', | ||
water_detect = FALSE | ||
) { | ||
|
||
if (!file.exists(cache_folder)) dir.create(cache_folder) | ||
dem_file <- paste0(cache_folder, "/dem" ,if(render_high_quality) "_hq") | ||
overlay_file <- paste0(cache_folder, "/overlay_image",if(render_high_quality) "_hq", ".rds") | ||
|
||
|
||
message("Reading the tracklog") | ||
tracklog <- strava::process_data(system.file(tracklog_file, package = "strava")) | ||
|
||
|
||
if( paste0(dem_file,".gri") %>% file.exists() ) { | ||
|
||
message("Loading Digital Elevation Model (DEM) from disk") | ||
dem <- raster::raster(dem_file) | ||
|
||
} else { | ||
|
||
message("Downloading Digital Elevation Model (DEM)") | ||
dem <- geoviz::mapzen_dem(lat = tracklog$lat, | ||
long = tracklog$lon, | ||
max_tiles = if(render_high_quality) 100 else 10) | ||
|
||
# Downloaded DEM tiles cover a larger area so we crop them to fit the tracklog | ||
message("Cropping DEM") | ||
dem <- geoviz::crop_raster_track(dem, | ||
lat = tracklog$lat, | ||
long = tracklog$lon, | ||
width_buffer = buffer_around_tracklog_km) | ||
|
||
message("Saving DEM to disk") | ||
raster::writeRaster(x = dem, filename = dem_file, overwrite = TRUE) | ||
|
||
} | ||
|
||
|
||
message("Calculating elevation matrix") | ||
elmat <- matrix( | ||
raster::extract(dem, raster::extent(dem), method = 'bilinear'), | ||
nrow = ncol(dem), | ||
ncol = nrow(dem) | ||
) | ||
|
||
|
||
if( overlay_file %>% file.exists() ) { | ||
|
||
message("Loading overlay image from disk") | ||
overlay_image <- readRDS(overlay_file) | ||
|
||
} else { | ||
|
||
message("Downloading overlay image") | ||
overlay_image <- geoviz::slippy_overlay( | ||
dem, | ||
image_source = "stamen", | ||
image_type = "terrain", | ||
max_tiles = if(render_high_quality) 500 else 10, | ||
return_png = T, | ||
png_opacity = 0.5) | ||
saveRDS(overlay_image, overlay_file) | ||
} | ||
|
||
|
||
message("Calculating the scene") | ||
|
||
scene <- elmat %>% | ||
rayshader::sphere_shade(sunangle = sunangle) %>% | ||
{ if (water_detect) rayshader::add_water(rayshader::detect_water(elmat), color = "lightblue") else . } %>% | ||
rayshader::add_shadow(rayshader::ray_shade(elmat, | ||
sunangle = sunangle, | ||
sunaltitude = sunaltitude, | ||
zscale = elevation_scale, | ||
multicore = FALSE), | ||
max_darken = 0.2) %>% | ||
rayshader::add_shadow(rayshader::lamb_shade(elmat,zscale = elevation_scale, sunaltitude = 3), | ||
max_darken = 0.5) %>% | ||
rayshader::add_overlay(overlay_image, alphalayer = .6) | ||
|
||
|
||
message("Plotting the scene") | ||
|
||
rayshader::plot_3d( | ||
scene, | ||
elmat, | ||
zscale = elevation_scale, | ||
#baseshape = 'circle', | ||
zoom = 0.8, | ||
fov = 10, | ||
mouseMode = c("none", "trackball", "zoom", "none", "zoom"), | ||
#windowsize = c(854,480), | ||
shadowcolor = 'grey10', | ||
background = color_background, | ||
triangulate = F | ||
) | ||
|
||
|
||
message("Adding tracklog to the scene") | ||
|
||
geoviz::add_gps_to_rayshader( | ||
dem, | ||
tracklog$lat, | ||
tracklog$lon, | ||
#tracklog$ele, | ||
clamp_to_ground = TRUE, | ||
line_width = 3, | ||
lightsaber = FALSE, | ||
alpha = .9, | ||
colour = color_tracklog, | ||
zscale = elevation_scale/(1+elevation_scale_tracklog_corr) | ||
) | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.