Skip to content
Snippets Groups Projects
Commit 86396c02 authored by alexreisner's avatar alexreisner
Browse files

Refactor: extract some common code into new methods.

parent d00e7e85
No related branches found
No related tags found
No related merge requests found
...@@ -67,31 +67,12 @@ module Geocoder ...@@ -67,31 +67,12 @@ module Geocoder
## ##
# Named scope options hash for use with a database that supports POWER(), # Named scope options hash for use with a database that supports POWER(),
# SQRT(), PI(), and trigonometric functions (SIN(), COS(), and ASIN()). # SQRT(), PI(), and trigonometric functions (SIN(), COS(), and ASIN()).
# #
# Taken from the excellent tutorial at: # Taken from the excellent tutorial at:
# http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL # http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
# #
def full_near_scope_options(latitude, longitude, radius, options) def full_near_scope_options(latitude, longitude, radius, options)
# set defaults/clean up arguments
options[:order] ||= 'distance ASC' options[:order] ||= 'distance ASC'
radius = radius.to_i
# constrain search to a (radius x radius) square
factor = (Math::cos(latitude * Math::PI / 180.0) * 69.0).abs
lon_lo = longitude - (radius / factor);
lon_hi = longitude + (radius / factor);
lat_lo = latitude - (radius / 69.0);
lat_hi = latitude + (radius / 69.0);
# build limit clause
limit = nil
if options[:limit] or options[:offset]
options[:offset] ||= 0
limit = "#{options[:offset]},#{options[:limit]}"
end
# generate hash
lat_attr = geocoder_options[:latitude] lat_attr = geocoder_options[:latitude]
lon_attr = geocoder_options[:longitude] lon_attr = geocoder_options[:longitude]
distance = "3956 * 2 * ASIN(SQRT(" + distance = "3956 * 2 * ASIN(SQRT(" +
...@@ -102,13 +83,12 @@ module Geocoder ...@@ -102,13 +83,12 @@ module Geocoder
"PI() / 180 / 2), 2) ))" "PI() / 180 / 2), 2) ))"
{ {
:select => "*, #{distance} AS distance", :select => "*, #{distance} AS distance",
:conditions => [ :conditions => \
"#{lat_attr} BETWEEN ? AND ? AND " + ["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
"#{lon_attr} BETWEEN ? AND ?", coordinate_bounds(latitude, longitude, radius),
lat_lo, lat_hi, lon_lo, lon_hi],
:having => "#{distance} <= #{radius}", :having => "#{distance} <= #{radius}",
:order => options[:order], :order => options[:order],
:limit => limit :limit => limit_clause(options)
} }
end end
...@@ -119,36 +99,42 @@ module Geocoder ...@@ -119,36 +99,42 @@ module Geocoder
# objects outside the given radius). # objects outside the given radius).
# #
def approx_near_scope_options(latitude, longitude, radius, options) def approx_near_scope_options(latitude, longitude, radius, options)
# set defaults/clean up arguments
radius = radius.to_i
# constrain search to a (radius x radius) square
factor = (Math::cos(latitude * Math::PI / 180.0) * 69.0).abs
lon_lo = longitude - (radius / factor);
lon_hi = longitude + (radius / factor);
lat_lo = latitude - (radius / 69.0);
lat_hi = latitude + (radius / 69.0);
# build limit clause
limit = nil
if options[:limit] or options[:offset]
options[:offset] ||= 0
limit = "#{options[:offset]},#{options[:limit]}"
end
# generate hash
lat_attr = geocoder_options[:latitude] lat_attr = geocoder_options[:latitude]
lon_attr = geocoder_options[:longitude] lon_attr = geocoder_options[:longitude]
{ {
:conditions => [ :conditions => \
"#{lat_attr} BETWEEN ? AND ? AND " + ["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
"#{lon_attr} BETWEEN ? AND ?", coordinate_bounds(latitude, longitude, radius),
lat_lo, lat_hi, lon_lo, lon_hi],
:order => options[:order], :order => options[:order],
:limit => limit :limit => limit_clause(options)
} }
end end
##
# Get the rough high/low lat/long bounds for a geographic point and
# radius. Returns an array: <tt>[lat_lo, lat_hi, lon_lo, lon_hi]</tt>.
# Used to constrain search to a (radius x radius) square.
#
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
##
# Build the limit clause for a query based on the same options hash
# passed to the x_near_scope_options methods.
#
def limit_clause(options)
if options[:limit] or options[:offset]
"#{options[:offset].to_i},#{options[:limit].to_i}"
end
end
end end
## ##
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment