# LispPad Location

Library `(lisppad location)` implements procedures for geocoding and reverse geocoding and provides representations of locations (latitude, longitude, altitude) and places (structured representation of addresses).

## Locations

A location consists of a latitude, a longitude, and an optional altitude. Locations are represented as lists of two or three flonum values.

(location? obj) [procedure]

Returns `#t` if the given expression obj is a valid location; returns `#f` otherwise.

(location latitude longitude) [procedure]
(location latitude longitude altitude)

Creates a location for the given latitude, longitude, and altitude. This procedure fails with an error if any of the provided arguments are not flonum values.

(current-location) [procedure]

Returns the current device location. If a device location can’t be determined, the procedure returns `#f`. The procedure also returns `#f` if the user did not authorize the device to reveal the location to LispPad.

(location-latitude loc) [procedure]

Returns the latitude of location loc.

(location-longitude loc) [procedure]

Returns the longitude of location loc.

(location-altitude loc) [procedure]

Returns the altitude of location loc. Since altitudes are optional, procedure `location-altitude` returns `#f` if the altitude is undefined.

(location-distance loc1 loc2) [procedure]

Returns the distance between location loc1 and location loc2 in meters.

(location->timezone loc) [procedure]

Returns a timezone identifier (string) for location loc.

## Places

A place is a structured representation describing a place on Earth. Its main components are address components, but a place might also provide meta-information such as the timezone of the place or the ISO country code. Library `(lispkit date-time)` provides more functionality to deal with such meta-data. Places are represented as lists of one to ten strings in the following order:

1. ISO country code
2. Country
3. Region (a part of the country; e.g. State, Bundesland, Kanton, etc.)
4. Administrational region (a part of the region; e.g. County, Landkreis, etc.)
5. Postal code
6. City
7. Locality (a part of the city; e.g. District, Stadtteil, etc.)
8. Street
9. Street number
10. Time zone

Note that all components are optional. An optional component is represented as `#f`.

(place? obj) [procedure]

Returns `#t` if the given expression obj is a valid place; returns `#f` otherwise.

(place code) [procedure]
(place code country)
(place code country region)
(place code country region admin)
(place code country region admin zip)
(place code country region admin zip city)
(place code country region admin zip city locality)
(place code country region admin zip city locality street)
(place code country region admin zip city locality street nr)
(place code country region admin zip city locality street nr tz)

Returns a location for the given components of a place. Each component is either `#f` (= undefined) or a string.

(place-country-code pl) [procedure]

Returns the country code for place pl as a string or `#f` if the country code is undefined.

(place-country pl) [procedure]

Returns the country for place pl as a string or `#f` if the country is undefined.

(place-region pl) [procedure]

Returns the region for place pl as a string or `#f` if the region is undefined.

(place-admin pl) [procedure]

Returns the administrational region for place pl as a string or `#f` if the administrational region is undefined.

(place-postal-code pl) [procedure]

Returns the postal code for place pl as a string or `#f` if the postal code is undefined.

(place-city pl) [procedure]

Returns the city for place pl as a string or `#f` if the city is undefined.

(place-locality pl) [procedure]

Returns the locality for place pl as a string or `#f` if the locality is undefined.

(place-street pl) [procedure]

Returns the street for place pl as a string or `#f` if the street is undefined.

(place-street-number pl) [procedure]

Returns the street number for place pl as a string or `#f` if the street number is undefined.

(place-timezone pl) [procedure]

Returns the timezone for place pl as a string or `#f` if the timezone is undefined.

## Geocoding

(geocode obj) [procedure]
(geocode obj locale)

Returns a list of locations for the given place or address. obj is either a valid place representation or it is an address string. locale is a symbol representing a locale, which is used to interpret the given place or address. `geocode` signals an error if the geocoding operation fails (e.g. if there is no network access).

    (geocode "Brandschenkestrasse 110, Zürich" 'de_CH)
    ⇒ ((47.3654121 8.5247038))

(reverse-geocode loc) [procedure]
(reverse-geocode loc locale)
(reverse-geocode lat long)
(reverse-geocode lat long locale)

Returns a list of places for the given location. loc is a valid location. lat and long describe latitude and longitude as flonums directly. locale is a symbol representing a locale. It is used for the place representations returned by `reverse-geocode`.

    (reverse-geocode (location 47.36541 8.5247) 'en_US)
    ⇒ (("CH" "Switzerland" "Zürich" "Zürich"
        "8002" "Zürich" "Brunau"
        "Brandschenkestrasse" "110" "Europe/Zurich"))

(place->address pl) [procedure]

Formats a place as an address. For this operation to succeed, it is important that the country code of the place pl is set as it is used to determine the address format.

    (define pl (car (reverse-geocode (location 47.36541 8.5247) 'de_CH)))
    pl ⇒ (("CH" "Schweiz" "Zürich" "Zürich"
           "8002" "Zürich" "Brunau"
           "Brandschenkestrasse" "110" "Europe/Zurich"))
    (display (place->address pl))
    ⇒
    Brandschenkestrasse 110
    8002 Zürich
    Schweiz

(address->place str) [procedure]
(address->place str locale)

Parses the given address string str into a place (or potentially multiple possible places) and returns this as a list of places. locale is a symbol representing a locale. It is used for the place representations returned by `address->place`.

    (address->place "Brandschenkestrasse 110, Zürich")
    ⇒ (("CH" "Switzerland" "Zürich" "Zürich"
        "8002" "Zürich" "Brunau"
        "Brandschenkestrasse" "110" "Europe/Zurich"))