class Maidenhead
Easily convert between latitude and longitude coordinates the the Maidenhead
Locator System coordinates.
Public Class Methods
Convert from a Maidenhead
locator string to latitude and longitude. Location may be between 1 and 5 grids in size (2 to 10 characters). Longer values may work, but accuracy is not guaranteed as latitude and longitude values returned are rounded ot 6 decimal places.
For each grid, an arbitrary but repeatable latitude and longitude is returned.
# File lib/maidenhead.rb, line 37 def self.to_latlon(location) maidenhead = Maidenhead.new maidenhead.locator = location [ maidenhead.lat, maidenhead.lon ] end
Convert from latitude and longitude to a Maidenhead
locator string. Latitude should be between -90 and 90, and longitude should be between -180 and 180. Precision defaults to 5 blocks, which returns 10 characters. More precise coordinates may work, but accuracy is not guaranteed.
# File lib/maidenhead.rb, line 72 def self.to_maidenhead(lat, lon, precision = 5) maidenhead = Maidenhead.new maidenhead.lat = lat maidenhead.lon = lon maidenhead.precision = precision maidenhead.locator end
Verify that the provided Maidenhead
locator string is valid.
# File lib/maidenhead.rb, line 8 def self.valid_maidenhead?(location) return false unless location.is_a?String return false unless location.length >= 2 return false unless (location.length % 2) == 0 length = location.length / 2 length.times do |counter| grid = location[counter * 2, 2] if (counter == 0) return false unless grid =~ /[a-rA-R]{2}/ elsif (counter % 2) == 0 return false unless grid =~ /[a-xA-X]{2}/ else return false unless grid =~ /[0-9]{2}/ end end true end
Public Instance Methods
Retrieve the latitude, usually post-conversion from a locator string. The result is rounded to 6 decimal places.
# File lib/maidenhead.rb, line 92 def lat @lat.round(6) end
Set the latitude. Values must be between -90.0 and +90.0 or an ArgumentError will be raised.
# File lib/maidenhead.rb, line 84 def lat=(pos) @lat = range_check("lat", 90.0, pos) end
Set the locator string. It must be a valid string, or an ArgumentError will be raised. This also directly computes the latitude and longitude values for this locator, so they will be valid after caling this method.
# File lib/maidenhead.rb, line 48 def locator=(location) unless Maidenhead.valid_maidenhead?(location) raise ArgumentError.new("Location is not a valid Maidenhead Locator System string") end @locator = location @lat = -90.0 @lon = -180.0 pad_locator convert_part_to_latlon(0, 1) convert_part_to_latlon(1, 10) convert_part_to_latlon(2, 10 * 24) convert_part_to_latlon(3, 10 * 24 * 10) convert_part_to_latlon(4, 10 * 24 * 10 * 24) end
Retrieve the longitude, usually post-conversion from a locator string. The result is rounded to 6 decimal places.
# File lib/maidenhead.rb, line 108 def lon @lon.round(6) end
Set the longitude. Values must be between -180.0 and +180.0 or an ArgumentError will be raised.
# File lib/maidenhead.rb, line 100 def lon=(pos) @lon = range_check("lon", 180.0, pos) end
# File lib/maidenhead.rb, line 121 def precision @precision end
Set the desired precision when converting from a latitude / longitude to a maidenhead locator. This specifies the number of groups to use, usually 2 through 5, which results in 4 through 10 characters.
# File lib/maidenhead.rb, line 117 def precision=(value) @precision = value end
Private Instance Methods
# File lib/maidenhead.rb, line 164 def calculate_field @lat_tmp = (@lat_tmp / 10) + 0.0000001 @lon_tmp = (@lon_tmp / 20) + 0.0000001 @locator += n2l(@lon_tmp.floor).upcase + n2l(@lat_tmp.floor).upcase @precision_tmp -= 1 end
# File lib/maidenhead.rb, line 182 def calculate_values @precision_tmp.times do |counter| if (counter % 2) == 0 compute_locator(counter, 10) else compute_locator(counter, 24) end end end
# File lib/maidenhead.rb, line 171 def compute_locator(counter, divisor) @lat_tmp = (@lat_tmp - @lat_tmp.floor) * divisor @lon_tmp = (@lon_tmp - @lon_tmp.floor) * divisor if (counter % 2) == 0 @locator += "#{@lon_tmp.floor}#{@lat_tmp.floor}" else @locator += n2l(@lon_tmp.floor) + n2l(@lat_tmp.floor) end end
# File lib/maidenhead.rb, line 156 def convert_part_to_latlon(counter, divisor) grid_lon = @locator[counter * 2, 1] grid_lat = @locator[counter * 2 + 1, 1] @lat += l2n(grid_lat) * 10.0 / divisor @lon += l2n(grid_lon) * 20.0 / divisor end
# File lib/maidenhead.rb, line 192 def l2n(letter) if letter =~ /[0-9]+/ letter.to_i else letter.downcase.ord - 97 end end
# File lib/maidenhead.rb, line 200 def n2l(number) (number + 97).chr end
# File lib/maidenhead.rb, line 144 def pad_locator length = @locator.length / 2 while (length < 5) if (length % 2) == 1 @locator += '55' else @locator += 'LL' end length = @locator.length / 2 end end
# File lib/maidenhead.rb, line 204 def range_check(target, range, pos) pos = pos.to_f if pos < -range or pos > range raise ArgumentError.new("#{target} must be between -#{range} and +#{range}") end pos end