Coordinates and distances
PyWorldAtlas stores signed WGS84 latitude and longitude on every bundled capital and populated-place record. Exact lookup, friendly display helpers, and dependency-free great-circle calculations all work offline.
Look up coordinates
Constrain city lookups by country whenever a name may be shared:
>>> from pyworldatlas import Atlas
>>> atlas = Atlas()
>>> tokyo = atlas.city("Tokyo", country="Japan")
>>> tokyo.coordinates.as_tuple()
(35.6895, 139.69171)
>>> paris_coordinates = atlas.coordinates("Paris", country="FR")
>>> paris_coordinates.as_tuple()
(48.85341, 2.3488)
An unconstrained exact name that matches multiple stored cities raises
AmbiguousPlaceError instead of choosing silently.
String inputs are resolved as bundled city names, not country names.
first_country and second_country only disambiguate those city-name
strings. Pass Country objects for country distance.
Distance between places
>>> paris = atlas.city("Paris", country="France")
>>> round(atlas.distance_between(tokyo, paris))
9713
>>> round(atlas.distance_between(tokyo, paris, unit="mi"))
6035
>>> round(atlas.distance_between(
... "Tokyo", "Paris", first_country="JP", second_country="FR"
... ))
9713
unit accepts "km", "mi", or "nmi". Calculations use the
standard haversine formula and the WGS84 mean Earth radius. Results represent
surface great-circle distance, not road, rail, or flight-routing distance.
Country and model inputs
Country inputs use the selected primary capital. Capital and city objects use their own coordinates:
>>> japan = atlas.country("Japan")
>>> france = atlas.country("France")
>>> round(atlas.distance_between(japan, france))
9713
>>> round(atlas.distance_between(japan.capital, france.capital))
9713
An area without primary-capital coordinates raises
CapitalNotFoundError when used as a country input.
Raw latitude and longitude
Use Coordinate directly or pass (latitude, longitude)
tuples to the atlas helper:
>>> from pyworldatlas import Coordinate
>>> london = Coordinate(51.5074, -0.1278)
>>> paris_center = Coordinate(48.8566, 2.3522)
>>> round(london.distance_to(paris_center), 1)
343.6
>>> round(london.bearing_to(paris_center), 1)
148.1
>>> london.compass_direction_to(paris_center)
'SSE'
>>> midpoint = london.midpoint_to(paris_center)
>>> (round(midpoint.latitude, 4), round(midpoint.longitude, 4))
(50.1886, 1.1466)
>>> start = (51.5074, -0.1278)
>>> finish = (48.8566, 2.3522)
>>> round(atlas.distance_between(start, finish), 1)
343.6
>>> atlas.close()
Latitude must be from -90 through 90 and longitude from -180 through 180.
Invalid coordinates and unsupported units raise ValueError.
Initial bearing is undefined for coincident or antipodal coordinates, and a
unique spherical midpoint is undefined for antipodal coordinates; those cases
also raise ValueError.
Friendly coordinate labels
Decimal degrees are compact; degrees/minutes/seconds are useful for teaching how a coordinate is composed:
>>> tokyo_coordinates = Coordinate(35.6895, 139.6917)
>>> tokyo_coordinates.hemispheres
('N', 'E')
>>> tokyo_coordinates.format()
'35.6895° N, 139.6917° E'
>>> tokyo_coordinates.dms()
'35° 41′ 22.2″ N, 139° 41′ 30.1″ E'
compass_direction_to converts the initial bearing to a 4-, 8-, or 16-point
compass label. It describes the beginning of the same great-circle path and is
not a navigation instruction.
Country coordinates
country.capital_coordinates exposes the primary capital position when one
is available. Passing a Country to
atlas.distance_between uses that position. Country inputs therefore produce
capital-to-capital distances, not centroid distances.