Skip to content

Instantly share code, notes, and snippets.

@matsadler
Created August 2, 2012 11:51
Show Gist options
  • Save matsadler/3236508 to your computer and use it in GitHub Desktop.
Save matsadler/3236508 to your computer and use it in GitHub Desktop.
Additions to the pr_geohash gem for distance calculation
require "pr_geohash"
module GeoHash
RADIUS_OF_THE_EARTH = 6371
RADIANS_CONVERSION_FACTOR = 180 / Math::PI
# decode geohash to a latitude/longitude point in the centre of the
# bounding box described by the geohash
def decode_point(geohash)
lat_min, lng_min, lat_max, lng_max = decode(geohash).flatten
lat = round_between((lat_min + lat_max) / 2, lat_min, lat_max)
lng = round_between((lng_min + lng_max) / 2, lng_min, lng_max)
[lat, lng]
end
module_function :decode_point
# return distance between the centre point of each geohash in kilometres
def distance(origin_geohash, destination_geohash)
origin_lat, origin_long = GeoHash.decode_point(origin_geohash)
dest_lat, dest_long = GeoHash.decode_point(destination_geohash)
sin_lats = Math.sin(rad(origin_lat)) * Math.sin(rad(dest_lat))
cos_lats = Math.cos(rad(origin_lat)) * Math.cos(rad(dest_lat))
cos_longs = Math.cos(rad(dest_long) - rad(origin_long))
x = sin_lats + (cos_lats * cos_longs)
x = [x, 1.0].min
x = [x, -1.0].max
Math.acos(x) * RADIUS_OF_THE_EARTH
end
module_function :distance
# :stopdoc:
# nominally private, but not possible as a module_function
# (which they have to be available for the other module_functions)
def round_between(value, min, max, max_length=10)
rounded = value
while max_length > 0 && rounded > min && rounded < max
rounded = value.round(max_length)
max_length -= 1
end
value.round(max_length + 1)
end
module_function :round_between
def rad(degree)
degree / RADIANS_CONVERSION_FACTOR
end
module_function :rad
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment