This is a Swift library to solve geodesic problems on an ellipsoid model of the earth.
It wraps the C implementation of the geodesic routines from GeographicLib.
Licensed under the MIT/X11 License; see LICENSE.txt.
The algorithms are documented in
- C. F. F. Karney, Algorithms for geodesics, J. Geodesy 87(1), 43–55 (2013); Addenda.
- Library documentation: (coming soon)
- GeographicLib: https://geographiclib.sourceforge.io
- C implementation: https://github.com/geographiclib/geographiclib-c
The public API of this library is a WIP. It aims to be faithful to map directly to the underlying C libraries while being more idiomatically Swift. Be aware of potential breaking changes to the API until 1.0.0 and pin to specific minor versions if needed.
Add the following to your Package.swift
file:
import PackageDescription
let package = Package(
name: "MyPackage",
/* ... */
dependencies: [
.package(url: "https://github.com/scottrhoyt/geographiclib-swift.git", from: "0.1.0"),
],
/* ... */
targets: [
.target(
name: "MyPackage",
dependencies: [
.product(name: "GeographicLib", package: "geographiclib-swift")
]
)
]
/* ... */
)
import GeographicLib
// Create a geodesic calculator with WGS-84 ellipsoid (default)
let geodesic = Geodesic()
// Solve the direct problem: given a starting point, azimuth, and distance
let direct = geodesic.direct(
latitude: 40.64, // JFK Airport
longitude: -73.78,
azimuth: 45.0, // northeast
distance: 10_000_000 // 10,000 km
)
print("Destination: \(direct.latitude)°, \(direct.longitude)°")
// Solve the inverse problem: given two points, find distance and azimuths
let inverse = geodesic.inverse(
startLatitude: 40.64, // JFK Airport
startLongitude: -73.78,
endLatitude: 1.36, // Singapore Changi Airport
endLongitude: 103.99
)
print("Distance: \(inverse.distance) meters")
print("Initial azimuth: \(inverse.startAzimuth)°")
// Use GRS-80 ellipsoid
let grs80 = Geodesic(.grs80)
// Use a custom ellipsoid
let customEllipsoid = Ellipsoid(equatorialRadius: 6378000.0, flattening: 1.0/300.0)
let customGeodesic = Geodesic(customEllipsoid)
// Use a sphere for simplified calculations
let sphere = Geodesic(.sphere)
For efficient calculations of multiple points along a geodesic:
// Create a geodesic line
let line = geodesic.inverseLine(
latitude1: 40.64, longitude1: -73.78, // JFK
latitude2: 1.36, longitude2: 103.99 // Singapore
)
// Calculate waypoints
for i in 0...10 {
let fraction = Double(i) / 10.0
let position = line.position(distance: line.distance * fraction)
print("Waypoint \(i): \(position.latitude)°, \(position.longitude)°")
}
Calculate areas and perimeters of geodesic polygons:
// Simple polygon area calculation
let antarctica = [
(-72.9, -74), (-71.9, -102), (-74.9, -102), (-74.3, -131),
(-77.5, -163), (-77.4, 163), (-71.7, 172), (-65.9, 140),
(-65.7, 113), (-66.6, 88), (-66.9, 59), (-69.8, 25),
(-70.0, -4), (-71.0, -14), (-77.3, -33), (-77.9, -46), (-74.7, -61)
]
let (area, perimeter) = geodesic.polygonArea(coordinates: antarctica)
print("Antarctica area: \(area) m²")
print("Antarctica perimeter: \(perimeter) m")
// Using the Polygon type for more control
var polygon = Polygon()
polygon.addPoint(latitude: 0, longitude: 0)
polygon.addPoint(latitude: 0, longitude: 90)
polygon.addPoint(latitude: 90, longitude: 0)
let result = polygon.compute()
print("Triangle area: \(result.area!) m²")
- Direct geodesic problem: Given a starting point, azimuth, and distance, find the destination point
- Inverse geodesic problem: Given two points, find the distance and azimuths between them
- Geodesic lines: Efficiently compute multiple points along a geodesic
- Polygon areas: Calculate areas and perimeters of geodesic polygons
- Multiple ellipsoids: Support for WGS-84, GRS-80, custom ellipsoids, and spheres
- Swift 5.5 or later
- Platforms: macOS, iOS, tvOS, watchOS, Linux, Windows