module Geocoder::Calculations

def distance_between(lat1, lon1, lat2, lon2, options = {})


:units :: :mi (default) or :km

Takes two sets of coordinates and an options hash:
Calculate the distance between two points on Earth (Haversine formula).
#
def distance_between(lat1, lon1, lat2, lon2, options = {})
  # set default options
  options[:units] ||= :mi
  # define conversion factors
  conversions = { :mi => 3956, :km => 6371 }
  # convert degrees to radians
  lat1 = to_radians(lat1)
  lon1 = to_radians(lon1)
  lat2 = to_radians(lat2)
  lon2 = to_radians(lon2)
  # compute distances
  dlat = (lat1 - lat2).abs
  dlon = (lon1 - lon2).abs
  a = (Math.sin(dlat / 2))**2 + Math.cos(lat1) *
      (Math.sin(dlon / 2))**2 * Math.cos(lat2)
  c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
  c * conversions[options[:units]]
end

def geographic_center(points)


the procedure documented at http://www.geomidpoint.com/calculation.html.
(can be mixed). Any objects missing coordinates are ignored. Follows
gravity) for an array of geocoded objects and/or [lat,lon] arrays
Compute the geographic center (aka geographic midpoint, center of
#
def geographic_center(points)
  # convert objects to [lat,lon] arrays and remove nils
  points = points.map{ |p|
    p.is_a?(Array) ? p : (p.geocoded?? p.read_coordinates : nil)
  }.compact
  # convert degrees to radians
  points.map!{ |p| [to_radians(p[0]), to_radians(p[1])] }
  # convert to Cartesian coordinates
  x = []; y = []; z = []
  points.each do |p|
    x << Math.cos(p[0]) * Math.cos(p[1])
    y << Math.cos(p[0]) * Math.sin(p[1])
    z << Math.sin(p[0])
  end
  # compute average coordinate values
  xa, ya, za = [x,y,z].map do |c|
    c.inject(0){ |tot,i| tot += i } / c.size.to_f
  end
  # convert back to latitude/longitude
  lon = Math.atan2(ya, xa)
  hyp = Math.sqrt(xa**2 + ya**2)
  lat = Math.atan2(za, hyp)
  # return answer in degrees
  [to_degrees(lat), to_degrees(lon)]
end

def km_in_mi


Conversion factor: km to mi.
#
def km_in_mi
  0.621371192
end

def to_degrees(radians)


Convert radians to degrees.
#
def to_degrees(radians)
  (radians * 180.0) / Math::PI
end

def to_radians(degrees)


Convert degrees to radians.
#
def to_radians(degrees)
  degrees * (Math::PI / 180)
end