I am trying to get the driving distance between two points with lat/lon given. I can manually put them into google map and get the driving distance but I want to do all this programatically.
I guess JavaScript is the language to go. But, I do not know JavaScript and I am fairly familiar using R. I would prefer to do it in R since I am doing all the data analysis in R.
I am looking for distance along the road not crow-fly distance. After few hours of trying, I wrote the following function in R (This and this one helped). Do you have any better way to get the distance either within this function or anything very very simpler?
library(XML)
latlon2ft <- function(origin,destination)
{
xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false')
xmlfile <- xmlTreeParse(xml.url)
xmltop = xmlRoot(xmlfile)
distance <- xmltop[['row']][[1]][5][1][['distance']][['value']][[1]]
distance <- as.numeric(unclass(distance)[['value']])
ft <- distance*3.28084 # FROM METER TO FEET
return(ft)
}
latlon2ft(origin='37.193489,-121.07395',destination='37.151616,-121.046586')
RESULT = 17224.41
You need RCurl
or an equivalent here.
library(XML)
library(bitops)
library(RCurl)
latlon2ft <- function(origin,destination){
xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false')
xmlfile <- xmlParse(getURL(xml.url))
dist <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value)
distance <- as.numeric(sub(" km","",dist))
ft <- distance*3.28084 # FROM METER TO FEET
return(ft)
}
latlon2ft(origin='37.193489,-121.07395',destination='37.151616,-121.046586')
Result:
[1] 17224.41
I authored the gmapsdistance
package to do just that. It is available on CRAN. You can use the function in the following way:
results = gmapsdistance(origin = "38.1621328+24.0029257",
destination = "37.9908372+23.7383394",
mode = "walking") results
# $Time
# [1] 30025
#
# $Distance
# [1] 39507
#
# $Status
# [1] "OK"
You can also include vectors of origins and destinations, and get the resulting distance matrix. It supports also directions, and has a bunch of options:
results = gmapsdistance(origin = c("Washington+DC", "New+York+NY", "Seattle+WA", "Miami+FL"),
destination = c("Los+Angeles+CA", "Austin+TX", "Chicago+IL", "Philadelphia+PA"),
mode = "bicycling",
departure = 1514742000)
results
# $Time
# or Time.Los+Angeles+CA Time.Austin+TX Time.Chicago+IL Time.Philadelphia+PA
# 1 Washington+DC 856621 535146 247765 54430
# 2 New+York+NY 917486 596011 308630 32215
# 3 Seattle+WA 374692 678959 674989 956702
# 4 Miami+FL 829039 416667 452035 411283
#
# $Distance
# or Distance.Los+Angeles+CA Distance.Austin+TX Distance.Chicago+IL Distance.Philadelphia+PA
# 1 Washington+DC 4567470 2838519 1303067 266508
# 2 New+York+NY 4855086 3126136 1590684 160917
# 3 Seattle+WA 1982354 3562970 3588297 5051951
# 4 Miami+FL 4559205 2279966 2381610 2169382
#
# $Status
# or status.Los+Angeles+CA status.Austin+TX status.Chicago+IL status.Philadelphia+PA
# 1 Washington+DC OK OK OK OK
# 2 New+York+NY OK OK OK OK
# 3 Seattle+WA OK OK OK OK
# 4 Miami+FL OK OK OK OK
I needed to calculate driving distances for a bunch of addresses, so I wrote a short function for it and put it in a likewise small packet. You can find it in my GitHub repo: https://github.com/JanMultmeier/GeoData/blob/master/GeoDataPackage/R/GetDist.R
This should get it to run:
require(devtools)
install_github("JanMultmeier/GeoData/GeoDataPackage")
library(GeoData)
getDist(from="1 Infinity Loop, Cupertino, CA 95014", to="1600 Amphitheatre Pkwy, Mountain View, CA 94043",modus="driving",get="distance")
It should return 14.8 km.
Barryhunter has already hinted at the usage restriction by Google, which ties the use of this API to displaying the results on a Google map.
Hope that still helps some people who stumble across this post (like me)...
I've written the googleway
package to do this using Google Maps API
In particular, the google_directions()
function will give you driving distances, directions, routes, legs, steps etc.
And the google_distance()
function will give you a distance matrix for all the origins/destinations
You need a Google API key to use their API
library(googleway)
## your valid API key
key <- "your_api_key_here"
directions <- google_directions(origin = c(37.193489,-121.07395),
destination = c(37.151616,-121.046586),
key = key,
simplify = T)
directions$routes$legs
# [[1]]
# distance.text distance.value duration.text duration.value duration_in_traffic.text duration_in_traffic.value end_address
# 1 5.2 km 5250 3 mins 161 3 mins 156 I-5, Gustine, CA 95322, USA
# end_location.lat end_location.lng start_address start_location.lat start_location.lng
# 1 37.15162 -121.0466 I-5, Gustine, CA 95322, USA 37.19349 -121.074
# steps
# 1 5.2 km, 5250, 3 mins, 161, 37.1516163, -121.0465852, Head <b>southeast</b> on <b>I-5 S</b>, ij_bFfg~aVpBgA`DkB~FeDbIwEpEgCtaAsj@nAs@lDqBxIaF~FgDlHcEjC{AdFuCrBkAhC{A|A{@|A}@bAk@rBkArBkA|A{@`DiB|A}@vDwBdAm@dAm@rBkA|A{@zA{@~J{FpC_B~A}@tBkAjHeEvGuDlMmHtBkAVO, 37.1934864, -121.0739565, DRIVING
# traffic_speed_entry via_waypoint
# 1 NULL NULL
google_distance(origins = list(c(37.193489,-121.07395)),
destinations = list(c(37.151616,-121.046586)),
key = key,
simplify = T,
units = "imperial")
# $destination_addresses
# [1] "I-5, Gustine, CA 95322, USA"
#
# $origin_addresses
# [1] "I-5, Gustine, CA 95322, USA"
#
# $rows
# elements
# 1 3.3 mi, 5250, 3 mins, 161, 3 mins, 157, OK
#
# $status
# [1] "OK"
Given the google_directions()
function returns a polyline (the line you get on Google Maps when you search for a route), we can plot it on a Google Map
key <- 'your_map_api_key'
df_route <- decode_pl(directions$routes$overview_polyline$points)
google_map(data = df_route, key = key, height = 800, search_box = T) %>%
add_markers()
## or you can use `add_polyline()` to view the entire line
At time of writing, Renjin (a Java-based R interpreter) does not have a lot of packages to help solve this problem. Here is an implementation that does not depend on extra packages.
# Computes the distance between two locations in meters. This uses an online
# map API and therefore an Internet connection is required for an accurate
# result. If no connection is found, this will use the Haversine formula
# to provide a rough estimate for the distance.
#
# @param src The source latitude and longitude.
# @param dst The destination latitude and longitude.
# @param mode Driving, cycling, walking, etc.
distance <- function( lat1, lon1, lat2, lon2, mode = 'driving' ) {
lat1 = as.numeric( lat1 )
lon1 = as.numeric( lon1 )
lat2 = as.numeric( lat2 )
lon2 = as.numeric( lon2 )
# Create the URL to use to get the distance data.
url = paste0(
'https://maps.googleapis.com/maps/api/distancematrix/xml?',
'origins=', lat1,
',', lon1,
'&destinations=', lat2,
',', lon2,
'&mode=', mode,
'&sensor=false'
)
tryCatch({
# Download the XML document with distance information.
xml = readLines( url )
# The <value> element immediately follows the distance element.
value = xml[ grep( "<distance>", xml ) + 1 ]
# Obtain the distance in meters.
meters = sub( ".*>(.*?)<.*", "\\1", value )
# Return the distance.
as.numeric( meters )
},
warning = function( w ) {
haversine( lat1, lon1, lat2, lon2 )
},
error = function( e ) {
haversine( lat1, lon1, lat2, lon2 )
})
}
# Computes distance using Haversine formula.
#
# Returns the result in meters.
haversine <- function( lat1, lon1, lat2, lon2, radius = 6371 ) {
# Convert decimal degrees to radians
lon1 = lon1 * pi / 180
lon2 = lon2 * pi / 180
lat1 = lat1 * pi / 180
lat2 = lat2 * pi / 180
# Haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
return( radius * c * 1000 )
}
Output:
distance( '44.5646', '-123.2620', '41.2861', '-124.0902' )
[1] 495892
distance( 44.5646, -123.2620, 41.2861, -124.0902, mode='walking' )
[1] 487715
Conversion from meters to feet is an exercise for the reader.
来源:https://stackoverflow.com/questions/16863018/getting-driving-distance-between-two-points-lat-lon-using-r-and-google-map-ap