Module: MockRedis::GeospatialMethods

Included in:
Database
Defined in:
lib/mock_redis/geospatial_methods.rb

Constant Summary collapse

LNG_RANGE =
(-180..180).freeze
LAT_RANGE =
(-85.05112878..85.05112878).freeze
STEP =
26
UNITS =
{
  m: 1,
  km: 1000,
  ft: 0.3048,
  mi: 1609.34
}.freeze
D_R =
Math::PI / 180.0
EARTH_RADIUS_IN_METERS =
6_372_797.560856

Instance Method Summary collapse

Instance Method Details

#geodist(key, member1, member2, unit = 'm') ⇒ Object


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/mock_redis/geospatial_methods.rb', line 26

def geodist(key, member1, member2, unit = 'm')
  to_meter = parse_unit(unit)

  return nil if zcard(key).zero?

  score1 = zscore(key, member1)
  score2 = zscore(key, member2)
  return nil if score1.nil? || score2.nil?
  hash1 = { bits: score1.to_i, step: STEP }
  hash2 = { bits: score2.to_i, step: STEP }

  lng1, lat1 = geohash_decode(hash1)
  lng2, lat2 = geohash_decode(hash2)

  distance = geohash_distance(lng1, lat1, lng2, lat2) / to_meter
  format('%<distance>.4f', distance: distance)
end

#geohash(key, members) ⇒ Object


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/mock_redis/geospatial_methods.rb', line 44

def geohash(key, members)
  lng_range = (-180..180)
  lat_range = (-90..90)
  geoalphabet = '0123456789bcdefghjkmnpqrstuvwxyz'

  Array(members).map do |member|
    score = zscore(key, member)
    next nil unless score
    score = score.to_i
    hash = { bits: score, step: STEP }
    lng, lat = geohash_decode(hash)
    bits = geohash_encode(lng, lat, lng_range, lat_range)[:bits]
    hash = ''
    11.times do |i|
      shift = (52 - ((i + 1) * 5))
      idx = shift > 0 ? (bits >> shift) & 0x1f : 0
      hash << geoalphabet[idx]
    end
    hash
  end
end

#geopos(key, members) ⇒ Object


66
67
68
69
70
71
72
73
74
75
76
# File 'lib/mock_redis/geospatial_methods.rb', line 66

def geopos(key, members)
  Array(members).map do |member|
    score = zscore(key, member)
    next nil unless score
    hash = { bits: score.to_i, step: STEP }
    lng, lat = geohash_decode(hash)
    lng = format_decoded_coord(lng)
    lat = format_decoded_coord(lat)
    [lng, lat]
  end
end