Turf for Swift

📱iOS     🖥💻macOS     📺tvOS     ⌚️watchOS     Linux     Documentation     Carthage compatible     CocoaPods     SPM compatible    

A spatial analysis library written in Swift for native iOS, macOS, tvOS, watchOS, and Linux applications, ported from Turf.js.

Requirements

Turf requires Xcode 14.1 or above and supports the following minimum deployment targets:

  • iOS 11.0 and above
  • macOS 10.13 (High Sierra) and above
  • tvOS 11.0 and above
  • watchOS 4.0 and above
  • visionOS 1.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.

Installation

Releases are available for installation using any of the popular Swift dependency managers.

CocoaPods

To install Turf using CocoaPods:

  1. Specify the following dependency in your Podfile: rb pod 'Turf', '~> 2.8'
  2. Run pod repo update if you haven’t lately.
  3. Run pod install and open the resulting Xcode workspace.
  4. Add import Turf to any Swift file in your application target.

Carthage

To install Turf using Carthage:

  1. Add the following dependency to your Cartfile: github "mapbox/turf-swift" ~> 2.8
  2. Run carthage bootstrap.
  3. Follow the rest of Carthage’s integration instructions. Your application target’s Embedded Frameworks should include Turf.framework.
  4. Add import Turf to any Swift file in your application target.

Swift Package Manager

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.8.0")

Then import Turf in any Swift file in your module.

Available functionality

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 Linux
RadianCoordinate2D.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 Linux
RadianCoordinate2D.coordinate(at:facing:)
turf-distance#distance CLLocationCoordinate2D.distance(to:)
LocationCoordinate2D.distance(to:) on Linux
RadianCoordinate2D.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

GeoJSON

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
    ]
  }
}
*/

Well Known Text (WKT)

turf-swift contains a minimal WKT encoding/decoding support for geometries implementing WKTCodable protocol.

let wktString = "POINT(123.53 -12.12)"

// Decoding is done using an init method
let point = try? Point(wkt: wktString)
let geometry = try? Geometry(wkt: wktString)

print(point?.coordinates)

// ...

// Geometries then can be serialized using a property getter
let serializedWKTString = point?.wkt
print(serializedWKTString)