如何在rayshader中自定义比例尺颜色以匹配地图调色板?
问题:为rayshader的
render_scalebar()应用完整颜色渐变 我正在用R语言的rayshader包制作伦敦地表温度(LST)的3D地图,地图采用RdYlBu发散型调色板:c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026"),但render_scalebar()函数仅接受color_first和color_second两个颜色参数,生成的双色交替比例尺无法匹配地图的调色板。
当前代码如下:
pacman::p_load(terra, rayshader) # 1. Load the raster lst_rast <- rast( nrows = 562, ncols = 729, resolution = c(80, 80), extent = ext(503580, 561900, 155920, 200880), crs = "EPSG:27700" ) values(lst_rast) <- runif(562 * 729, min = 17, max = 30) names(lst_rast) <- "london_study_area" # 2. Convert to matrix lst_matrix <- raster_to_matrix(raster::raster(lst_rast)) range(lst_matrix, na.rm = TRUE) # 3. Build shading texture lst_matrix |> height_shade(texture = grDevices::colorRampPalette( c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026") )(256)) |> plot_3d( lst_matrix, zscale = 0.2, theta = 30, phi = 45, zoom = 0.75, windowsize = c(1200, 800), background = "white", solid = FALSE ) render_camera(fov = 0, theta = 60, zoom = 0.75, phi = 45) render_scalebar( limits = c(0, 5, 10), label_unit = "km", position = "W", scale_length = c(0.33, 1) ) render_compass(position = "NE") render_snapshot(clear = TRUE)
请问是否有方法为render_scalebar()应用完整的颜色渐变?
解决方案
由于render_scalebar()本身不支持多色渐变,可通过以下两种方法实现匹配调色板的比例尺:
方法1:在渲染后的图片上叠加自定义渐变比例尺
先保存3D地图快照,再用magick和ggplot2添加自定义渐变比例尺:
pacman::p_load(terra, rayshader, magick, ggplot2) # 生成并保存无默认比例尺的3D地图 lst_matrix |> height_shade(texture = grDevices::colorRampPalette( c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026") )(256)) |> plot_3d( lst_matrix, zscale = 0.2, theta = 30, phi = 45, zoom = 0.75, windowsize = c(1200, 800), background = "white", solid = FALSE ) render_camera(fov = 0, theta = 60, zoom = 0.75, phi = 45) render_compass(position = "NE") render_snapshot(filename = "lst_3d_map.png", clear = TRUE) # 创建渐变比例尺图片 pal <- grDevices::colorRampPalette(c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026"))(256) scale_plot <- ggplot() + geom_tile(aes(x = 1, y = seq_along(pal), fill = seq_along(pal))) + scale_fill_gradientn(colors = pal) + scale_y_continuous(limits = c(1,256), breaks = c(1,128,256), labels = c(min(lst_matrix), round(mean(lst_matrix),1), max(lst_matrix))) + theme_void() + theme(plot.background = element_rect(fill = "white")) ggsave("scale_bar.png", scale_plot, width = 0.5, height = 4, dpi = 300) # 合并地图与比例尺 map_img <- image_read("lst_3d_map.png") scale_img <- image_read("scale_bar.png") final_img <- image_composite(map_img, scale_img, offset = "+50+200") # 调整offset控制比例尺位置 image_write(final_img, "lst_3d_map_with_scale.png")
方法2:在3D场景中添加自定义渐变平面
利用add_3d_object()添加带渐变纹理的平面模拟比例尺,再用render_label()添加数值标签:
pacman::p_load(terra, rayshader) # 生成3D场景 lst_matrix |> height_shade(texture = grDevices::colorRampPalette( c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026") )(256)) |> plot_3d( lst_matrix, zscale = 0.2, theta = 30, phi = 45, zoom = 0.75, windowsize = c(1200, 800), background = "white", solid = FALSE ) render_camera(fov = 0, theta = 60, zoom = 0.75, phi = 45) # 创建渐变纹理 pal <- grDevices::colorRampPalette(c("#313695", "#74add1", "#ffffbf", "#f46d43", "#a50026"))(256) grad_texture <- matrix(rev(pal), nrow = 256, ncol = 1) # 添加渐变平面作为比例尺(调整x/y/z和scale适配场景) add_3d_object( obj = cube3d(), x = 0, y = ncol(lst_matrix) + 50, z = min(lst_matrix), scale = c(10, 1, max(lst_matrix) - min(lst_matrix)), texture = grad_texture, lit = FALSE ) # 添加比例尺数值标签 render_label( x = 0, y = ncol(lst_matrix) + 60, z = min(lst_matrix), text = round(min(lst_matrix),1), textsize = 2, clear_previous = FALSE ) render_label( x = 0, y = ncol(lst_matrix) + 60, z = mean(lst_matrix), text = round(mean(lst_matrix),1), textsize = 2, clear_previous = FALSE ) render_label( x = 0, y = ncol(lst_matrix) + 60, z = max(lst_matrix), text = round(max(lst_matrix),1), textsize = 2, clear_previous = FALSE ) render_compass(position = "NE") render_snapshot(clear = TRUE)
内容的提问来源于stack exchange,提问作者Nikos
相关产品推荐
相关产品推荐

