A spatial analysis library written in Swift for native iOS, macOS, tvOS, watchOS, and Linux applications, ported from Turf.js.
Turf requires Xcode 12.0 or above and supports the following minimum deployment targets:
- iOS 10.0 and above
- macOS 10.12 (Sierra) and above
- tvOS 10.0 and above
- watchOS 3.0 and above
Alternatively, you can incorporate Turf into a command line tool without Xcode on any platform that Swift supports, including Linux.
If your project is written in Objective-C, you’ll need to write a compatibility layer between turf-swift and your Objective-C code. If your project is written in Objective-C++, you may be able to use spatial-algorithms as an alternative to Turf.
Although a stable release of this library is not yet available, prereleases are available for installation using any of the popular Swift dependency managers.
To install Turf using CocoaPods:
- Specify the following dependency in your Podfile:
pod 'Turf', '~> 2.4'
- Run
pod repo update
if you haven’t lately. - Run
pod install
and open the resulting Xcode workspace. - Add
import Turf
to any Swift file in your application target.
To install Turf using Carthage:
- Add the following dependency to your Cartfile:
github "mapbox/turf-swift" ~> 2.4
- Run
carthage bootstrap
. - Follow the rest of Carthage’s integration instructions. Your application target’s Embedded Frameworks should include Turf.framework.
- Add
import Turf
to any Swift file in your application target.
To install Turf using the Swift Package Manager, add the following package to the dependencies
in your Package.swift file:
.package(url: "https://github.com/mapbox/turf-swift.git", from: "2.4.0")
Then import Turf
in any Swift file in your module.
This work-in-progress port of Turf.js contains the following functionality:
Turf.js | Turf for Swift |
---|---|
turf-along#along | LineString.coordinateFromStart(distance:) |
turf-area#area | Polygon.area |
turf-bearing#bearing | CLLocationCoordinate2D.direction(to:) LocationCoordinate2D.direction(to:) on LinuxRadianCoordinate2D.direction(to:) |
turf-bezier-spline#bezierSpline | LineString.bezier(resolution:sharpness:) |
turf-boolean-point-in-polygon#booleanPointInPolygon | Polygon.contains(_:ignoreBoundary:) |
turf-center#center | Polygon.center |
turf-center-of-mass#centerOfMass | Polygon.centerOfMass |
turf-centroid#centroid | Polygon.centroid |
turf-circle#circle | Polygon(center:radius:vertices:) |
turf-destination#destination | CLLocationCoordinate2D.coordinate(at:facing:) LocationCoordinate2D.coordinate(at:facing:) on LinuxRadianCoordinate2D.coordinate(at:facing:) |
turf-distance#distance | CLLocationCoordinate2D.distance(to:) LocationCoordinate2D.distance(to:) on LinuxRadianCoordinate2D.distance(to:) |
turf-helpers#polygon | Polygon(_:) |
turf-helpers#lineString | LineString(_:) |
turf-helpers#degreesToRadians | CLLocationDegrees.toRadians() LocationDegrees.toRadians() on Linux |
turf-helpers#radiansToDegrees | CLLocationDegrees.toDegrees() LocationDegrees.toDegrees() on Linux |
turf-helpers#convertLength turf-helpers#convertArea |
Measurement.converted(to:) |
turf-length#length | LineString.distance(from:to:) |
turf-line-intersect#lineIntersect | LineString.intersections(with:) |
turf-line-slice#lineSlice | LineString.sliced(from:to:) |
turf-line-slice-along#lineSliceAlong | LineString.trimmed(from:to:) |
turf-midpoint#midpoint | mid(_:_:) |
turf-nearest-point-on-line#nearestPointOnLine | LineString.closestCoordinate(to:) |
turf-polygon-to-line#polygonToLine | LineString(_:) MultiLineString(_:) |
turf-simplify#simplify | LineString.simplify(tolerance:highestQuality:) LineString.simplified(tolerance:highestQuality:) |
turf-polygon-smooth#polygonSmooth | Polygon.smooth(iterations:) |
— | CLLocationDirection.difference(from:) LocationDirection.difference(from:) on Linux |
— | CLLocationDirection.wrap(min:max:) LocationDirection.wrap(min:max:) on Linux |
turf-swift also contains a GeoJSON encoder/decoder with support for Codable.
// Decode an unknown GeoJSON object.
let geojson = try JSONDecoder().decode(GeoJSONObject.self, from: data)
guard case let .feature(feature) = geojson,
case let .point(point) = feature.geometry else {
return
}
// Decode a known GeoJSON object.
let featureCollection = try JSONDecoder().decode(FeatureCollection.self, from: data)
// Initialize a Point feature and encode it as GeoJSON.
let coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 1)
let point = Point(coordinate)
let pointFeature = Feature(geometry: .point(point))
let data = try JSONEncoder().encode(pointFeature)
let json = String(data: data, encoding: .utf8)
print(json)
/*
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
1,
0
]
}
}
*/