From 32f5833f058012589f5c137b2efe38400abb4c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 1 Oct 2021 13:46:14 -0700 Subject: [PATCH 1/4] Added Turf.js cross-references to documentation comments Also linked Turf.js functions in readme to Turf.js demonstration page. --- README.md | 53 +++++---- Sources/Turf/CoreLocation.swift | 18 ++- Sources/Turf/Geometries/LineString.swift | 104 +++++++++++------- Sources/Turf/Geometries/MultiLineString.swift | 2 + Sources/Turf/Geometries/Polygon.swift | 102 +++++++++++------ Sources/Turf/Turf.swift | 7 +- 6 files changed, 183 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 9e4c26f4..c8414417 100644 --- a/README.md +++ b/README.md @@ -67,34 +67,33 @@ Then `import Turf` in any Swift file in your module. This work-in-progress port of [Turf.js](https://github.com/Turfjs/turf/) contains the following functionality: -Turf.js | Turf-swift +Turf.js | Turf for Swift ----|---- -[turf-along](https://github.com/Turfjs/turf/tree/master/packages/turf-along/) | `LineString.coordinateFromStart(distance:)` -[turf-area](https://github.com/Turfjs/turf/blob/master/packages/turf-area/) | `Polygon.area` -[turf-bearing](https://turfjs.org/docs/#bearing) | `CLLocationCoordinate2D.direction(to:)`
`LocationCoordinate2D.direction(to:)` on Linux
`RadianCoordinate2D.direction(to:)` -[turf-bezier-spline](https://github.com/Turfjs/turf/tree/master/packages/turf-bezier-spline/) | `LineString.bezier(resolution:sharpness:)` -[turf-boolean-point-in-polygon](https://github.com/Turfjs/turf/tree/master/packages/turf-boolean-point-in-polygon) | `Polygon.contains(_:ignoreBoundary:)` -[turf-center](http://turfjs.org/docs/#center) | `Polygon.center` -[turf-center-of-mass](http://turfjs.org/docs/#centerOfMass) | `Polygon.centerOfMass` -[turf-centroid](http://turfjs.org/docs/#centroid) | `Polygon.centroid` -[turf-circle](https://turfjs.org/docs/#circle) | `Polygon(center:radius:vertices:)` | -[turf-destination](https://github.com/Turfjs/turf/tree/master/packages/turf-destination/) | `CLLocationCoordinate2D.coordinate(at:facing:)`
`LocationCoordinate2D.coordinate(at:facing:)` on Linux
`RadianCoordinate2D.coordinate(at:facing:)` -[turf-distance](https://github.com/Turfjs/turf/tree/master/packages/turf-distance/) | `CLLocationCoordinate2D.distance(to:)`
`LocationCoordinate2D.distance(to:)` on Linux
`RadianCoordinate2D.distance(to:)` -[turf-helpers#polygon](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/#polygon) | `Polygon(_:)` -[turf-helpers#lineString](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/#linestring) | `LineString(_:)` -[turf-helpers#degreesToRadians](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/#degreesToRadians) | `CLLocationDegrees.toRadians()`
`LocationDegrees.toRadians()` on Linux -[turf-helpers#radiansToDegrees](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/#radiansToDegrees) | `CLLocationDegrees.toDegrees()`
`LocationDegrees.toDegrees()` on Linux -[turf-helpers#convertLength](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers#convertlength)
[turf-helpers#convertArea](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers#convertarea) | `Measurement.converted(to:)` -[turf-length](https://github.com/Turfjs/turf/tree/master/packages/turf-length/) | `LineString.distance(from:to:)` -[turf-line-intersect](https://github.com/Turfjs/turf/tree/master/packages/turf-line-intersect/) | `intersection(_:_:)` -[turf-line-slice](https://github.com/Turfjs/turf/tree/master/packages/turf-line-slice/) | `LineString.sliced(from:to:)` -[turf-line-slice-along](https://github.com/Turfjs/turf/tree/master/packages/turf-line-slice-along/) | `LineString.trimmed(from:distance:)` -[turf-midpoint](https://github.com/Turfjs/turf/blob/master/packages/turf-midpoint/index.js) | `mid(_:_:)` -[turf-nearest-point-on-line](https://github.com/Turfjs/turf/tree/master/packages/turf-nearest-point-on-line/) | `LineString.closestCoordinate(to:)` -[turf-polygon-to-line](https://github.com/Turfjs/turf/tree/master/packages/turf-polygon-to-line/) | `LineString(_:)`
`MultiLineString(_:)`
`FeatureCollection(_:)` -[turf-simplify](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify) | `LineString.simplified(tolerance:highestQuality:)` -[turf-polygon-smooth](https://github.com/Turfjs/turf/tree/master/packages/turf-polygon-smooth) | `Polygon.smooth(iterations:)` -[turf-simplify](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify) | `Polygon.simplified(tolerance:highestQuality:)` +[turf-along#along](https://turfjs.org/docs/#along) | `LineString.coordinateFromStart(distance:)` +[turf-area#area](https://turfjs.org/docs/#area) | `Polygon.area` +[turf-bearing#bearing](https://turfjs.org/docs/#bearing) | `CLLocationCoordinate2D.direction(to:)`
`LocationCoordinate2D.direction(to:)` on Linux
`RadianCoordinate2D.direction(to:)` +[turf-bezier-spline#bezierSpline](https://turfjs.org/docs/#bezierSpline) | `LineString.bezier(resolution:sharpness:)` +[turf-boolean-point-in-polygon#booleanPointInPolygon](https://turfjs.org/docs/#booleanPointInPolygon) | `Polygon.contains(_:ignoreBoundary:)` +[turf-center#center](https://turfjs.org/docs/#center) | `Polygon.center` +[turf-center-of-mass#centerOfMass](https://turfjs.org/docs/#centerOfMass) | `Polygon.centerOfMass` +[turf-centroid#centroid](https://turfjs.org/docs/#centroid) | `Polygon.centroid` +[turf-circle#circle](https://turfjs.org/docs/#circle) | `Polygon(center:radius:vertices:)` | +[turf-destination#destination](https://turfjs.org/docs/#destination) | `CLLocationCoordinate2D.coordinate(at:facing:)`
`LocationCoordinate2D.coordinate(at:facing:)` on Linux
`RadianCoordinate2D.coordinate(at:facing:)` +[turf-distance#distance](https://turfjs.org/docs/#distance) | `CLLocationCoordinate2D.distance(to:)`
`LocationCoordinate2D.distance(to:)` on Linux
`RadianCoordinate2D.distance(to:)` +[turf-helpers#polygon](https://turfjs.org/docs/#polygon) | `Polygon(_:)` +[turf-helpers#lineString](https://turfjs.org/docs/#lineString) | `LineString(_:)` +[turf-helpers#degreesToRadians](https://turfjs.org/docs/#degreesToRadians) | `CLLocationDegrees.toRadians()`
`LocationDegrees.toRadians()` on Linux +[turf-helpers#radiansToDegrees](https://turfjs.org/docs/#radiansToDegrees) | `CLLocationDegrees.toDegrees()`
`LocationDegrees.toDegrees()` on Linux +[turf-helpers#convertLength](https://turfjs.org/docs/#convertLength)
[turf-helpers#convertArea](https://turfjs.org/docs/#convertArea) | `Measurement.converted(to:)` +[turf-length#length](https://turfjs.org/docs/#length) | `LineString.distance(from:to:)` +[turf-line-intersect#lineIntersect](https://turfjs.org/docs/#lineIntersect) | `intersection(_:_:)` +[turf-line-slice#lineSlice](https://turfjs.org/docs/#lineSlice) | `LineString.sliced(from:to:)` +[turf-line-slice-along#lineSliceAlong](https://turfjs.org/docs/#lineSliceAlong) | `LineString.trimmed(from:distance:)` +[turf-midpoint#midpoint](https://turfjs.org/docs/#midpoint) | `mid(_:_:)` +[turf-nearest-point-on-line#nearestPointOnLine](https://turfjs.org/docs/#nearestPointOnLine) | `LineString.closestCoordinate(to:)` +[turf-polygon-to-line#polygonToLine](https://turfjs.org/docs/#polygonToLine) | `LineString(_:)`
`MultiLineString(_:)` +[turf-simplify#simplify](https://turfjs.org/docs/#simplify) | `LineString.simplify(tolerance:highestQuality:)`
`LineString.simplified(tolerance:highestQuality:)` +[turf-polygon-smooth#polygonSmooth](https://turfjs.org/docs/#polygonSmooth) | `Polygon.smooth(iterations:)` — | `CLLocationDirection.difference(from:)`
`LocationDirection.difference(from:)` on Linux — | `CLLocationDirection.wrap(min:max:)`
`LocationDirection.wrap(min:max:)` on Linux diff --git a/Sources/Turf/CoreLocation.swift b/Sources/Turf/CoreLocation.swift index aabf50a7..d8cd2d8c 100644 --- a/Sources/Turf/CoreLocation.swift +++ b/Sources/Turf/CoreLocation.swift @@ -107,6 +107,8 @@ extension LocationDirection { extension LocationDegrees { /** Returns the direction in radians. + + This method is equivalent to the [`degreesToRadians`](https://turfjs.org/docs/#degreesToRadians) method of the turf-helpers package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/)). */ public func toRadians() -> LocationRadians { return self * .pi / 180.0 @@ -114,6 +116,8 @@ extension LocationDegrees { /** Returns the direction in degrees. + + This method is equivalent to the [`radiansToDegrees`](https://turfjs.org/docs/#radiansToDegrees) method of the turf-helpers package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/)). */ public func toDegrees() -> LocationDirection { return self * 180.0 / .pi @@ -198,7 +202,11 @@ extension LocationCoordinate2D: Equatable { return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude } - /// Returns the direction from the receiver to the given coordinate. + /** + Returns the direction from the receiver to the given coordinate. + + This method is equivalent to the [turf-bearing](https://turfjs.org/docs/#bearing) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-bearing/)). + */ public func direction(to coordinate: LocationCoordinate2D) -> LocationDirection { return RadianCoordinate2D(self).direction(to: RadianCoordinate2D(coordinate)).converted(to: .degrees).value } @@ -209,7 +217,11 @@ extension LocationCoordinate2D: Equatable { return coordinate(at: distance, facing: angle) } - /// Returns a coordinate a certain Haversine distance away in the given direction. + /** + Returns a coordinate a certain Haversine distance away in the given direction. + + This method is equivalent to the [turf-destination](https://turfjs.org/docs/#destination) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-destination/)). + */ public func coordinate(at distance: LocationDistance, facing direction: Measurement) -> LocationCoordinate2D { let radianCoordinate = RadianCoordinate2D(self).coordinate(at: distance / metersPerRadian, facing: direction) return LocationCoordinate2D(radianCoordinate) @@ -217,6 +229,8 @@ extension LocationCoordinate2D: Equatable { /** Returns the Haversine distance between two coordinates measured in degrees. + + This method is equivalent to the [turf-distance](https://turfjs.org/docs/#distance) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-distance/)). */ public func distance(to coordinate: LocationCoordinate2D) -> LocationDistance { return RadianCoordinate2D(self).distance(to: RadianCoordinate2D(coordinate)) * metersPerRadian diff --git a/Sources/Turf/Geometries/LineString.swift b/Sources/Turf/Geometries/LineString.swift index fcfd0d31..5e6a3871 100644 --- a/Sources/Turf/Geometries/LineString.swift +++ b/Sources/Turf/Geometries/LineString.swift @@ -13,6 +13,8 @@ public struct LineString: Equatable { /** Initializes a line string defined by given positions. + This initializer is equivalent to the [`lineString`](https://turfjs.org/docs/#lineString) function in the turf-helpers package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/)). + - parameter coordinates: The positions at which the line string is located. */ public init(_ coordinates: [LocationCoordinate2D]) { @@ -22,6 +24,8 @@ public struct LineString: Equatable { /** Initializes a line string coincident to the given linear ring. + This initializer is roughly equivalent to the [`polygon-to-line`](https://turfjs.org/docs/#polygonToLine) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-polygon-to-line/)), except that it accepts a linear ring instead of a full polygon. + - parameter ring: The linear ring coincident to the line string. */ public init(_ ring: Ring) { @@ -54,10 +58,13 @@ extension LineString: Codable { } extension LineString { - /// Returns a new `.LineString` based on bezier transformation of the input line. - /// - /// ported from https://github.com/Turfjs/turf/blob/1ea264853e1be7469c8b7d2795651c9114a069aa/packages/turf-bezier-spline/index.ts + /** + Returns the line string transformed into an approximation of a curve by applying a Bézier spline algorithm. + + This method is equivalent to the [turf-bezier-spline](https://turfjs.org/docs/#bezierSpline) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-bezier-spline/)). + */ public func bezier(resolution: Int = 10000, sharpness: Double = 0.85) -> LineString? { + // Ported from https://github.com/Turfjs/turf/blob/1ea264853e1be7469c8b7d2795651c9114a069aa/packages/turf-bezier-spline/index.ts let points = coordinates.map { SplinePoint(coordinate: $0) } @@ -70,7 +77,11 @@ extension LineString { return LineString(coords) } - /// Returns a `.LineString` along a `.LineString` within a distance from a coordinate. + /** + Returns the portion of the line string that begins at the given coordinate and extends the given distance along the line string. + + This method is roughly equivalent to the [turf-line-slice-along](https://turfjs.org/docs/#lineSliceAlong) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-line-slice-along/)), except that it accepts a starting position instead of a starting distance along the line string. + */ public func trimmed(from coordinate: LocationCoordinate2D, distance: LocationDistance) -> LineString? { let startVertex = closestCoordinate(to: coordinate) guard startVertex != nil && distance != 0 else { @@ -113,9 +124,9 @@ extension LineString { return LineString(vertices) } - /// `IndexedCoordinate` is a coordinate with additional information such as - /// the index from its position in the polyline and distance from the start - /// of the polyline. + /** + `IndexedCoordinate` is a coordinate with additional information such as the index from its position in the polyline and distance from the start of the polyline. + */ public struct IndexedCoordinate { /// The coordinate public let coordinate: Array.Element @@ -125,15 +136,20 @@ extension LineString { public let distance: LocationDistance } - /// Returns a coordinate along a `.LineString` at a certain distance from the start of the polyline. + /** + Returns a coordinate along a line string at a certain distance from the start of the polyline. + + This method is equivalent to the [turf-along](https://turfjs.org/docs/#along) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-along/)). + */ public func coordinateFromStart(distance: LocationDistance) -> LocationCoordinate2D? { return indexedCoordinateFromStart(distance: distance)?.coordinate } - /// Returns an indexed coordinate along a `.LineString` at a certain distance from the start of the polyline. - /// - /// Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-along/index.js + /** + Returns an indexed coordinate along a line string at a certain distance from the start of the polyline. + */ public func indexedCoordinateFromStart(distance: LocationDistance) -> IndexedCoordinate? { + // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-along/index.js var traveled: LocationDistance = 0 guard let firstCoordinate = coordinates.first else { @@ -166,10 +182,13 @@ extension LineString { } - /// Returns the distance along a slice of a `.LineString` with the given endpoints. - /// - /// Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js + /** + Returns the distance along a slice of the line string with the given endpoints. + + If the `start` and `end` arguments are unspecified, this method is equivalent to the [turf-length](https://turfjs.org/docs/#length) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-length/)). + */ public func distance(from start: LocationCoordinate2D? = nil, to end: LocationCoordinate2D? = nil) -> LocationDistance? { + // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js guard !coordinates.isEmpty else { return nil } guard let slicedCoordinates = sliced(from: start, to: end)?.coordinates else { @@ -180,10 +199,13 @@ extension LineString { return zippedCoordinates.map { $0.distance(to: $1) }.reduce(0, +) } - /// Returns a subset of the `.LineString` between given coordinates. - /// - /// Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js + /** + Returns a subset of the line string between two given coordinates. + + This method is equivalent to the [turf-line-slice](https://turfjs.org/docs/#lineSlice) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-line-slice/)). + */ public func sliced(from start: LocationCoordinate2D? = nil, to end: LocationCoordinate2D? = nil) -> LineString? { + // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js guard !coordinates.isEmpty else { return nil } let startVertex = (start != nil ? closestCoordinate(to: start!) : nil) ?? IndexedCoordinate(coordinate: coordinates.first!, index: 0, distance: 0) @@ -204,12 +226,15 @@ extension LineString { return LineString(coords) } - /// Returns the geographic coordinate along the `.LineString` that is closest to the given coordinate as the crow flies. - /// The returned coordinate may not correspond to one of the polyline’s vertices, but it always lies along the polyline. - /// - /// Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-point-on-line/index.js - + /** + Returns the geographic coordinate along the line string that is closest to the given coordinate as the crow flies. + + The returned coordinate may not correspond to one of the polyline’s vertices, but it always lies along the polyline. + + This method is equivalent to the [turf-nearest-point-on-line](https://turfjs.org/docs/#nearestPointOnLine) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-nearest-point-on-line/)). + */ public func closestCoordinate(to coordinate: LocationCoordinate2D) -> IndexedCoordinate? { + // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-point-on-line/index.js guard let startCoordinate = coordinates.first else { return nil } guard coordinates.count > 1 else { @@ -253,15 +278,17 @@ extension LineString { return closestCoordinate } - /// Returns a copy of the LineString with the Ramer–Douglas–Peucker algorithm applied to it. - /// - /// tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point - /// and the simplified point. Higher tolerance values results in higher simplification. - /// - /// highestQuality: Excludes distance-based preprocessing step which leads to highest quality simplification. High quality simplification runs considerably slower so consider how much precision is needed in your application. - /// - /// Ported from https://github.com/Turfjs/turf/blob/master/packages/turf-simplify/lib/simplify.js + /** + Returns a copy of the line string simplified using the Ramer–Douglas–Peucker algorithm. + + This method is equivalent to the [turf-simplify](https://turfjs.org/docs/#simplify) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify/)). + + - parameter tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point and the simplified point. A higher tolerance value results in higher simplification. + - parameter highestQuality: Excludes the distance-based preprocessing step that leads to highest-quality simplification. High-quality simplification runs considerably slower, so consider how much precision is needed in your application. + - returns: A simplified line string. + */ public func simplified(tolerance: Double = 1.0, highestQuality: Bool = false) -> LineString { + // Ported from https://github.com/Turfjs/turf/blob/4e8342acb1dbd099f5e91c8ee27f05fb2647ee1b/packages/turf-simplify/lib/simplify.js guard coordinates.count > 2 else { return LineString(coordinates) } var copy = LineString(coordinates) @@ -269,15 +296,16 @@ extension LineString { return copy } - /// Mutates the LineString into a simplified version using the Ramer–Douglas–Peucker algorithm. - /// - /// tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point - /// and the simplified point. Higher tolerance values results in higher simplification. - /// - /// highestQuality: Excludes distance-based preprocessing step which leads to highest quality simplification. High quality simplification runs considerably slower so consider how much precision is needed in your application. - /// - /// Ported from https://github.com/Turfjs/turf/blob/master/packages/turf-simplify/lib/simplify.js + /** + Simplifies the line string in place using the Ramer–Douglas–Peucker algorithm. + + This method is nearly equivalent to the [turf-simplify](https://turfjs.org/docs/#simplify) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify/)), except that it mutates the line string it is called on. + + - parameter tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point and the simplified point. A higher tolerance value results in higher simplification. + - parameter highestQuality: Excludes the distance-based preprocessing step that leads to highest-quality simplification. High-quality simplification runs considerably slower, so consider how much precision is needed in your application. + */ public mutating func simplify(tolerance: Double = 1.0, highestQuality: Bool = false) { + // Ported from https://github.com/Turfjs/turf/blob/4e8342acb1dbd099f5e91c8ee27f05fb2647ee1b/packages/turf-simplify/lib/simplify.js coordinates = Simplifier.simplify(coordinates, tolerance: tolerance, highestQuality: highestQuality) } } diff --git a/Sources/Turf/Geometries/MultiLineString.swift b/Sources/Turf/Geometries/MultiLineString.swift index db3d87ec..d393ad2a 100644 --- a/Sources/Turf/Geometries/MultiLineString.swift +++ b/Sources/Turf/Geometries/MultiLineString.swift @@ -22,6 +22,8 @@ public struct MultiLineString: Equatable { /** Initializes a multi–line string coincident to the given polygon’s linear rings. + This initializer is equivalent to the [`polygon-to-line`](https://turfjs.org/docs/#polygonToLine) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-polygon-to-line/)). + - parameter polygon: The polygon whose linear rings are coincident to the multi–line string. */ public init(_ polygon: Polygon) { diff --git a/Sources/Turf/Geometries/Polygon.swift b/Sources/Turf/Geometries/Polygon.swift index 84033e63..867462e3 100644 --- a/Sources/Turf/Geometries/Polygon.swift +++ b/Sources/Turf/Geometries/Polygon.swift @@ -13,6 +13,8 @@ public struct Polygon: Equatable { /** Initializes a polygon defined by the given positions. + This initializer is equivalent to the [`polygon`](https://turfjs.org/docs/#polygon) function in the turf-helpers package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-helpers/)). + - parameter coordinates: The positions at which the polygon is located. Each nested array corresponds to one linear ring. */ public init(_ coordinates: [[LocationCoordinate2D]]) { @@ -32,6 +34,8 @@ public struct Polygon: Equatable { /** Initializes a polygon as a given center coordinate with a given number of vertices, as a means to approximate a circle. + + This initializer is equivalent to the [turf-circle](https://turfjs.org/docs/#circle) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-circle/)). - Parameter center: The center coordinate for the polygon. - Parameter radius: The radius of the polygon, measured in meters. @@ -89,21 +93,29 @@ extension Polygon { } } - /// An area of current `Polygon` - /// - /// Ported from https://github.com/Turfjs/turf/blob/a94151418cb969868fdb42955a19a133512da0fd/packages/turf-area/index.js + /** + The polygon’s area. + + This property is equivalent to the [turf-area](https://turfjs.org/docs/#area) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-area/)). + */ public var area: Double { + // Ported from https://github.com/Turfjs/turf/blob/a94151418cb969868fdb42955a19a133512da0fd/packages/turf-area/index.js return abs(outerRing.area) - innerRings .map { abs($0.area) } .reduce(0, +) } - /// Determines if the given coordinate falls within the polygon and outside of its interior rings. - /// The optional parameter `ignoreBoundary` will result in the method returning true if the given coordinate - /// lies on the boundary line of the polygon or its interior rings. - /// - ///Ported from: https://github.com/Turfjs/turf/blob/e53677b0931da9e38bb947da448ee7404adc369d/packages/turf-boolean-point-in-polygon/index.ts#L31-L75 + /** + Returns whether the given coordinate falls within the polygon and outside of its interior rings. + + This method is equivalent to the [turf-boolean-point-in-polygon](https://turfjs.org/docs/#booleanPointInPolygon) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-boolean-point-in-polygon/)). + + - parameter coordinate: The coordinate to test for containment. + - parameter ignoreBoundary: Consider the coordinate to fall within the polygon even if it lies directly on one of the polygon’s linear rings. + - returns: True if the coordinate falls within the polygon; false otherwise. + */ public func contains(_ coordinate: LocationCoordinate2D, ignoreBoundary: Bool = false) -> Bool { + // Ported from https://github.com/Turfjs/turf/blob/e53677b0931da9e38bb947da448ee7404adc369d/packages/turf-boolean-point-in-polygon/index.ts#L31-L75 guard outerRing.contains(coordinate, ignoreBoundary: ignoreBoundary) else { return false } @@ -115,11 +127,15 @@ extension Polygon { return true } - /// Smooths a `Polygon`. Based on [Chaikin's algorithm](http://graphics.cs.ucdavis.edu/education/CAGDNotes/Chaikins-Algorithm/Chaikins-Algorithm.html). - /// Warning: may create degenerate polygons. - /// - /// Ported from https://github.com/Turfjs/turf/blob/402716a29f6ae16bf3d0220e213e5380cc5a50c4/packages/turf-polygon-smooth/index.js + /** + Returns the polygon with corners smoothed out using [Chaikin’s algorithm](https://www.cs.unc.edu/~dm/UNC/COMP258/LECTURES/Chaikins-Algorithm.pdf). + + This method is equivalent to the [turf-polygon-smooth](https://turfjs.org/docs/#polygonSmooth) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-polygon-smooth/)). + + - note: The returned polygon may be a degenerate polygon. + */ public func smooth(iterations: Int = 3) -> Polygon { + // Ported from https://github.com/Turfjs/turf/blob/402716a29f6ae16bf3d0220e213e5380cc5a50c4/packages/turf-polygon-smooth/index.js var poly = self var tempOutput: [[LocationCoordinate2D]] = [[]]; var outCoords: [[LocationCoordinate2D]] = [[]]; @@ -179,29 +195,32 @@ extension Polygon { }) } - /// Returns a copy of the Polygon with the Ramer–Douglas–Peucker algorithm applied to it. - /// - /// tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point - /// and the simplified point. Higher tolerance values results in higher simplification. - /// - /// highestQuality: Excludes distance-based preprocessing step which leads to highest quality simplification. High quality simplification runs considerably slower so consider how much precision is needed in your application. - /// - /// Ported from https://github.com/Turfjs/turf/blob/master/packages/turf-simplify/lib/simplify.js + /** + Returns a copy of the polygon simplified using the Ramer–Douglas–Peucker algorithm. + + This method is equivalent to the [turf-simplify](https://turfjs.org/docs/#simplify) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify/)). + + - parameter tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point and the simplified point. A higher tolerance value results in higher simplification. + - parameter highestQuality: Excludes the distance-based preprocessing step that leads to highest-quality simplification. High-quality simplification runs considerably slower, so consider how much precision is needed in your application. + - returns: A simplified polygon. + */ public func simplified(tolerance: Double = 1.0, highestQuality: Bool = false) -> Polygon { + // Ported from https://github.com/Turfjs/turf/blob/89505bf5df83dfde95a96de7c9abcdfd22ce5f63/packages/turf-simplify/lib/simplify.js var copy = Polygon(coordinates) copy.simplify(tolerance: tolerance, highestQuality: highestQuality) return copy } - /// Mutates the Polygon into a simplified version using the Ramer–Douglas–Peucker algorithm. - /// - /// tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point - /// and the simplified point. Higher tolerance values results in higher simplification. - /// - /// highestQuality: Excludes distance-based preprocessing step which leads to highest quality simplification. High quality simplification runs considerably slower so consider how much precision is needed in your application. - /// - /// Ported from https://github.com/Turfjs/turf/blob/master/packages/turf-simplify/lib/simplify.js + /** + Simplifies the polygon in place using the Ramer–Douglas–Peucker algorithm. + + This method is nearly equivalent to the [turf-simplify](https://turfjs.org/docs/#simplify) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-simplify/)), except that it mutates the polygon it is called on. + + - parameter tolerance: Controls the level of simplification by specifying the maximum allowed distance between the original line point and the simplified point. A higher tolerance value results in higher simplification. + - parameter highestQuality: Excludes the distance-based preprocessing step that leads to highest-quality simplification. High-quality simplification runs considerably slower, so consider how much precision is needed in your application. + */ public mutating func simplify(tolerance: Double = 1.0, highestQuality: Bool = false) { + // Ported from https://github.com/Turfjs/turf/blob/89505bf5df83dfde95a96de7c9abcdfd22ce5f63/packages/turf-simplify/lib/simplify.js coordinates = coordinates.map { ring in guard ring.count > 3 else { return ring } @@ -241,9 +260,13 @@ extension Polygon { ) } - /// Calculates the absolute centre (of the bounding box). + /** + Calculates the absolute center of the bounding box. + + This property is equivalent to the [turf-center](https://turfjs.org/docs/#center) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-center/)). + */ public var center: LocationCoordinate2D? { - // This implementation is a port of: https://github.com/Turfjs/turf/blob/master/packages/turf-center/index.ts + // This implementation is a port of: https://github.com/Turfjs/turf/blob/89505bf5df83dfde95a96de7c9abcdfd22ce5f63/packages/turf-center/index.ts return BoundingBox(from: outerRing.coordinates) .map { .init( latitude: ($0.southWest.latitude + $0.northEast.latitude) / 2, @@ -251,10 +274,15 @@ extension Polygon { ) } } - /// Calculates the centroid using the mean of all vertices. - /// This lessens the effect of small islands and artifacts when calculating the centroid of a set of polygons. + /** + Calculates the centroid using the mean of all vertices. + + Compared to `center` and `centerOfMass`, the centroid is less affected by small islands and artifacts. + + This property is equivalent to the [turf-centroid](https://turfjs.org/docs/#centroid) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-centroid/)). + */ public var centroid: LocationCoordinate2D? { - // This implementation is a port of: https://github.com/Turfjs/turf/blob/master/packages/turf-centroid/index.ts + // Ported from https://github.com/Turfjs/turf/blob/89505bf5df83dfde95a96de7c9abcdfd22ce5f63/packages/turf-centroid/index.ts let coordinates = outerRing.coordinates.dropLast() guard coordinates.count > 0 else { return nil } @@ -270,9 +298,13 @@ extension Polygon { ).normalized } - /// Calculates the [center of mass](https://en.wikipedia.org/wiki/Center_of_mass) using this formula: [Centroid of Polygon](https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon). + /** + Calculates the [center of mass](https://en.wikipedia.org/wiki/Center_of_mass) using the [centroid of polygon](https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon) formula. + + This property is equivalent to the [turf-center-of-mass](https://turfjs.org/docs/#centerOfMass) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-center-of-mass/)). + */ public var centerOfMass: LocationCoordinate2D? { - // This implementation is a port of: https://github.com/Turfjs/turf/blob/master/packages/turf-center-of-mass/index.ts + // Ported from https://github.com/Turfjs/turf/blob/89505bf5df83dfde95a96de7c9abcdfd22ce5f63/packages/turf-center-of-mass/index.ts // First, we neutralize the feature (set it around coordinates [0,0]) to prevent rounding errors // We take any point to translate all the points around 0 diff --git a/Sources/Turf/Turf.swift b/Sources/Turf/Turf.swift index c55426fe..8129d7a1 100644 --- a/Sources/Turf/Turf.swift +++ b/Sources/Turf/Turf.swift @@ -7,10 +7,13 @@ let metersPerRadian: LocationDistance = 6_373_000.0 // WGS84 equatorial radius as specified by the International Union of Geodesy and Geophysics let equatorialRadius: LocationDistance = 6_378_137 +/// A segment between two positions in a `LineString` geometry or `Ring`. public typealias LineSegment = (LocationCoordinate2D, LocationCoordinate2D) /** Returns the intersection of two line segments. + + This function is roughly equivalent to the [turf-line-intersect](https://turfjs.org/docs/#lineIntersect) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-line-intersect/)), except that it only accepts individual line segments instead of whole line strings. */ public func intersection(_ line1: LineSegment, _ line2: LineSegment) -> LocationCoordinate2D? { // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-point-on-line/index.js, in turn adapted from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/ @@ -39,7 +42,9 @@ public func intersection(_ line1: LineSegment, _ line2: LineSegment) -> Location } /** - Returns the point midway between two coordinates measured in degrees + Returns the point midway between two coordinates measured in degrees. + + This function is equivalent to the [turf-midpoint](https://turfjs.org/docs/#midpoint) package of Turf.js ([source code](https://github.com/Turfjs/turf/tree/master/packages/turf-midpoint/)). */ public func mid(_ coord1: LocationCoordinate2D, _ coord2: LocationCoordinate2D) -> LocationCoordinate2D { let dist = coord1.distance(to: coord2) From a77381ac870698c6f607aeb7fac1128ffb36cfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 1 Oct 2021 14:05:36 -0700 Subject: [PATCH 2/4] Added docset generation script --- docs/jazzy.yml | 6 ++++++ scripts/document.sh | 39 +++++++++++++++++++++++++++++++++++++++ scripts/update-version.sh | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 docs/jazzy.yml create mode 100755 scripts/document.sh diff --git a/docs/jazzy.yml b/docs/jazzy.yml new file mode 100644 index 00000000..5f0103da --- /dev/null +++ b/docs/jazzy.yml @@ -0,0 +1,6 @@ +module: Turf +author: Mapbox +title: Turf for Swift +author_url: https://github.com/mapbox/turf-swift/ +github_url: https://github.com/mapbox/turf-swift +copyright: '© 2014–2021 [Mapbox](https://www.mapbox.com/). See [license](https://github.com/mapbox/turf-swift/blob/main/LICENSE.md) for more details.' diff --git a/scripts/document.sh b/scripts/document.sh new file mode 100755 index 00000000..8ebc9965 --- /dev/null +++ b/scripts/document.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -e +set -o pipefail +set -u + +if [ -z `which jazzy` ]; then + echo "Installing jazzy…" + gem install jazzy + if [ -z `which jazzy` ]; then + echo "Unable to install jazzy." + exit 1 + fi +fi + + +OUTPUT=${OUTPUT:-documentation} + +BRANCH=$( git describe --tags --match=v*.*.* --abbrev=0 ) +SHORT_VERSION=$( echo ${BRANCH} | sed 's/^v//' ) +RELEASE_VERSION=$( echo ${SHORT_VERSION} | sed -e 's/-.*//' ) +MINOR_VERSION=$( echo ${SHORT_VERSION} | grep -Eo '^\d+\.\d+' ) + +rm -rf ${OUTPUT} +mkdir -p ${OUTPUT} + +#cp -r docs/img "${OUTPUT}" + +jazzy \ + --config docs/jazzy.yml \ + --sdk macosx \ + --module-version ${SHORT_VERSION} \ + --github-file-prefix "https://github.com/mapbox/mapbox-directions-swift/tree/${BRANCH}" \ + --readme README.md \ + --root-url "https://mapbox.github.io/turf-swift/${RELEASE_VERSION}/" \ + --output ${OUTPUT} \ + --build-tool-arguments CODE_SIGN_IDENTITY=,CODE_SIGNING_REQUIRED=NO,CODE_SIGNING_ALLOWED=NO + +echo $SHORT_VERSION > $OUTPUT/latest_version diff --git a/scripts/update-version.sh b/scripts/update-version.sh index 07ad3b85..72f2fed4 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -41,4 +41,4 @@ fi step "Updating copyright year to ${YEAR}…" -sed -i '' -E "s/© ([0-9]{4})[–-][0-9]{4}/© \\1–${YEAR}/g" LICENSE.md +sed -i '' -E "s/© ([0-9]{4})[–-][0-9]{4}/© \\1–${YEAR}/g" LICENSE.md docs/jazzy.yml From 422cfa2708286648ef94975dc3d81cfe8c41f81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 1 Oct 2021 16:57:48 -0700 Subject: [PATCH 3/4] Added documentation badge to readme --- README.md | 1 + scripts/update-version.sh | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index c8414417..13f4ad8e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ 📺[![tvOS](https://app.bitrise.io/app/0b037542c2395ffb/status.svg?token=yOtMqbu-5bj8grB1Jmoefg)](https://www.bitrise.io/app/0b037542c2395ffb)     ⌚️[![watchOS](https://app.bitrise.io/app/0d4d611f02295183/status.svg?token=NiLB_E_0IvYYqV4Mj973TQ)](https://www.bitrise.io/app/0d4d611f02295183)     Linux[![](https://api.travis-ci.com/mapbox/turf-swift.svg?branch=main)](https://travis-ci.com/mapbox/turf-swift)     +[![](https://mapbox.github.io/turf-swift/1.2.0/badge.svg)](https://mapbox.github.io/turf-swift/)     [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)     [![CocoaPods](https://img.shields.io/cocoapods/v/Turf.svg)](http://cocoadocs.org/docsets/Turf/)     [![SPM compatible](https://img.shields.io/badge/SPM-compatible-4BC51D.svg?style=flat)](https://swift.org/package-manager/)     diff --git a/scripts/update-version.sh b/scripts/update-version.sh index 72f2fed4..e8ca9d27 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -39,6 +39,12 @@ elif [[ $SHORT_VERSION != $SEM_VERSION ]]; then sed -i '' -E "s/:tag => 'v[^']+'/:tag => 'v${SEM_VERSION}'/g; s/\"mapbox\/turf-swift\" \"v[^\"]+\"/\"mapbox\/turf-swift\" \"v${SEM_VERSION}\"/g; s/\.exact\(\"*[^\"]+/.exact(\"${SEM_VERSION}/g" README.md fi +# Skip updating the documentation badge for prereleases. +if [[ $SHORT_VERSION == $SEM_VERSION ]]; then + step "Updating readmes to version ${SEM_VERSION}…" + sed -i '' -E "s/turf-swift\/${MINOR_VERSION}\/badge.svg/g; s/turf-swift\/${SEM_VERSION}\/badge.svg/g" README.md +fi + step "Updating copyright year to ${YEAR}…" sed -i '' -E "s/© ([0-9]{4})[–-][0-9]{4}/© \\1–${YEAR}/g" LICENSE.md docs/jazzy.yml From eeab0ae29c3a491ba3d75db25aba204c0d5d3533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 1 Oct 2021 22:19:16 -0700 Subject: [PATCH 4/4] Documented more public symbols --- Sources/Turf/Feature.swift | 14 ++++++++++++++ Sources/Turf/FeatureCollection.swift | 8 +++++++- Sources/Turf/Geometries/MultiPolygon.swift | 14 +++++++------- Sources/Turf/RadianCoordinate2D.swift | 20 ++++++++++++++++++-- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/Sources/Turf/Feature.swift b/Sources/Turf/Feature.swift index a5236497..0af1dd80 100644 --- a/Sources/Turf/Feature.swift +++ b/Sources/Turf/Feature.swift @@ -7,10 +7,24 @@ import CoreLocation A [Feature object](https://datatracker.ietf.org/doc/html/rfc7946#section-3.2) represents a spatially bounded thing. */ public struct Feature: Equatable { + /** + A string or number that commonly identifies the feature in the context of a data set. + + Turf does not guarantee that the feature is unique; however, a data set may make such a guarantee. + */ public var identifier: FeatureIdentifier? + + /// Arbitrary, JSON-compatible attributes to associate with the feature. public var properties: JSONObject? + + /// The geometry at which the feature is located. public var geometry: Geometry? + /** + Initializes a feature located at the given geometry. + + - parameter geometry: The geometry at which the feature is located. + */ public init(geometry: Geometry?) { self.geometry = geometry } diff --git a/Sources/Turf/FeatureCollection.swift b/Sources/Turf/FeatureCollection.swift index 0213d6d1..5d789499 100644 --- a/Sources/Turf/FeatureCollection.swift +++ b/Sources/Turf/FeatureCollection.swift @@ -4,8 +4,14 @@ import Foundation A [FeatureCollection object](https://datatracker.ietf.org/doc/html/rfc7946#section-3.3) is a collection of Feature objects. */ public struct FeatureCollection: Equatable { - public var features: Array = [] + /// The features that the collection contains. + public var features: [Feature] = [] + /** + Initializes a feature collection containing the given features. + + - parameter features: The features that the collection contains. + */ public init(features: [Feature]) { self.features = features } diff --git a/Sources/Turf/Geometries/MultiPolygon.swift b/Sources/Turf/Geometries/MultiPolygon.swift index 14bf40d7..10eec50c 100644 --- a/Sources/Turf/Geometries/MultiPolygon.swift +++ b/Sources/Turf/Geometries/MultiPolygon.swift @@ -10,6 +10,13 @@ public struct MultiPolygon: Equatable { /// The positions at which the multipolygon is located. Each nested array corresponds to one polygon. public var coordinates: [[[LocationCoordinate2D]]] + /// The polygon geometries that conceptually form the multipolygon. + public var polygons: [Polygon] { + return coordinates.map { (coordinates) -> Polygon in + return Polygon(coordinates) + } + } + /** Initializes a multipolygon defined by the given positions. @@ -56,13 +63,6 @@ extension MultiPolygon: Codable { } extension MultiPolygon { - - public var polygons: [Polygon] { - return coordinates.map { (coordinates) -> Polygon in - return Polygon(coordinates) - } - } - /** * Determines if the given coordinate falls within any of the polygons. * The optional parameter `ignoreBoundary` will result in the method returning true if the given coordinate diff --git a/Sources/Turf/RadianCoordinate2D.swift b/Sources/Turf/RadianCoordinate2D.swift index 424f4bcf..25a80e0e 100644 --- a/Sources/Turf/RadianCoordinate2D.swift +++ b/Sources/Turf/RadianCoordinate2D.swift @@ -3,22 +3,38 @@ import Foundation import CoreLocation #endif +/// A latitude or longitude measured in radians, as opposed to `LocationDegrees`, which is measured in degrees of arc. public typealias LocationRadians = Double + +/// A difference in latitude or longitude measured in radians, as opposed to `CLLocationDegrees`, which is used by some libraries to represent a similar distance measured in degrees of arc. public typealias RadianDistance = Double /** - A `RadianCoordinate2D` is a coordinate represented in radians as opposed to - `LocationCoordinate2D` which is represented in latitude and longitude. + A coordinate pair measured in radians, as opposed to `LocationCoordinate2D`, which is measured in degrees of arc. */ public struct RadianCoordinate2D { + /// The latitude measured in radians. private(set) var latitude: LocationRadians + + /// The longitude measured in radians. private(set) var longitude: LocationRadians + /** + Initializes a coordinate pair located at the given latitude and longitude. + + - parameter latitude: The latitude measured in radians. + - parameter longitude: The longitude measured in radians. + */ public init(latitude: LocationRadians, longitude: LocationRadians) { self.latitude = latitude self.longitude = longitude } + /** + Initializes a coordinate pair measured in radians that is coincident to the given coordinate pair measured in degrees of arc. + + - parameter degreeCoordinate: A coordinate pair measured in degrees of arc. + */ public init(_ degreeCoordinate: LocationCoordinate2D) { latitude = degreeCoordinate.latitude.toRadians() longitude = degreeCoordinate.longitude.toRadians()