在英国计算点与海岸线之间的最小距离。

4

我一直在按照这个例子计算英国的最小距离。因此,我使用EPSG:27700作为英国的坐标参考系统,它具有以下投影字符串:

"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs"

然而,我不确定应该遵循哪个wgs.84代码。目前我正在使用:

"+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

我也尝试使用了datum=OSGB36和+ellps=airy。

完整的代码如下:

library(rgeos)
library(maptools)
library(rgdal)

epsg.27700 <- '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000    +ellps=airy +datum=OSGB36 +units=m +no_defs'
wgs.84    <- '+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0'

coast <- readShapeLines("ne_10m_coastline",CRS(wgs.84)) #have tried other shapefiles with the same issue
MAD   <- readWKT("POINT(-0.1830372 51.1197467)",p4s=CRS(wgs.84)) #Crawley, West Sussex
gDistance(MAD,coast)

[1] 0.28958
Warning messages:
1: In RGEOSDistanceFunc(spgeom1, spgeom2, byid, "rgeos_distance") :
  Spatial object 1 is not projected; GEOS expects planar coordinates
2: In RGEOSDistanceFunc(spgeom1, spgeom2, byid, "rgeos_distance") :
  Spatial object 2 is not projected; GEOS expects planar coordinates
3: In RGEOSDistanceFunc(spgeom1, spgeom2, byid, "rgeos_distance") :
  spgeom1 and spgeom2 have different proj4 strings

尝试完成投影线时出现错误提示。
coast.proj <- spTransform(coast,CRS(Epsg.27700))

non finite transformation detected:
 [1] 111.01051  19.68378       Inf       Inf
Error in .spTransform_Line(input[[i]], to_args = to_args, from_args = from_args,  : 
 failure in Lines 22 Line 1 points 1
In addition: Warning message:
In .spTransform_Line(input[[i]], to_args = to_args, from_args = from_args,  :
 671 projected point(s) not finite

我在这里做错了什么,我有些困惑。
1个回答

5
据我所知,您没有做错任何事情。错误消息告诉您,全球海岸线形状文件中的一些坐标映射到 Inf。我不确定具体原因,但通常期望在特定区域使用平面投影在全球范围内工作并不是一个好主意(尽管在其他问题中确实有效...)。一种解决方法是将海岸线形状文件剪切到特定投影的边界框,然后转换剪切的形状文件。EPSG.27700 的边界框可以在此处找到:这里
# use bounding box for epsg.27700
# found here: http://spatialreference.org/ref/epsg/osgb-1936-british-national-grid/
bbx <- readWKT("POLYGON((-7.5600 49.9600, 1.7800 49.9600, 1.7800 60.8400, -7.5600 60.8400, -7.5600 49.9600))",
               p4s=CRS(wgs.84)) 
coast <- gIntersection(coast,bbx)  # just coastlines within bbx
# now transformation works
coast.proj   <- spTransform(coast,CRS(epsg.27700))
MAD.proj     <- spTransform(MAD,CRS(epsg.27700))
dist.27700   <- gDistance(MAD.proj,coast.proj)   # distance in sq.meters
dist.27700
# [1] 32153.23

所以最近的海岸线距离这里有32.2公里。我们还可以确定这是海岸线的哪个位置。

# identify the closest point
th     <- seq(0,2*pi,len=1000)
circle <- cbind(1.00001*dist.wgs84*cos(th)+MAD$x,1.00001*dist.wgs84*sin(th)+MAD$y)
sp.circle <- SpatialLines(list(Lines(list(Line(circle)),ID="1")),proj4string=CRS(wgs.84))
sp.pts <- gIntersection(sp.circle,coast)
sp.pts
# SpatialPoints:
#            x        y
# 1 -0.2019854 50.83079
# 1 -0.1997009 50.83064
# Coordinate Reference System (CRS) arguments: +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 

最后我们可以绘制结果。您应该始终这样做。

# plot the results: plot is in CRS(wgs.84)
plot(coast, asp=1)
plot(bbx,add=T)
plot(MAD,add=T, col="red", pch=20)
plot(sp.circle,add=T, col="blue", lty=2)
lines(c(MAD$x,sp.pts$x),c(MAD$y,sp.pts$y),col="red")


这只是一个跟进问题,是否可以将MAD、MAD.proj和dist.27700放在循环中,因为我有大约40万个位置需要检查到海岸的距离,或者有其他的想法吗? - MikeM
我倾向于将所有点放入单个spatialPoints对象中(为方便起见,我们再次称之为MAD),然后将其转换为MAD.proj,然后执行以下操作:sapply(1:length(MAD.proj),function(i)gDistance(MAD.proj[i],coast.proj))。这将生成一个距离向量,表示每个点到最近海岸的距离。 - jlhoward
谢谢您的建议。我在尝试将所有点放入单个spatialPoints对象的概念上遇到了困难。我尝试使用MULTIPOINT,但这似乎只能接受约200个点。我还尝试将数据带入数据框,并在该数据框上使用coordinates函数,但是以下操作失败了 MAD.proj <- spTransform(points,CRS(epsg.27700)),显示无法从NA参考系统进行转换。不确定我错过了什么? - MikeM
这是因为spTransform(sp,...)将投影从一个转换到另一个。它必须知道起始CRS,这意味着sp必须有一个定义的CRS。如果您的点在名为df的矩阵或数据框中,请尝试使用以下代码:MAD <- SpatialPoints(df,proj4string=CRS(wgs.84))。然后spTransform(...)应该可以工作了。 - jlhoward

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接