tmap中含栅格地图仅部分渲染,南部区域被截断求助
解决tmap绘制栅格地图南部截断的问题
我使用tmap绘制含栅格的地图时,南部区域被截断。推测可能和内存限制、投影转换或边界框(bbox)有关,但同CRS的其他栅格在项目中可正常工作,对栅格下采样后问题仍未解决。
地图截断效果:
栅格参数
class : RasterLayer dimensions : 2000, 1441, 2882000 (nrow, ncol, ncell) resolution : 0.0343, 0.0179 (x, y) extent : 19.64043, 69.06673, 41.19558, 76.99558 (xmin, xmax, ymin, ymax) crs : +proj=longlat +datum=WGS84 +no_defs source : copernicus_2000.tif names : copernicus_2000 values : 20, 200 (min, max)
原代码
library(tmap) library(tmaptools) library(sf) library(raster) library(maps) raster.file <- tempfile() download.file("https://github.com/andliszmmu/storage/raw/main/copernicus_2000.tif", raster.file, mode="wb") ocean.pal <- '#afdff9' prj <- CRS("+proj=eqdc +lat_0=57 +lon_0=46.8 +lat_1=69.4367 +lat_2=51.3043 +x_0=0 +y_0=0 +ellps=sphere +units=m +no_defs") map_bbox <- st_bbox(c(xmin = -1700000, ymin = -1780000, xmax = 1040000, ymax = 2330000), crs = prj) land <- st_as_sf(maps::map("world", plot = FALSE, fill = TRUE)) land <- land[land$ID=='Russia',] land <- st_transform(land, prj) model <- raster(paste0(raster.file)) tm = tm_shape(land, bbox = map_bbox) + tm_fill(col = ocean.pal) + tm_shape(model)+ tm_raster(style='fixed', breaks = c(0, 35,45,55,67,75,85,95,112, 200), palette=c('lightgreen', 'yellow', 'red', 'grey', 'white', 'blue', '#f21deb', 'darkgreen', 'green'), labels=c("a","b","c","d","e","f","g","h","i"), alpha = 1, #n=5, stretch.palette = FALSE, title = 'Landscape classification', legend.show = TRUE, legend.reverse = TRUE, legend.z=0) + tm_layout(frame = T, frame.lwd = 2, inner.margins = c(0,0,0,0), outer.margins = c(0.07, 0.127, 0.07, 0.112), asp = 39/56, legend.frame = T, legend.format = list(text.separator = "–"), legend.frame.lwd = 1, legend.outside = F, legend.position = c(0.001, 0.999), legend.just = c("left", "top"), legend.width = -0.32, legend.height = 0.9, legend.text.size = 0.7, legend.title.size = 1.1, legend.bg.color = "white", title.size = 0.7, title.bg.color = 'white', title.position = c('left', 'bottom')) + tmap_options(check.and.fix = TRUE, max.raster = c(plot = 1e8, view = 1e8)) tm
问题根源
核心问题在于栅格未提前转换为目标投影,且未匹配地图的边界框范围。tmap动态投影栅格时,无法正确计算投影后的完整范围,加上仅对land图层设置了bbox,导致栅格渲染范围和地图边界不匹配,出现南部截断。
修复方案
- 提前将栅格转换为目标投影,避免tmap动态投影的不确定性,手动控制投影过程。
- 将转换后的栅格裁剪到
map_bbox指定的范围,确保栅格与地图边界完全对齐。 - 保持
bbox在第一个tm_shape图层的设置,确保所有后续图层都遵循该范围约束。
修改后的代码
library(tmap) library(tmaptools) library(sf) library(raster) library(maps) raster.file <- tempfile() download.file("https://github.com/andliszmmu/storage/raw/main/copernicus_2000.tif", raster.file, mode="wb") ocean.pal <- '#afdff9' prj <- CRS("+proj=eqdc +lat_0=57 +lon_0=46.8 +lat_1=69.4367 +lat_2=51.3043 +x_0=0 +y_0=0 +ellps=sphere +units=m +no_defs") map_bbox <- st_bbox(c(xmin = -1700000, ymin = -1780000, xmax = 1040000, ymax = 2330000), crs = prj) # 处理陆地图层 land <- st_as_sf(maps::map("world", plot = FALSE, fill = TRUE)) land <- land[land$ID=='Russia',] land <- st_transform(land, prj) # 处理栅格:先投影,再裁剪到map_bbox范围 model <- raster(raster.file) # 投影栅格到目标CRS,设置5000米分辨率(可根据需求调整) model_proj <- projectRaster(model, crs = prj, res = 5000) # 将bbox转换为sf多边形,用于裁剪栅格 bbox_poly <- st_as_sfc(map_bbox) # 裁剪栅格到边界框范围 model_cropped <- crop(model_proj, bbox_poly) # 绘制地图 tm <- tm_shape(land, bbox = map_bbox) + tm_fill(col = ocean.pal) + tm_shape(model_cropped)+ tm_raster(style='fixed', breaks = c(0, 35,45,55,67,75,85,95,112, 200), palette=c('lightgreen', 'yellow', 'red', 'grey', 'white', 'blue', '#f21deb', 'darkgreen', 'green'), labels=c("a","b","c","d","e","f","g","h","i"), alpha = 1, stretch.palette = FALSE, title = 'Landscape classification', legend.show = TRUE, legend.reverse = TRUE, legend.z=0) + tm_layout(frame = T, frame.lwd = 2, inner.margins = c(0,0,0,0), outer.margins = c(0.07, 0.127, 0.07, 0.112), asp = 39/56, legend.frame = T, legend.format = list(text.separator = "–"), legend.frame.lwd = 1, legend.outside = F, legend.position = c(0.001, 0.999), legend.just = c("left", "top"), legend.width = -0.32, legend.height = 0.9, legend.text.size = 0.7, legend.title.size = 1.1, legend.bg.color = "white", title.size = 0.7, title.bg.color = 'white', title.position = c('left', 'bottom')) + tmap_options(check.and.fix = TRUE, max.raster = c(plot = 1e8, view = 1e8)) tm
额外说明
- 投影栅格时设置的
res=5000可根据需求调整:数值越大分辨率越低,内存占用越小;反之精度更高但更耗资源。 - 提前裁剪栅格不仅能解决截断问题,还能减少渲染时的内存占用,提升绘制速度。
- 若仍有内存问题,可进一步降低栅格分辨率,或使用
raster::aggregate()对栅格进行聚合降采样。
内容的提问来源于stack exchange,提问作者Andrey Lissovsky
相关产品推荐
相关产品推荐

