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);