Module: Quadkey

Defined in:
lib/quadkey.rb,
lib/quadkey/version.rb

Constant Summary collapse

MIN_LATITUDE =
-85.05112878
MAX_LATITUDE =
85.05112878
MIN_LONGITUDE =
-180
MAX_LONGITUDE =
180
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.clip(n, min_value, max_value) ⇒ Object



23
24
25
# File 'lib/quadkey.rb', line 23

def self.clip(n, min_value, max_value)
  [[n, min_value].max, max_value].min
end

.coordinates_to_pixel(latitude, longitude, precision) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/quadkey.rb', line 31

def self.coordinates_to_pixel(latitude, longitude, precision)
  latitude = clip(latitude, MIN_LATITUDE, MAX_LATITUDE)
  longitude = clip(longitude, MIN_LONGITUDE, MAX_LONGITUDE)

  x = (longitude + 180) / 360
  sin_latitude = Math.sin(latitude * Math::PI / 180)
  y = 0.5 - Math.log((1 + sin_latitude) / (1 - sin_latitude)) / (4 * Math::PI)

  map_size = map_size(precision).to_f
  pixel_x = clip(x * map_size + 0.5, 0, map_size - 1).to_i
  pixel_y = clip(y * map_size + 0.5, 0, map_size - 1).to_i

  return pixel_x, pixel_y
end

.decode(quadkey) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/quadkey.rb', line 15

def self.decode(quadkey)
  tile_x, tile_y, precision = quadkey_to_tile(quadkey)
  pixel_x, pixel_y = tile_to_pixel(tile_x, tile_y)
  latitude, longitude = pixel_to_coordinates(pixel_x, pixel_y, precision)

  return latitude, longitude, precision
end

.encode(latitude, longitude, precision) ⇒ Object



9
10
11
12
13
# File 'lib/quadkey.rb', line 9

def self.encode(latitude, longitude, precision)
  pixel_x, pixel_y = coordinates_to_pixel(latitude, longitude, precision)
  tile_x, tile_y = pixel_to_tile(pixel_x, pixel_y)
  tile_to_quadkey(tile_x, tile_y, precision)
end

.map_size(precision) ⇒ Object



27
28
29
# File 'lib/quadkey.rb', line 27

def self.map_size(precision)
  256 << precision
end

.pixel_to_coordinates(pixel_x, pixel_y, precision) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/quadkey.rb', line 46

def self.pixel_to_coordinates(pixel_x, pixel_y, precision)
  map_size = map_size(precision).to_f
  x = (clip(pixel_x, 0, map_size - 1) / map_size).to_f - 0.5
  y = 0.5 - (clip(pixel_y, 0, map_size - 1) / map_size).to_f

  latitude = 90 - 360 * Math.atan(Math.exp(-y * 2 * Math::PI)) / Math::PI
  longitude = 360 * x

  return latitude, longitude
end

.pixel_to_tile(pixel_x, pixel_y) ⇒ Object



57
58
59
60
61
62
# File 'lib/quadkey.rb', line 57

def self.pixel_to_tile(pixel_x, pixel_y)
  tile_x = pixel_x / 256
  tile_y = pixel_y / 256

  return tile_x, tile_y
end

.quadkey_to_tile(quadkey) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/quadkey.rb', line 90

def self.quadkey_to_tile(quadkey)
  tile_x = 0
  tile_y = 0
  precision = quadkey.length
  precision.downto(1) do |i|
    mask = 1 << (i - 1)
    case quadkey[precision - i]
    when '0'
    when '1'
      tile_x |= mask
    when '2'
      tile_y |= mask
    when '3'
      tile_x |= mask
      tile_y |= mask
    else
      raise "Invalid Quadkey digit sequence."
    end
  end

  return tile_x, tile_y, precision
end

.tile_to_pixel(tile_x, tile_y) ⇒ Object



64
65
66
67
68
69
# File 'lib/quadkey.rb', line 64

def self.tile_to_pixel(tile_x, tile_y)
  pixel_x = tile_x * 256
  pixel_y = tile_y * 256

  return pixel_x, pixel_y
end

.tile_to_quadkey(tile_x, tile_y, precision) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/quadkey.rb', line 71

def self.tile_to_quadkey(tile_x, tile_y, precision)
  quadkey = ''

  precision.downto(1) do |i|
    digit = '0'.ord
    mask = 1 << (i - 1)
    if (tile_x & mask) != 0
      digit += 1
    end
    if (tile_y & mask) != 0
      digit += 1
      digit += 1
    end
    quadkey += digit.chr
  end

  return quadkey
end