module Geocoder::Orm::ActiveRecord::ClassMethods

def approx_near_scope_options(latitude, longitude, radius, options)


objects outside the given radius).
rather than a circle, so results are very approximate (will include
functions, like SQLite. Approach is to find objects within a square
Scope options hash for use with a database without trigonometric
#
def approx_near_scope_options(latitude, longitude, radius, options)
  default_near_scope_options(latitude, longitude, radius, options).merge(
    :select => options[:select] || nil
  )
end

def coordinate_bounds(latitude, longitude, radius)


Used to constrain search to a (radius x radius) square.
radius. Returns an array: [lat_lo, lat_hi, lon_lo, lon_hi].
Get the rough high/low lat/long bounds for a geographic point and
#
def coordinate_bounds(latitude, longitude, radius)
  radius = radius.to_f
  factor = (Math::cos(latitude * Math::PI / 180.0) * 69.0).abs
  [
    latitude  - (radius / 69.0),
    latitude  + (radius / 69.0),
    longitude - (radius / factor),
    longitude + (radius / factor)
  ]
end

def default_near_scope_options(latitude, longitude, radius, options)


Options used for any near-like scope.
#
def default_near_scope_options(latitude, longitude, radius, options)
  lat_attr = geocoder_options[:latitude]
  lon_attr = geocoder_options[:longitude]
  conditions = \
    ["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
    coordinate_bounds(latitude, longitude, radius)
  if obj = options[:exclude]
    conditions[0] << " AND #{table_name}.id != ?"
    conditions << obj.id
  end
  {
    :group  => columns.map{ |c| "#{table_name}.#{c.name}" }.join(','),
    :order  => options[:order],
    :limit  => options[:limit],
    :offset => options[:offset],
    :conditions => conditions
  }
end

def full_near_scope_options(latitude, longitude, radius, options)


http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
Taken from the excellent tutorial at:

SQRT(), PI(), and trigonometric functions (SIN(), COS(), and ASIN()).
Scope options hash for use with a database that supports POWER(),
#
def full_near_scope_options(latitude, longitude, radius, options)
  lat_attr = geocoder_options[:latitude]
  lon_attr = geocoder_options[:longitude]
  distance = "3956 * 2 * ASIN(SQRT(" +
    "POWER(SIN((#{latitude} - #{lat_attr}) * " +
    "PI() / 180 / 2), 2) + COS(#{latitude} * PI()/180) * " +
    "COS(#{lat_attr} * PI() / 180) * " +
    "POWER(SIN((#{longitude} - #{lon_attr}) * " +
    "PI() / 180 / 2), 2) ))"
  options[:order] ||= "#{distance} ASC"
  default_near_scope_options(latitude, longitude, radius, options).merge(
    :select => "#{options[:select] || '*'}, #{distance} AS distance",
    :having => "#{distance} <= #{radius}"
  )
end

def near_scope_options(latitude, longitude, radius = 20, options = {})


+select+ :: string with the SELECT SQL fragment (e.g. “id, name”)
+offset+ :: number of records to skip (for OFFSET SQL clause)
+limit+ :: number of records to return (for LIMIT SQL clause)
+order+ :: column(s) for ORDER BY SQL clause
+exclude+ :: an object to exclude (used by the #nearbys method)
+units+ :: :mi (default) or :km

Options hash may include:
records within a radius (in miles) of the given point.
Get options hash suitable for passing to ActiveRecord.find to get
#
def near_scope_options(latitude, longitude, radius = 20, options = {})
  radius *= Geocoder::Calculations.km_in_mi if options[:units] == :km
  if ::ActiveRecord::Base.connection.adapter_name == "SQLite"
    approx_near_scope_options(latitude, longitude, radius, options)
  else
    full_near_scope_options(latitude, longitude, radius, options)
  end
end