class DistanceFox::Calculations
Constants
- EARTH_RADIUS
Public Class Methods
Origin and destination can be:
-
an array of coordinates ([lat,lon])
-
an array of coordinates (['lat','lon'])
-
a geocodable address (string)
# File lib/distance_fox/calculations.rb, line 62 def self.driving_distance(origin, destination) origin = extract_coordinates(origin).join(',') destination = extract_coordinates(destination).join(',') google_distance_query = "https://maps.googleapis.com/maps/api/distancematrix/json?mode=driving&origins=#{origin}&destinations=#{destination}&key=#{DistanceFox.configuration.api_key}" google_distance_response = HTTParty.get(URI.escape(google_distance_query)) google_distance_response['rows'][0]['elements'][0]['distance']['value'].to_f / 1000 end
Address can be: a geocodable address (string)
# File lib/distance_fox/calculations.rb, line 88 def self.geocode(address) google_distance_response = HTTParty.get(URI.escape(google_distance_query)) case google_distance_response["results"] when [] raise "Status: #{google_distance_response['status']}" else coordinates = google_distance_response['results'][0]['geometry']['location'] end [coordinates['lat'], coordinates['lng']] end
Origin and destination can be:
-
an array of coordinates ([lat,lon])
-
an array of coordinates (['lat','lon'])
-
a geocodable address (string)
# File lib/distance_fox/calculations.rb, line 12 def self.linear_distance(origin, destination) lat_origin, lon_origin = extract_coordinates origin lat_destination, lon_destination = extract_coordinates destination delta_lat = (lat_destination - lat_origin) * Math::PI / 180 delta_lon = (lon_destination - lon_origin) * Math::PI / 180 a = Math.sin(delta_lat / 2) * Math.sin(delta_lat / 2) + Math.cos(lat_origin * Math::PI / 180) * Math.cos(lat_destination * Math::PI / 180) * Math.sin(delta_lon / 2) * Math.sin(delta_lon / 2) c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) d = EARTH_RADIUS * c d.round(3) end
Driving Distance to nearest location from multiple locations
Origin can be:
-
an array of coordinates ([lat,lon])
-
an array of coordinates (['lat','lon'])
-
a geocodable address (string)
Destinations can be:
-
an array of hashes ([{'city' => 'City', 'coordinates' => ['lat','lon']}])
# File lib/distance_fox/calculations.rb, line 80 def self.nearest_driving_distance(origin, destinations) origin = origin.join(',') destination = nearest_linear_distance(origin, destinations)['coordinates']['destination'].join(',') driving_distance(origin, destination) end
Linear Distance to nearest location from multiple locations Origin can be:
-
an array of float coordinates ([lat,lon])
-
an array of string coordinates (['lat','lon'])
Destinations can be:
-
an array of hashes ([{'city' => 'City', 'coordinates' => ['lat','lon']}])
# File lib/distance_fox/calculations.rb, line 39 def self.nearest_linear_distance(origin, destinations) origins_with_distance = [] origin_coordinates = extract_coordinates origin destinations.each do |destination| distance = linear_distance(origin_coordinates, destination['coordinates']) origins_with_distance.push( 'destination' => destination['city'], 'distance' => distance, 'coordinates' => { 'origin' => origin_coordinates, 'destination' => destination['coordinates'] } ) end origins_with_distance.min_by { |key| key['distance'] } end
Private Class Methods
Takes an object which is a [lat,lon] array or a geocodable string. Note that if a string is passed this may be a slow- running method and may return nil.
# File lib/distance_fox/calculations.rb, line 105 def self.extract_coordinates(point) case point when Array if point.size == 2 lat, lon = point if !lat.nil? && lat.respond_to?(:to_f) && !lon.nil? && lon.respond_to?(:to_f) return [lat.to_f, lon.to_f] end end when String (point = geocode(point)) && (return point) end raise "#{point} is not geocodable" end