Class: DistanceFox::Calculations

Inherits:
Object
  • Object
show all
Defined in:
lib/distance_fox/calculations.rb

Constant Summary collapse

EARTH_RADIUS =
6371.0

Class Method Summary collapse

Class Method Details

.driving_distance(origin, destination) ⇒ Object

Origin and destination can be:

  • an array of coordinates ([lat,lon])

  • an array of coordinates ([‘lat’,‘lon’])

  • a geocodable address (string)



62
63
64
65
66
67
68
# 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

.geocode(address) ⇒ Object

Address can be: a geocodable address (string)



88
89
90
91
92
93
94
95
96
97
# 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

.linear_distance(origin, destination) ⇒ Object

Origin and destination can be:

  • an array of coordinates ([lat,lon])

  • an array of coordinates ([‘lat’,‘lon’])

  • a geocodable address (string)



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 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

.nearest_driving_distance(origin, destinations) ⇒ Object

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’, ‘coordinates’ => [‘lat’,‘lon’]])



80
81
82
83
84
# 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

.nearest_linear_distance(origin, destinations) ⇒ Object

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’, ‘coordinates’ => [‘lat’,‘lon’]])



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 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