R:计算两个地理点之间的距离

nc1teljy  于 2023-04-03  发布在  其他
关注(0)|答案(1)|浏览(177)

bounty将在13小时后到期。回答此问题可获得+50声望奖励。stats_noob正在寻找来自信誉良好的来源的答案

我有兴趣学习如何在R中使用道路网络文件。
例如,我会有兴趣找出以下两个(加拿大)地址之间的驾驶距离:

  • 加拿大国家电视塔:290 Bremner Blvd,多伦多,ON M5 V 3L 9
  • 多伦多机场:100 Dunlop Crt,Toronto,ON L5P 1B2

在过去,我会使用像OpenStreetMap(OSM)这样的API:

library(tmap)

library(tmaptools)
remotes::install_github("riatelab/osrm")

q1 = geocode_OSM("6301 Silver Dart Dr, Mississauga, ON L5P 1B2")
q2 = geocode_OSM("290 Bremner Blvd, Toronto, ON M5V 3L9")

q1 = as.numeric(q1$coords)
q2 = as.numeric(q2$coords)

q1_lat = q1[1]
q1_long = q1[2]
q2_lat = q2[1]
q2_long = q2[2]

route = osrmRoute(src = c(q1[1], q1[2]) ,  dst = c(q2[1], q2[2]), osrm.profile = "car")

> route$distance
[1] 26.2836

正如我们在这里可以看到,这两点之间的驾驶距离是26.2公里(这是相当接近的距离从谷歌Map获得)

**我的问题:**我现在想尝试使用道路网络文件做类似的事情。

例如,我发现了以下文件,其中包含有关道路网络的信息(https://www12.statcan.gc.ca/census-recensement/2021/geo/sip-pis/rnf-frr/index2021-eng.cfm?Year=21)。然后我将其以.shp格式(即shapefile)下载到我的电脑上。

根据这样一份道路网络文件,是否可以找出任何两个地址之间的“行车距离”(无论是“语言地址”还是地理坐标)?

谢谢!

**注意:**此文件似乎很大,我不确定我的计算机是否可以完全加载它-是否可以命令计算机仅导入此文件的一小部分?(例如,import where province =安大略,import where city =多伦多)

4ioopgfo

4ioopgfo1#

是的,您可以下载Map并根据这些文件中有关道路网络的信息计算距离。您已经在使用osrm R包。这将向远程演示服务器发送请求,该服务器将执行此操作。但是,包docs状态,
OSRM演示服务器不允许大型查询(超过10000个距离或持续时间)。
相反,你可以安装osrm-backend,一个用C++编写的高性能路由引擎。这将允许你根据你提供的Map设置自己的路由服务器。然后你可以从R中向你的本地服务器发出如上所述的请求,没有速率限制。

安装osrm-backend并构建map

你可能是对的,你将无法轻松地在标准PC上构建整个加拿大Map。如果你设置你的交换文件,你可能可以,但它可能需要很长时间(小时到天)。我用了一个较小的Map,由geofabrik托管的Ontario Open Street Map数据。你可以下载其他地区here
最简单的方法是使用OSRM docker image。一旦安装了docker,以下内容将下载安大略数据和Docker映像,并启动服务器。以下内容将在终端中输入,而不是R。这应该适用于Windows(在PowerShell中),Mac或Linux。

# Download the map - may take about 15 mins - from https://download.geofabrik.de/north-america/canada/ontario.html
wget -O ontario-latest.osm.pbf https://download.geofabrik.de/north-america/canada/ontario-latest.osm.pbf

# May take 5-10 mins to download the Docker image the first time
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-extract -p /opt/car.lua /data/ontario-latest.osm.pbf || "osrm-extract failed"
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-partition /data/ontario-latest.osm.pbf || "osrm-partition failed"
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-customize /data/ontario-latest.osm.pbf || "osrm-customize failed"

# Run the image
docker run -t -i -p 5000:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/ontario-latest.osrm

这将在端口5000上启动路由引擎HTTP服务器。您应该看到类似于以下内容的输出:

[2023-03-27T18:04:02.703986704] [info] starting up engines, v5.27.1
[2023-03-27T18:04:02.704179704] [info] Threads: 8
[2023-03-27T18:04:02.704216504] [info] IP address: 0.0.0.0
[2023-03-27T18:04:02.704250504] [info] IP port: 5000
[2023-03-27T18:04:07.973464309] [info] http 1.1 compression handled by zlib version 1.2.11
[2023-03-27T18:04:07.973828509] [info] Listening on: 0.0.0.0:5000
[2023-03-27T18:04:07.973957909] [info] running and waiting for requests

然后您可以从R中查询此内容。

从R查询服务器

重要的是将osrm.server设置为本地主机:

library(osrm)
options("osrm.server" = "http://127.0.0.1:5000/")
options("osrm.profile" = "car") # Easiest to set this here as well

使用您问题中的示例坐标,我们可以做到:

osrmRoute(src = src, dst = dst)
# Simple feature collection with 1 feature and 4 fields
# Geometry type: LINESTRING
# Dimension:     XY
# Bounding box:  xmin: -79.6122 ymin: 43.61352 xmax: -79.38643 ymax: 43.68883
# Geodetic CRS:  WGS 84
#     src dst duration distance                       geometry
# 1_1   1   1 23.25667  26.2836 LINESTRING (-79.61214 43.68...

对于多个坐标,也可以使用osrmTable()

osrmTable(src = src, dst = dst)
# $durations
#      1
# 1 23.3

# $sources
#         lon      lat
# 1 -79.61214 43.68332

# $destinations
#         lon      lat
# 1 -79.38643 43.64182

一旦你停止了osrm服务器Docker容器,你只需要最后一行就可以再次运行它,即

docker run -t -i -p 5000:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/ontario-latest.osrm

如果你有大量的坐标对,你可能会遇到max-table-size参数。你可以通过将它作为一个参数传递给docker run来增加它,例如:

docker run -t -i -p 5000:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld --max-table-size 100000 /data/ontario-latest.osrm

您的问题的第二部分是关于将地址反向地理编码为lat/lon的。这是一个完全不同的问题,我不打算在这里回答它。然而,好消息是有一个docker image用于Nominatim,这就是tmaptools::geocode_OSM()在引擎盖下查询的内容(同样有速率限制)。你可以用类似的方式安装它-如果你有麻烦,问另一个问题。

相关问题