0

The terra::shade hill shade algorithm only uses immediate neighbors to compute hill shading. In contrast, Google Earth Engine's ee.Algorithms.HillShadow has a neighborhood size argument, which can lead to very different results. Below is a minimal reproducible example that shows how terra::shade only casts shadows in the immediate vicinity of the "tower" in the middle. Using the same raster, GEE's ee.Algorithms.HillShadow produces very different results (see figure and code).

I am also including plots from a real-world example based on a high-resolution digital surface model. This illustrates the difference in a real-world application of the algorithm.

Question

What are options for a hillshade algorithm in R that take a larger neighborhood size into account similar to GEE's ee.Algorithms.HillShadow?

R Code

library("tidyverse")
library("terra")
library("tidyterra")
library("ggpubr")

# Define raster
set.seed(123423)
dsm_values <- sample(1:3, 1000, replace = TRUE)
m <- matrix(dsm_values, nrow = 100, ncol = 100)
m[40:60,40:60] <- 100
r <- rast(m, crs = "epsg:2263")
names(r) <- "dsm"

# Compute hillshade
terrain <- terra::terrain(r$dsm, c("slope", "aspect"), unit = "radians")
shade <- terra::shade(terrain$slope, terrain$aspect, angle = altitude, direction = azimuth, normalize = TRUE)


g1 <- ggplot() +
    geom_spatraster(data = r, aes(fill = dsm)) +
    scale_fill_gradientn(colors = c('blue', 'limegreen', 'yellow', 'darkorange', 'red')) +
    ggtitle("DSM") +
    theme_bw()

g2 <- ggplot() +
    geom_spatraster(data = shade, aes(fill = hillshade)) +
    scale_fill_gradient2(low = "#ffffff", high = "#000000") +
    ggtitle("shade") +
    theme_bw()

ggarrange(g1, g2)

GEE

// IMPORT raster as `dsm`
var azimuth = 136;
var altitude = 14.6;

/* Shadow ----------------------------------------------- */
var shade = ee.Algorithms.HillShadow(dsm, azimuth, altitude, 300);

/* Mapping shadow  ---------------------------- */
Map.centerObject(dsm, 18);
var params = {min: -5, max: 500, palette: ['blue', 'limegreen', 'yellow', 'darkorange', 'red']};
Map.addLayer(dsm, params, 'DSM', true);
Map.addLayer(shade, {min:0, max: 1, palette: "black, white"}, 'Shadow', true, 0.5);

terra::shade

enter image description here

GEE ee.Algorithms.HillShadow

enter image description here

Real-world example

enter image description here enter image description here enter image description here

0

1 Answer 1

1

The two functions here are essentially very different things. The R hillshade function is a measure of how steep and angled a location is to a light source, and the Google Earth Engine algorithm is computing "realistic" shadows cast by objects. No amount of tweaking the R hillshade algorithm will do shadow-casting.

If you want to do this in R you need to look at true 3d packages, such as maybe rgl or rayshader [https://www.rayshader.com/] or integrate with other systems that can do it - maybe there's a GRASS algorithm that does 3d shadow casting...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.