OpenLocationCode (olc v0.1.0)

View Source

Convert locations to and from Open Location Code (Plus Code).

Plus Codes are short, 10-11 character codes that can be used instead of street addresses. The codes can be generated and decoded offline, and use a reduced character set that minimises the chance of codes including words.

Codes are able to be shortened relative to a nearby location. This means that in many cases, only four to seven characters of the code are needed. To recover the original code, the same location is not required, as long as a nearby location is provided.

Codes represent rectangular areas rather than points, and the longer the code, the smaller the area. A 10 character code represents a 13.5x13.5 meter area (at the equator). An 11 character code represents approximately a 2.8x3.5 meter area.

Examples

# Encode a location, default accuracy:
OpenLocationCode.encode(47.365590, 8.524997)
#=> {:ok, "8FVC9G8F+6X"}

# Encode a location using one stage of additional refinement:
OpenLocationCode.encode(47.365590, 8.524997, 11)
#=> {:ok, "8FVC9G8F+6XQ"}

# Decode a full code:
{:ok, code_area} = OpenLocationCode.decode("8FVC9G8F+6X")

# Attempt to trim the first characters from a code:
OpenLocationCode.shorten("8FVC9G8F+6X", 47.5, 8.5)
#=> {:ok, "9G8F+6X"}

# Recover the full code from a short code:
OpenLocationCode.recover_nearest("9G8F+6X", 47.4, 8.6)
#=> {:ok, "8FVC9G8F+6X"}

OpenLocationCode.recover_nearest("8F+6X", 47.4, 8.6)
#=> {:ok, "8FVC9G8F+6X"}

Summary

Functions

Clip a latitude into the range -90 to 90.

Decodes an Open Location Code into location coordinates.

Encode a location into an Open Location Code.

Encode a location using integer values into a code.

Determines if a code is a valid full Open Location Code.

Convert location in degrees into integer representations.

Normalize a longitude into the range -180 to 180, not including 180.

Recover the nearest matching full code to a specified location.

Determines if a code is a valid short code.

Remove characters from the start of an Open Location Code.

Determines if a code is valid.

Functions

clip_latitude(latitude)

Clip a latitude into the range -90 to 90.

decode(code)

Decodes an Open Location Code into location coordinates.

Returns a tuple with :ok and a CodeArea struct that includes the coordinates of the bounding box - the lower left, center and upper right. Returns an error tuple if the code is invalid or not a full code.

Examples

iex> OpenLocationCode.decode("8FVC9G8F+6X")
{:ok,
 %OpenLocationCode.CodeArea{
   latitude_lo: 47.3655,
   longitude_lo: 8.524875,
   latitude_hi: 47.36562499999999,
   longitude_hi: 8.525,
   latitude_center: 47.365562499999996,
   longitude_center: 8.5249375,
   code_length: 10
 }}

iex> OpenLocationCode.decode("invalid")
{:error, :invalid_code}

iex> OpenLocationCode.decode("9G8F+6X")  # short code
{:error, :full_code_expected}

encode(latitude, longitude, code_length \\ 10)

Encode a location into an Open Location Code.

Produces a code of the specified length, or the default length if no length is provided. The length determines the accuracy of the code. The default length is 10 characters.

Parameters

  • latitude - The latitude in degrees (must be between -90 and 90)
  • longitude - The longitude in degrees (must be between -180 and 180)
  • code_length - The desired length of the code (default: 10, max: 15)

Examples

iex> OpenLocationCode.encode(47.365590, 8.524997)
{:ok, "8FVC9G8F+6X"}

iex> OpenLocationCode.encode(47.365590, 8.524997, 11)
{:ok, "8FVC9G8F+6XQ"}

encode_integers(lat_val, lng_val, code_length)

Encode a location using integer values into a code.

This function takes pre-computed integer representations of latitude and longitude coordinates and generates an Open Location Code.

Examples

iex> OpenLocationCode.encode_integers(4736559000, 852499700, 10)
{:ok, "F7F6F367+WX"}

full?(code)

Determines if a code is a valid full Open Location Code.

Not all possible combinations of Open Location Code characters decode to valid latitude and longitude values. This checks that a code is valid and also that the latitude and longitude values are legal.

Examples

iex> OpenLocationCode.full?("8FVC9G8F+6X")
true

iex> OpenLocationCode.full?("9G8F+6X")  # short code
false

iex> OpenLocationCode.full?("invalid")
false

location_to_integers(latitude, longitude)

Convert location in degrees into integer representations.

This is an internal helper function that converts floating-point coordinates into integer values for processing.

Examples

iex> OpenLocationCode.location_to_integers(47.365590, 8.524997)
{:ok, {3434139750, 1544396775}}

normalize_longitude(longitude)

Normalize a longitude into the range -180 to 180, not including 180.

recover_nearest(code, reference_latitude, reference_longitude)

Recover the nearest matching full code to a specified location.

Given a short code of between four and seven characters, this recovers the nearest matching full code to the specified location.

If a full code is provided, it returns the code in proper capitalization.

Parameters

  • code - A short Open Location Code (or full code)
  • reference_latitude - Reference latitude in degrees
  • reference_longitude - Reference longitude in degrees

Examples

iex> OpenLocationCode.recover_nearest("9G8F+6X", 47.4, 8.6)
{:ok, "8FVC9G8F+6X"}

iex> OpenLocationCode.recover_nearest("8F+6X", 47.4, 8.6)
{:ok, "8FVCCJ8F+6X"}

# Full codes are returned as-is (but uppercased)
iex> OpenLocationCode.recover_nearest("8fvc9g8f+6x", 47.4, 8.6)
{:ok, "8FVC9G8F+6X"}

short?(code)

Determines if a code is a valid short code.

A short Open Location Code is a sequence created by removing four or more digits from an Open Location Code. It must include a separator character.

Examples

iex> OpenLocationCode.short?("9G8F+6X")
true

iex> OpenLocationCode.short?("8F+6X")
true

iex> OpenLocationCode.short?("8FVC9G8F+6X")  # full code
false

iex> OpenLocationCode.short?("invalid")
false

shorten(code, latitude, longitude)

Remove characters from the start of an Open Location Code.

This uses a reference location to determine how many initial characters can be removed from the OLC code. The closer the reference location is to the code's center, the more characters can be removed.

Returns an error if the code cannot be shortened (e.g., if it's not a full code, contains padding, or is too short).

Parameters

  • code - A full Open Location Code
  • latitude - Reference latitude in degrees
  • longitude - Reference longitude in degrees

Examples

iex> OpenLocationCode.shorten("8FVC9G8F+6X", 47.5, 8.5)
{:ok, "9G8F+6X"}

# Error cases
iex> OpenLocationCode.shorten("9G8F+6X", 47.5, 8.5)  # short code
{:error, :full_code_expected}

iex> OpenLocationCode.shorten("8FVC00+", 47.5, 8.5)  # padded code
{:error, :cannot_shorten_padded_codes}

valid?(code)

Determines if a code is valid.

To be valid, all characters must be from the Open Location Code character set with at most one separator. The separator can be in any even-numbered position up to the eighth digit.

Examples

iex> OpenLocationCode.valid?("8FVC9G8F+6X")
true

iex> OpenLocationCode.valid?("8FVC9G8F+6XQ")
true

iex> OpenLocationCode.valid?("invalid")
false

iex> OpenLocationCode.valid?("8FVC9G8F6X")  # missing separator
false