我想计算从5弧分分钟分辨率的全局栅格中的所有像素到赤道的距离。结果距离应以米为单位,并考虑到地球的曲率,并且不应因地图投影而失真。
在小区域(例如单个国家)上的应用程序通常通过选择非常适合给定区域的EPSG代码来克服地图投影引起的变形的威胁。由于我的应用程序遍及全球,因此此技巧无效。但是,我并不需要一张可以在各个方面充分显示地球的地图。我只需要一个不会扭曲每个像素与赤道最近点之间距离的投影,即一个不会沿子午线扭曲距离的投影。就我而言,PlateCarrée投影("+proj=longlat +datum=WGS84"
)满足此条件。鉴于此信息,我尝试了以下代码:
r_res <- 1/12
r <- raster(resolution = c(r_res, r_res), crs = "+proj=longlat +datum=WGS84")
p <- as(r, "SpatialPoints")
equator <- st_sfc(st_point(c(-180,0)), st_point(c(0,0)), st_point(c(180,0))) %>% st_combine() %>% st_cast(., "LINESTRING") %>% st_sf(., crs = 4326) %>% st_transform(crs = "+proj=longlat +datum=WGS84") %>% as(., "Spatial")
d <- gDistance(p, equator, byid = T)
dmin <- apply(d, 2, min)
r[] <- dmin
不幸的是,在此示例中计算的距离是以度表示的,而不是以米表示的,这是由投影的longlat
格式引起的。此外,我找不到关于rgeos::gDistance()
是否考虑了行星曲率的任何信息。根据相关文章,gDistance()
甚至不应该应用于longlat
数据。
或者,我将网格投影到另一个以米为单位的投影(Mollweide)中:
r_res <- 1/12
r <- raster(resolution = c(r_res, r_res), crs = "+proj=longlat +datum=WGS84")
r <- projectRaster(r, crs="+proj=moll +ellps=WGS84")
p <- as(r, "SpatialPoints")
equator <- st_sfc(st_point(c(-180,0)), st_point(c(0,0)), st_point(c(180,0))) %>% st_combine() %>% st_cast(., "LINESTRING") %>% st_sf(., crs = 4326) %>% st_transform(crs="+proj=moll +ellps=WGS84") %>% as(., "Spatial")
d <- gDistance(p, equator, byid = T)
dmin <- apply(d, 2, min)
r[] <- dmin
但是,在这种情况下,我不确定gDistance()
是否校正了Mollweide投影所隐含的距离失真。
我知道可以使用经验法则latitude * 111 km
计算距赤道的距离。但是,对于我需要更高精度功能的应用程序来说,这种近似值太不精确了。
如果有人可以提供一些建议,那将是很棒的。随意依赖gDistance()
以外的距离函数。只要距离不失真,以米为单位,并且考虑到地球的曲率,我对任何函数都可以,例如sf
,gdistance
,raster
,{ {1}},geosphere
或任何其他软件包。
答案 0 :(得分:2)
这是一种方法(对于很大的栅格来说,这不是内存安全的)
library(raster)
r_res <- 1/12
r <- raster(resolution = c(r_res, r_res), crs = "+proj=longlat +datum=WGS84")
# latitudes for one column
lats <- cbind(0, yFromRow(r, 1:nrow(r)))
#distances (in km) for one column
dist <- pointDistance(lats, cbind(0,0), lonlat=TRUE) / 1000
# assign to all cells
d <- setValues(r, rep(dist, each=ncol(r)))
这会将“拇指法则”设置为mean(dist/abs(lats[,2]))
= 110.8032 km /纬度
这是一种内存安全(但效率低下)的方法:
x <- init(r, "y")
f <- function(i) { pointDistance(cbind(0, i), cbind(0,0), lonlat=TRUE) / 1000}
z <- calc(x, fun=f)