为什么mapboxapi返回一个倾斜的地图,其纬度明显不正确并且相对于数据错位?

问题描述 投票:0回答:1

我正在尝试创建几张跨越宽纬度范围的地图。我正在 R 中通过

mapboxapi
使用 Mapbox 地图。我想知道如何正确执行此操作,以便准确放置地图和我放在上面的数据。我需要重新投影吗?

地图上的经度显然相当正确,但直布罗陀海峡应该位于纬度约 36 度处。

basemap <- layer_static_mapbox(location = c(-20,10,20,55),
                               # style_id = "streets-v12",
                               style_url = "mapbox://styles/mapbox/streets-v12",
                               username = "User",
                               access_token = "Token",
                               attribution = T,
                               logo = T)

basemap

当我添加数据时情况会变得更糟(在“EPSG:4326”中): map+data

快速而肮脏的

borders
映射可以准确地定位数据和世界:

ggplot(data, aes(lon, lat)) +
  borders(xlim = c(-10, 10), ylim = c(10, 55)) +
  geom_hline(yintercept = 36, lty = 2, color = "cornflowerblue") +
  geom_point()

fastmap

r mapping mapbox projection
1个回答
0
投票

您的问题源于与

location = 
坐标如何转换有关的问题。来自有关
location
的文档:

虽然输入 sf 对象可以位于任意坐标参考系中,但如果提供长度为 4 的边界框向量,则它必须表示 WGS84 经度/纬度坐标,并且顺序为 c(xmin, ymin, xmax, ymax)

由于某种原因,无法正确解释使用

c(xmin, ymin, xmax, ymax)
选项。我怀疑由于“mapbox”数据的 CRS 是 WGS84 Pseudo-Mercator/EPSG:3857,因此某些内容未正确翻译。可能需要其他设置,但我无法确定如何使该选项发挥作用。

但是,这里有一个可以实现您想要的结果的代表。它涉及使用基于已投影到

mapbox
的 WGS84 Pseudo-Mercator/EPSG:3857 的坐标的 sf 对象。我稍微扩展了坐标以反映您的示例图像。我使用了
static_mapbox()
而不是
layer_static_mapbox()
,但这种方法无论如何都应该有效。

library(mapboxapi)
library(magick)
library(terra)
library(sf)
library(ggplot2)
library(tidyterra)

# Add API key (may be prompted to restart or to run readRenviron("~/.Renviron") )
mapboxapi::mb_access_token("pk.XXXX", install = TRUE, overwrite = TRUE)
readRenviron("~/.Renviron")

# Check API key is correct
Sys.getenv("MAPBOX_PUBLIC_TOKEN")
# "pk.XXXX"

# Create sf coordinates for basemap extent (slightly larger than your example)
# and project to WGS84 Pseudo-Mercator/EPSG:3857
map_ext <- as.polygons(ext(-20, 25, 10, 55), crs = "EPSG:4326") |>
  st_as_sf() |>
  st_transform(3857)

# Create static basemap using map_ext for extent
basemap <- static_mapbox(location = map_ext,
                         buffer_dist = 0,
                         style_url = "mapbox://styles/mapbox/streets-v12",
                         username = "mapbox",
                         attribution = TRUE,
                         logo = TRUE)

# Convert basemap to raw
img_raw <- image_data(basemap, channels = "rgb")

# Convert raw to a raster array
img_array <- as.integer(img_raw)
dim(img_array) <- c(image_info(basemap)$height, image_info(basemap)$width, 3)

# Create a SpatRaster object from array
r_base <- rast(img_array)

# Assign extent and CRS
ext(r_base) <- ext(map_ext)
crs(r_base) <- "EPSG:3857"

# Example point data (if not already, you will need to project your data to "EPSG:3857")
data <- data.frame(lon = seq(-15, 10, 1),
                   lat = seq(15, 50, length.out = 26)) |>
  st_as_sf(coords = c("lon", "lat"), crs = 4326) |>
  st_transform(3857)

ggplot() +
  geom_spatraster_rgb(data = r_base) +
  geom_sf(data = data) +
  coord_sf(expand = FALSE)

1

© www.soinside.com 2019 - 2024. All rights reserved.