class ProximityHash

Constants

EARTH_RADIUS
MAX_PRECISION
MIN_PRECISION

Public Class Methods

new(latitude, longitude, radius, precision) click to toggle source
# File lib/proximityhash.rb, line 11
def initialize(latitude, longitude, radius, precision)
  @centre = [ latitude, longitude ]
  @radius = radius
  @precision = precision
  if ((precision > MAX_PRECISION) or (precision < MIN_PRECISION))
    raise 'Precision out bounds'
  end
end

Public Instance Methods

calculate() click to toggle source
# File lib/proximityhash.rb, line 20
def calculate
  x = 0.0
  y = 0.0

  points = []
  geohashes = {}

  grid_width = [ 5009400.0, 1252300.0, 156500.0, 39100.0, 4900.0, 1200.0, 152.9, 38.2, 4.8, 1.2, 0.149, 0.0370 ]
  grid_height = [ 4992600.0, 624100.0, 156000.0, 19500.0, 4900.0, 609.4, 152.4, 19.0, 4.8, 0.595, 0.149, 0.0199 ]

  height = (grid_height[@precision - 1]) / 2.0
  width = (grid_width[@precision - 1]) / 2.0

  latitude = @centre[0]
  longitude = @centre[1]

  lat_moves = (@radius / height).ceil
  lon_moves = (@radius / width).ceil

  (0 .. lat_moves).each do |i|

    temp_lat = y + (height * i)

    (0..lon_moves).each do |j|

      temp_lon = x + (width * j)

      if within_radius(temp_lat, temp_lon, y, x) == true

        x_cen, y_cen = get_centre(temp_lat, temp_lon, height, width)
        lat, lon = convert_to_latlon(y_cen, x_cen, latitude, longitude)
        points += [[lat, lon]]
        lat, lon = convert_to_latlon(-y_cen, x_cen, latitude, longitude)
        points += [[lat, lon]]
        lat, lon = convert_to_latlon(y_cen, -x_cen, latitude, longitude)
        points += [[lat, lon]]
        lat, lon = convert_to_latlon(-y_cen, -x_cen, latitude, longitude)
        points += [[lat, lon]]
      end

    end

  end

  points.each do |point|
    geohash = GeoHash.encode(point[0], point[1], @precision)
    geohashes[geohash] = Haversine.distance(point, @centre).to_meters
  end

  geohashes.sort_by { |key, value| value }.to_h
end

Private Instance Methods

convert_to_latlon(y, x, latitude, longitude) click to toggle source
# File lib/proximityhash.rb, line 90
def convert_to_latlon(y, x, latitude, longitude)
   lat_diff = (y / EARTH_RADIUS) * (180.0 / Math::PI)
  lon_diff = (x / EARTH_RADIUS) * (180.0 / Math::PI) / Math.cos(latitude * Math::PI/180.0)

  final_lat = latitude + lat_diff
  final_lon = longitude + lon_diff

  return final_lat, final_lon
end
get_centre(latitude, longitude, height, width) click to toggle source
# File lib/proximityhash.rb, line 82
def get_centre(latitude, longitude, height, width)

  y_cen = latitude + (height / 2.0)
  x_cen = longitude + (width / 2.0)

  return x_cen, y_cen
end
within_radius(latitude, longitude, centre_lat, centre_lon) click to toggle source
# File lib/proximityhash.rb, line 74
def within_radius(latitude, longitude, centre_lat, centre_lon)

  x_diff = longitude - centre_lon
  y_diff = latitude - centre_lat

  return (((x_diff ** 2) + (y_diff ** 2)) <= (@radius ** 2))
end