Class: OpenLocationCode::Encoder
- Inherits:
-
Object
- Object
- OpenLocationCode::Encoder
- Defined in:
- lib/open_location_code/encoder.rb
Overview
Encode latitude longitude to code
Instance Attribute Summary collapse
-
#code_length ⇒ Object
Returns the value of attribute code_length.
-
#latitude ⇒ Object
Returns the value of attribute latitude.
-
#longitude ⇒ Object
Returns the value of attribute longitude.
-
#original ⇒ Object
Returns the value of attribute original.
Instance Method Summary collapse
-
#clip_latitude(latitude) ⇒ Float
Clip a latitude into the range -90 to 90.
-
#compute_latitude_precision ⇒ Object
Compute the latitude precision value for a given code length.
-
#encode_grid(code_length) ⇒ Object
Encode a location using the grid refinement method into an OLC string.
-
#encode_pairs(code_length) ⇒ Object
Encode a location into a sequence of OLC lat/lng pairs.
-
#initialize(latitude, longitude, code_length) ⇒ Encoder
constructor
A new instance of Encoder.
-
#normalize_longitude(longitude) ⇒ Float
Normalize a longitude into the range -180 to 180, not including 180.
-
#process ⇒ String
Encode latitude and longitude.
Constructor Details
#initialize(latitude, longitude, code_length) ⇒ Encoder
Returns a new instance of Encoder.
8 9 10 11 12 13 14 15 16 |
# File 'lib/open_location_code/encoder.rb', line 8 def initialize(latitude, longitude, code_length) @code_length = code_length # Ensure that latitude and longitude are valid. @latitude = clip_latitude(latitude) @longitude = normalize_longitude(longitude) @original = { latitude: latitude, longitude: longitude } end |
Instance Attribute Details
#code_length ⇒ Object
Returns the value of attribute code_length.
6 7 8 |
# File 'lib/open_location_code/encoder.rb', line 6 def code_length @code_length end |
#latitude ⇒ Object
Returns the value of attribute latitude.
6 7 8 |
# File 'lib/open_location_code/encoder.rb', line 6 def latitude @latitude end |
#longitude ⇒ Object
Returns the value of attribute longitude.
6 7 8 |
# File 'lib/open_location_code/encoder.rb', line 6 def longitude @longitude end |
#original ⇒ Object
Returns the value of attribute original.
6 7 8 |
# File 'lib/open_location_code/encoder.rb', line 6 def original @original end |
Instance Method Details
#clip_latitude(latitude) ⇒ Float
Clip a latitude into the range -90 to 90.
24 25 26 |
# File 'lib/open_location_code/encoder.rb', line 24 def clip_latitude(latitude) [ 90, [-90, latitude].max ].min end |
#compute_latitude_precision ⇒ Object
Compute the latitude precision value for a given code length. Lengths <=
10 have the same precision for latitude and longitude, but lengths > 10
have different precisions due to the grid method having fewer columns than
rows.
52 53 54 55 56 57 58 |
# File 'lib/open_location_code/encoder.rb', line 52 def compute_latitude_precision if code_length <= 10 return 20**(code_length/-2.0 + 2).floor end (20**-3).to_f/GRID_ROWS**(code_length - 10) end |
#encode_grid(code_length) ⇒ Object
Encode a location using the grid refinement method into an OLC string.
The grid refinement method divides the area into a grid of 4x5, and uses a
single character to refine the area. This allows default accuracy OLC codes
to be refined with just a single character.
@param [Integer] code_length
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 |
# File 'lib/open_location_code/encoder.rb', line 125 def encode_grid(code_length) code = '' lat_place_value = GRID_SIZE_DEGREES lng_place_value = GRID_SIZE_DEGREES # Adjust latitude and longitude so they fall into positive ranges and # get the offset for the required places. adjusted_latitude = (latitude + LATITUDE_MAX) % lat_place_value adjusted_longitude = (longitude + LONGITUDE_MAX) % lng_place_value code_length.times do |i| # Work out the row and column. row = (adjusted_latitude / (lat_place_value.to_f / GRID_ROWS)).floor col = (adjusted_longitude / (lng_place_value.to_f / GRID_COLUMNS)).floor lat_place_value /= GRID_ROWS lng_place_value /= GRID_COLUMNS adjusted_latitude -= (row * lat_place_value) adjusted_longitude -= (col * lng_place_value) code += CODE_ALPHABET[row * GRID_COLUMNS + col] end return code end |
#encode_pairs(code_length) ⇒ Object
Encode a location into a sequence of OLC lat/lng pairs.
This uses pairs of characters (longitude and latitude in that order) to represent each step in a 20x20 grid. Each code, therefore, has 1/400th the area of the previous code.
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 |
# File 'lib/open_location_code/encoder.rb', line 71 def encode_pairs(code_length) code = '' # Adjust latitude and longitude so they fall into positive ranges. adjusted_latitude = latitude + LATITUDE_MAX adjusted_longitude = longitude + LONGITUDE_MAX # Count digits - can't use string length because it may include a separator # character. digit_count = 0 while (digit_count < code_length) do # Provides the value of digits in this place in decimal degrees. place_value = PAIR_RESOLUTIONS[(digit_count / 2.0).floor] # Do the latitude - gets the digit for this place and subtracts that for # the next digit. digit_value = (adjusted_latitude / place_value.to_f).floor adjusted_latitude -= (digit_value * place_value) code += CODE_ALPHABET[digit_value] digit_count += 1 # And do the longitude - gets the digit for this place and subtracts that # for the next digit. digit_value = (adjusted_longitude / place_value.to_f).floor adjusted_longitude -= (digit_value * place_value) code += CODE_ALPHABET[digit_value] digit_count += 1 # Should we add a separator here? if digit_count == SEPARATOR_POSITION && digit_count < code_length code += SEPARATOR end end if code.length < SEPARATOR_POSITION code += PADDING_CHARACTER*(SEPARATOR_POSITION - code.length + 1) end if code.length == SEPARATOR_POSITION code += SEPARATOR end return code end |
#normalize_longitude(longitude) ⇒ Float
Normalize a longitude into the range -180 to 180, not including 180.
34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/open_location_code/encoder.rb', line 34 def normalize_longitude(longitude) while (longitude < -180) do longitude += 360 end while (longitude >= 180) do longitude -= 360 end longitude end |
#process ⇒ String
Encode latitude and longitude
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/open_location_code/encoder.rb', line 157 def process if code_length < 2 || (code_length < SEPARATOR_POSITION && code_length % 2 == 1) raise OLCError, 'Invalid Open Location Code length' end # Latitude 90 needs to be adjusted to be just less, so the returned code # can also be decoded. if latitude == 90 self.latitude -= compute_latitude_precision end code = encode_pairs([code_length, PAIR_CODE_LENGTH].min) # If the requested length indicates we want grid refined codes. if code_length > PAIR_CODE_LENGTH code += encode_grid(code_length - PAIR_CODE_LENGTH) end code end |