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

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,导致栅格渲染范围和地图边界不匹配,出现南部截断。

修复方案

  1. 提前将栅格转换为目标投影,避免tmap动态投影的不确定性,手动控制投影过程。
  2. 将转换后的栅格裁剪到map_bbox指定的范围,确保栅格与地图边界完全对齐。
  3. 保持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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 07:24:53