Class: Geohex::V3::Zone

Inherits:
Object
  • Object
show all
Defined in:
lib/geohex/v3/zone.rb

Constant Summary collapse

H_KEY =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
H_BASE =
20037508.34
H_DEG =
Math::PI * (30.0 / 180)
H_K =
Math.tan(H_DEG)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#codeObject (readonly)

Returns the value of attribute code.



14
15
16
# File 'lib/geohex/v3/zone.rb', line 14

def code
  @code
end

#latitudeObject (readonly) Also known as: lat

Returns the value of attribute latitude.



14
15
16
# File 'lib/geohex/v3/zone.rb', line 14

def latitude
  @latitude
end

#levelObject (readonly)

Returns the value of attribute level.



14
15
16
# File 'lib/geohex/v3/zone.rb', line 14

def level
  @level
end

#longitudeObject (readonly) Also known as: lon

Returns the value of attribute longitude.



14
15
16
# File 'lib/geohex/v3/zone.rb', line 14

def longitude
  @longitude
end

#xObject (readonly)

Returns the value of attribute x.



15
16
17
# File 'lib/geohex/v3/zone.rb', line 15

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



15
16
17
# File 'lib/geohex/v3/zone.rb', line 15

def y
  @y
end

Class Method Details

.decode(code) ⇒ Object



25
26
27
28
29
30
# File 'lib/geohex/v3/zone.rb', line 25

def decode code
  instance = self.new
  instance.decode code

  instance
end

.encode(latitude, longitude, level) ⇒ Object



20
21
22
23
# File 'lib/geohex/v3/zone.rb', line 20

def encode latitude, longitude, level
  instance = self.new
  instance.encode latitude, longitude, level
end

Instance Method Details

#decode(code) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/geohex/v3/zone.rb', line 156

def decode code
  level = code.length
  @level = code.length - 2
  h_size = calcHexSize(level)

  unit_x = 6 * h_size
  unit_y = 6 * h_size * H_K
  h_x = 0
  h_y = 0
  h_dec9 = ((H_KEY.index(code.slice(0, 1)) * 30) + H_KEY.index(code.slice(1, 1))).to_s + code.slice(2, code.length)

  if h_dec9.slice(0, 1).match(/[15]/) and h_dec9.slice(1, 1).match(/[^125]/) and h_dec9.slice(2, 1).match(/[^125]/)
    if h_dec9.slice(0, 1) == "5"
      h_dec9 = "7" + h_dec9.slice(1, h_dec9.length)
    else
      h_dec9 = "3" + h_dec9.slice(1, h_dec9.length)
    end
  end

  d9xlen = h_dec9.length

  (level + 1 - d9xlen).times do
    h_dec9 = "0" + h_dec9
    d9xlen += 1
  end

  h_dec3 = ""
  d9xlen.times do |i|
    h_dec0 = h_dec9.slice(i, 1).to_i.to_s(3)

    if h_dec0.length == 1
      h_dec3 += "0"
    end
    h_dec3 += h_dec0
  end

  h_decx = []
  h_decy = []

  (h_dec3.length / 2).times do |i|
    h_decx << h_dec3.slice(i * 2, 1)
    h_decy << h_dec3.slice(i * 2 + 1, 1)
  end

  (level + 1).times do |i|
    h_pow = (3 ** (level - i))
    case h_decx[i].to_i
    when 0
      h_x -= h_pow
    when 2
      h_x += h_pow
    end

    case h_decy[i].to_i
    when 0
      h_y -= h_pow
    when 2
      h_y += h_pow
    end
  end

  h_x, h_y, rev = adjust_xy h_x, h_y, @level

  @latitude, @longitude, @x, @y, @code = getZoneByXY h_x, h_y, @level

  [@latitude, @longitude, @x, @y, @code]
end

#encode(latitude, longitude, level = 7) ⇒ Object

Raises:

  • (ArgumentError)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/geohex/v3/zone.rb', line 56

def encode latitude, longitude, level = 7
  raise ArgumentError, "latitude must be between -90 and 90" unless (-90..90).include? latitude
  raise ArgumentError, "longitude must be between -180 and 180" unless (-180..180).include? longitude
  raise ArgumentError, "level must be between 0 and 15" unless (0..15).include? level

  @level = level
  level += 2
  h_size = calcHexSize(@level)

  z_xy = loc2xy(longitude, latitude)
  lon_grid = z_xy.x
  lat_grid = z_xy.y
  unit_x = 6 * h_size
  unit_y = 6 * h_size * H_K
  h_pos_x = (lon_grid + lat_grid / H_K) / unit_x
  h_pos_y = (lat_grid - H_K * lon_grid) / unit_y
  h_x_0 = h_pos_x.floor
  h_y_0 = h_pos_y.floor
  h_x_q = h_pos_x - h_x_0
  h_y_q = h_pos_y - h_y_0
  h_x = h_pos_x.round
  h_y = h_pos_y.round

  if (h_y_q > (-h_x_q) + 1)
    if((h_y_q < 2 * h_x_q) && (h_y_q > 0.5 * h_x_q))
      h_x = h_x_0 + 1
      h_y = h_y_0 + 1
    end
  elsif (h_y_q < (-h_x_q) + 1)
    if ((h_y_q > (2 * h_x_q) - 1) && (h_y_q < (0.5 * h_x_q) + 0.5))
      h_x = h_x_0
      h_y = h_y_0
    end
  end

  h_lat = (H_K * h_x * unit_x + h_y * unit_y) / 2
  h_lon = (h_lat - h_y * unit_y) / H_K

  z_loc = xy2loc(h_lon, h_lat)
  z_loc_x = z_loc.lon
  z_loc_y = z_loc.lat
  if ((H_BASE - h_lon) < h_size)
    z_loc_x = 180.0
    h_xy = h_x
    h_x = h_y
    h_y = h_xy
  end

  h_code = ''
  code3_x = []
  code3_y = []
  code3 = ''
  code9 = ''
  mod_x = h_x
  mod_y = h_y

  (level + 1).times do |i|
    h_pow = (3 ** (level - i))

    if (mod_x >= (h_pow / 2.0).ceil)
      code3_x << 2
      mod_x -= h_pow
    elsif(mod_x <= -(h_pow / 2.0).ceil)
      code3_x << 0
      mod_x += h_pow
    else
      code3_x << 1
    end

    if (mod_y >= (h_pow / 2.0).ceil)
      code3_y << 2
      mod_y -= h_pow
    elsif (mod_y <= -(h_pow / 2.0).ceil)
      code3_y << 0
      mod_y += h_pow
    else
      code3_y << 1
    end
  end

  (code3_x.size).to_i.times do |i|
    code3 = "#{ code3_x[i] }#{ code3_y[i] }"
    code9 = code3.to_i(3).to_s
    h_code += code9.to_s
  end

  h_2  = h_code.slice(3, h_code.size).to_s
  h_1  = h_code.slice(0, 3).to_i
  h_a1 = (h_1 / 30).to_i
  h_a2 = h_1 % 30

  @code = "#{ H_KEY.slice(h_a1, 1) }#{ H_KEY.slice(h_a2, 1) }#{ h_2 }"
  @x = h_x
  @y = h_y
  @latitude = latitude
  @longitude = longitude

  @code
end