You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 09:52:33