设置CRS以使用雄蕊贴图进行打印

a7qyws3x  于 2022-12-20  发布在  其他
关注(0)|答案(2)|浏览(121)

我试图在Map上绘制一个简单的多边形来表示我感兴趣的区域。到目前为止,我已将多边形定义为,并且能够独立地绘制它。

poly <- st_polygon(list(as.matrix(data.frame(lat = c(40, 40, 60, 60, 40),
                                             lon = c(-60, -40, -40, -60, -60))))) #EDIT: these are lat/lon coordinates
ggplot() + 
    geom_sf(data = poly,
    aes(geometry = geometry),
    col = "red)

但是,我需要添加一个底图,以便显示此多边形相对于其他空间元素的位置。

# Attempt #1: stamenmaps basemap

    grid_box <- c(left   = -70, 
                  right  = -30,
                  bottom = 35,
                  top    = 70)
    base <- get_stamenmap(grid_box, zoom = 6, maptype = "terrain-background", color = "color")
    ggmap(base) +
      geom_sf(data = poly, 
              aes(geometry = geometry),
              col = "red")

    Coordinate system already present. Adding new coordinate system, which will replace the existing one.
    Error in `geom_sf()`:
    ! Problem while computing aesthetics.
    ℹ Error occurred in the 4th layer.
    Caused by error in `FUN()`:
    ! object 'lon' not found
    Run `rlang::last_error()` to see where the error occurred.

我找到的唯一一种向多边形添加crs的方法如下(st_transform & st_as_sf不起作用),但这极大地改变了坐标的比例,仍然无法绘制。

# Attempt #2: new CRS

    poly <- st_polygon(list(as.matrix(data.frame(lon = c(-62, -43, -43, -62, -62),
                                                     lat = c(43, 43, 70, 70, 43))))) %>%
            st_sfc(crs = 3857)
    ggmap(base) +
      geom_sf(data = poly, 
              aes(geometry = geometry),
              col = "red")

Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Error in `geom_sf()`:
! Problem while computing aesthetics.
ℹ Error occurred in the 4th layer.
Caused by error in `FUN()`:
! object 'lon' not found
Run `rlang::last_error()` to see where the error occurred.

How can I get this polygon to plot over my basemaps?
acruukt9

acruukt91#

我相信你在第二次尝试sf::st_sfc()调用时是正确的。要使它工作,你必须想一想你的坐标意味着什么?
EPSG:3857中,坐标是以米为单位定义的,而最初名为lat & long的列似乎不是这样,lat & long通常以度为单位表示纬度和经度。
如果你的坐标是以度为单位的(这似乎是可能的,尽管我在你的问题中没有找到明确的说明),你会更好地使用EPSG:4326。
您必须解决的一个问题是,ggmap标记为EPSG:4326(未投影的度),但实际绘制为EPSG:3857(以墨卡托投影的米),此处描述了一种可能的方法How to put a geom_sf produced map on top of a ggmap produced raster
在此问题的基础上,我提出以下建议:

library(sf)
library(ggmap)

poly <- st_polygon(list(as.matrix(data.frame(lon = c(-62, -43, -43, -62, -62),
                                             lat = c(43, 43, 70, 70, 43))))) %>%
  st_sfc(crs = 4326) 

grid_box <- c(left   = -70, 
              right  = -30,
              bottom = 35,
              top    = 70)

base <- get_stamenmap(grid_box, zoom = 5, 
                      maptype = "terrain-background", 
                      color = "color")

ggmap_bbox <- function(map) {
  if (!inherits(map, "ggmap")) stop("map must be a ggmap object")
  # Extract the bounding box (in lat/lon) from the ggmap to a numeric vector, 
  # and set the names to what sf::st_bbox expects:
  map_bbox <- setNames(unlist(attr(map, "bb")), 
                       c("ymin", "xmin", "ymax", "xmax"))
  
  # Coonvert the bbox to an sf polygon, transform it to 3857, 
  # and convert back to a bbox (convoluted, but it works)
  bbox_3857 <- st_bbox(st_transform(st_as_sfc(st_bbox(map_bbox, crs = 4326)), 3857))
  
  # Overwrite the bbox of the ggmap object with the transformed coordinates 
  attr(map, "bb")$ll.lat <- bbox_3857["ymin"]
  attr(map, "bb")$ll.lon <- bbox_3857["xmin"]
  attr(map, "bb")$ur.lat <- bbox_3857["ymax"]
  attr(map, "bb")$ur.lon <- bbox_3857["xmax"]
  map
}

# Use the function:
base <- ggmap_bbox(base)

ggmap(base) +
  coord_sf(crs = st_crs(3857)) +
  geom_sf(data = st_transform(poly, 3857), 
          col = "red", fill = NA,
          inherit.aes = F) +
  theme(axis.title = element_blank())

b09cbbtk

b09cbbtk2#

虽然已经回答过了,但我想分享另一种解决这个问题的方法。您可以使用maptiles轻松地提取瓦片,并使用tidyterra无缝地绘制瓦片。唯一需要记住的是,瓦片通常在EPSG:3857中提供,因此您可能需要在该投影上获取并绘制瓦片,以便显示完整的细节。否则,光栅的投影(涉及重采样)将在最终图像上创建一些变形。
参见:

library(sf)
#> Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE
library(maptiles)
library(ggplot2)
library(tidyterra)
#> 
#> Attaching package: 'tidyterra'
#> The following object is masked from 'package:stats':
#> 
#>     filter

poly <- st_polygon(list(as.matrix(data.frame(
  lon = c(-62, -43, -43, -62, -62),
  lat = c(43, 43, 70, 70, 43)
)))) %>%
  st_sfc(crs = 4326) 

# Grid to polygon 

grid_box <- c(-70, 35, -30, 70)
class(grid_box) <- "bbox"
grid_poly <- st_as_sfc(grid_box) %>% st_set_crs(4326) %>%
  st_transform(3857)
 

basemap <- get_tiles(grid_poly, provider = "Stamen.Terrain", crop = TRUE)

ggplot() +
  geom_spatraster_rgb(data = basemap) +
  geom_sf(data = poly, fill = NA, color = "red") +
  coord_sf(crs=3857, expand = FALSE)

创建于2022年12月10日,使用reprex v2.0.2

相关问题