Class: PlusCodes::OpenLocationCode
- Inherits:
-
Object
- Object
- PlusCodes::OpenLocationCode
- Defined in:
- lib/plus_codes/open_location_code.rb
Overview
- OpenLocationCode
-
implements the Google Open Location Code(Plus+Codes) algorithm.
Instance Method Summary collapse
-
#decode(code) ⇒ CodeArea
Decodes an Open Location Code(Plus+Codes) into a [CodeArea].
-
#encode(latitude, longitude, code_length = 10) ⇒ String
Converts a latitude and longitude into a Open Location Code(Plus+Codes).
-
#full?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid full Open Location Code(Plus+Codes).
-
#recover_nearest(short_code, reference_latitude, reference_longitude) ⇒ String
Recovers a full Open Location Code(Plus+Codes) from a short code and a reference location.
-
#short?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid short Open Location Code(Plus+Codes).
-
#shorten(code, latitude, longitude) ⇒ String
Removes four, six or eight digits from the front of an Open Location Code(Plus+Codes) given a reference location.
-
#valid?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid sequence of Open Location Code(Plus+Codes) characters.
Instance Method Details
#decode(code) ⇒ CodeArea
Decodes an Open Location Code(Plus+Codes) into a [CodeArea].
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 |
# File 'lib/plus_codes/open_location_code.rb', line 70 def decode(code) raise ArgumentError, "Open Location Code(Plus+Codes) is not a valid full code: #{code}" unless full?(code) code = code.gsub(SEPARATOR, '') code = code.gsub(/#{PADDING}+/, '') code = code.upcase south_latitude = -90.0 west_longitude = -180.0 lat_resolution = 400.to_r lng_resolution = 400.to_r digit = 0 while digit < code.length if digit < 10 lat_resolution /= 20 lng_resolution /= 20 south_latitude += lat_resolution * DECODE[code[digit].ord] west_longitude += lng_resolution * DECODE[code[digit + 1].ord] digit += 2 else lat_resolution /= 5 lng_resolution /= 4 row = DECODE[code[digit].ord] / 4 column = DECODE[code[digit].ord] % 4 south_latitude += lat_resolution * row west_longitude += lng_resolution * column digit += 1 end end CodeArea.new(south_latitude, west_longitude, lat_resolution, lng_resolution) end |
#encode(latitude, longitude, code_length = 10) ⇒ String
Converts a latitude and longitude into a Open Location Code(Plus+Codes).
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/plus_codes/open_location_code.rb', line 44 def encode(latitude, longitude, code_length = 10) raise ArgumentError, "Invalid Open Location Code(Plus+Codes) length: #{code_length}" if invalid_length?(code_length) latitude = clip_latitude(latitude) longitude = normalize_longitude(longitude) latitude -= precision_by_length(code_length) if latitude == 90 lat = (latitude + 90).to_r lng = (longitude + 180).to_r digit = 0 code = '' while digit < code_length lat, lng = narrow_region(digit, lat, lng) digit, lat, lng = build_code(digit, code, lat, lng) code << SEPARATOR if (digit == SEPARATOR_POSITION) end digit < SEPARATOR_POSITION ? padded(code) : code end |
#full?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid full Open Location Code(Plus+Codes).
34 35 36 |
# File 'lib/plus_codes/open_location_code.rb', line 34 def full?(code) valid?(code) && !short?(code) end |
#recover_nearest(short_code, reference_latitude, reference_longitude) ⇒ String
Recovers a full Open Location Code(Plus+Codes) from a short code and a reference location.
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 |
# File 'lib/plus_codes/open_location_code.rb', line 112 def recover_nearest(short_code, reference_latitude, reference_longitude) return short_code if full?(short_code) raise ArgumentError, "Open Location Code(Plus+Codes) is not valid: #{short_code}" unless short?(short_code) ref_lat = clip_latitude(reference_latitude) ref_lng = normalize_longitude(reference_longitude) prefix_len = SEPARATOR_POSITION - short_code.index(SEPARATOR) code = prefix_by_reference(ref_lat, ref_lng, prefix_len) << short_code code_area = decode(code) area_range = precision_by_length(prefix_len) area_edge = area_range / 2 latitude = code_area.latitude_center latitude_diff = latitude - ref_lat if (latitude_diff > area_edge) latitude -= area_range elsif (latitude_diff < -area_edge) latitude += area_range end longitude = code_area.longitude_center longitude_diff = longitude - ref_lng if (longitude_diff > area_edge) longitude -= area_range elsif (longitude_diff < -area_edge) longitude += area_range end encode(latitude, longitude, code.length - SEPARATOR.length) end |
#short?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid short Open Location Code(Plus+Codes).
26 27 28 |
# File 'lib/plus_codes/open_location_code.rb', line 26 def short?(code) valid?(code) && code.index(SEPARATOR) < SEPARATOR_POSITION end |
#shorten(code, latitude, longitude) ⇒ String
Removes four, six or eight digits from the front of an Open Location Code(Plus+Codes) given a reference location.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/plus_codes/open_location_code.rb', line 152 def shorten(code, latitude, longitude) raise ArgumentError, "Open Location Code(Plus+Codes) is a valid full code: #{code}" unless full?(code) raise ArgumentError, "Cannot shorten padded codes: #{code}" unless code.index(PADDING).nil? code_area = decode(code) lat_diff = (latitude - code_area.latitude_center).abs lng_diff = (longitude - code_area.longitude_center).abs max_diff = [lat_diff, lng_diff].max [8, 6, 4].each do |removal_len| area_edge = precision_by_length(removal_len + 2) / 2 return code[removal_len..-1] if max_diff < area_edge end code.upcase end |
#valid?(code) ⇒ TrueClass, FalseClass
Determines if a string is a valid sequence of Open Location Code(Plus+Codes) characters.
15 16 17 18 19 20 |
# File 'lib/plus_codes/open_location_code.rb', line 15 def valid?(code) valid_length?(code) && valid_separator?(code) && valid_padding?(code) && valid_character?(code) end |