Coder Social home page Coder Social logo

mapbox / turf-swift Goto Github PK

View Code? Open in Web Editor NEW
234.0 100.0 55.0 4.61 MB

A Swift language port of Turf.js.

Home Page: https://mapbox.github.io/turf-swift/

License: ISC License

Swift 98.13% Objective-C 0.11% Ruby 0.84% Shell 0.92%
turf geospatial algorithm computational-geometry gis swift ios macos geojson

turf-swift's Introduction

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, visionOS, 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 (not supported via CocoaPods)

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:
    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)

turf-swift's People

Contributors

1ec5 avatar avi-c avatar azarovalex avatar bamx23 avatar boundsj avatar captainbarbosa avatar chezzdev avatar fphilipe avatar frederoni avatar friedbunny avatar jonkan avatar jthramer avatar macdrevx avatar maximalien avatar nighthawk avatar nitaliano avatar odnairy avatar okcoker avatar persidskiy avatar romainquidet avatar s2ler avatar sandychapman avatar shanma1991 avatar stonetip avatar udumft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

turf-swift's Issues

Struct with the same name as module name

Hi!
Search sdk team has issue with turf module in our frameworks.

It is known issue with swift modules, discussed here and swift bug.

In short words we are using BoundingBox struct which exposed to public interface of a xcframework. After the xcframework build for distribution all notions of BoundingBox becomes Turf.BoundingBox which is right (ModuleName.TypeName).
But because Turf module has entity named Turf error occurs 'BoundingBox' is not a member type of 'Turf'.

Simple workaround would be to rename Turf entity.

Move geometry structs out from under Geometry enumeration

After playing with the changes in #93 a bit, I’m finding it rather inconvenient to have to continually write Geometry.LineStringRepresentation every time I want to create a line string. I think we should move these types back out to the main namespace, where they were in v0.3.0. For example, Geometry.LineString’s associated value would be of type LineString.

/cc @mapbox/navigation-ios

IndexedCoordinate.distance measured from incorrect coordinate

IndexedCoordinate.distance is documented to be the distance from the start of the line string to the found coordinate:

/**
`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<CLLocationCoordinate2D>.Element
/// The index of the coordinate
public let index: Array<CLLocationCoordinate2D>.Index
/// The coordinate’s distance from the start of the polyline
public let distance: CLLocationDistance
}

However, LineString.closestCoordinate(to:) sets it to the distance from the input coordinate to the found coordinate:

let distances = (coordinate.distance(to: segment.0), coordinate.distance(to: segment.1))

This may be one reason for the failures in #77.

/cc @RomainQuidet @frederoni

BoundingBox mixes up its corners

The BoundingBox struct encodes and decodes northwest and southeast coordinates, in that order, whereas the GeoJSON specification expects southwest and northeast coordinates:

try container.encode(northWest.codableCoordinates)
try container.encode(southEast.codableCoordinates)

If an application decodes GeoJSON, the in-memory representation is incorrect. If an application creates a BoundingBox programmatically and encodes it to GeoJSON, the GeoJSON is incorrect.

BoundingBox was probably copied from MapboxDirections’ CoordinateBounds type, which was fixed in mapbox/mapbox-directions-swift#348.

/cc @mapbox/navigation-ios @frederoni

Is turf-swift supporting all Turf.js features?

I'm wondering if turf-swift supporting all Turf.js features? I'd like to calculate the distance from a point to a polygon so that I may need nearestPointOnLine, but I didn't find it. Any idea? Thanks.

Project Vision?

Hi I'm working on a project that needs a subset of these turf functions and while I was porting some over, I tried to go on to port some boolean functions next. I hit a bit of a rough patch as I noticed things implemented in this library like intersection don't necessarily follow the same patterns as what's in Turf.js.

When I first started messing around with turf-swift I noticed "GeoJSON was experimental" so I sort of stayed away from it. Getting deeper into the lib, it seems more unavoidable if the goal is for the whole library to be ported over.

My question is how do you see this library being structured moving forward? Seems like some functions have been added in a bit randomly, some of which aren't even named the same as original turf functions. The Java version has them organized by module. The Java version also uses a bunch of overloaded functions which may be desirable? I recently noticed the Geometry.swift module here. Was the idea of this to basically pass Geometry around to avoid these overloaded functions? Maybe it would be used in a context like this so we could prevent the use of Any?

How much should I consider the GeoJSON file moving forward? A lot of the turf helper functions accept GeoJSON so should these helper functions also be ported? The Java version has them as a part of the GeoJSON module which seems like it makes sense. I also prefer that checklist in general as compared to the table in the readme here. It makes it a lot clearer as to what functions have been ported.

On a related note has any work been done with Rbush mentioned here? Since that is a dependency of booleanIntersects I was wondering where the thinking here was left off in terms of using GKRTree or making a custom port of RBush?

I know the tests are an important part of any contribution here regardless of the structure moving forward but while I'm here, I'd like to follow whatever the vision for the project is/was.

GeoJSON object cannot be set programmatically

Hi,

Looks like the example from the README is broken. This no longer works:

// Initialize a PointFeature and encode as GeoJSON
let coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 1)
let point = Point(coordinate)
let pointFeature = PointFeature(point)
let data = try! JSONEncoder().encode(pointFeature)
let json = String(data: data, encoding: .utf8)

It seems you can now only create a PointFeature from a JSON file. Is that by design?

Test Specs:
Turf (0.2.0)
Xcode 9.4.1
Swift 4

Polyline struct

Assuming we aren’t overly concerned about Objective-C compatibility, we should encapsulate the concept of a “polygon” in a struct named Polyline or Line (to use Turf.js terminology), instead of assuming that any array of CLLocationCoordinate2Ds is intended to be connected sequentially. We could then place most of the freestanding functions under Polyline as instance methods.

Is there a more Swiftian representation than a struct that would allow client code to take advantage of all the Array methods more directly?

/cc @frederoni @bsudekum

Inconsistent results from Polyline.distance

I'm getting small inconsistencies from Polyline.distance. By tracing intermediate points along a polyline from start to end - including between vertices - the resulting distance(to: point) doesn't consistently increment from 0 to (total distance), but jumps up and down.

My suspicion is that there's something screwy going on with the interaction with closestCoordinate but I've not been able to nail it down.

For my purposes I only need the distance to a point from the start of the polyline, so I was able to get round it by hacking a baseIndex property onto closestCoordinate which always contains the value of index (not index+1) and then building this round it:

let slice = polyline.coordinates[0 ... coord.baseIndex]
let zipped = zip(slice.prefix(upTo: slice.count - 1), slice.suffix(from: 1))
return zipped.map { $0.distance(to: $1) }.reduce(0, +) +
	polyline.coordinates[coord.baseIndex].distance(to: coord.coordinate)

but I thought it worth flagging in case anyone else encounters this.

GeoJSON Decoder null value property support

When decoding GeoJSON with feature properties that have a 'null' value, the decoding fails (Unsupported JSON type).

From reading the GeoJSON RFC (https://tools.ietf.org/html/rfc7946#page-4), a null value is supported and should be handled.

Sample GeoJSON:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "id": 1,
        "fields": "one",
        "DESCRIP": null
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -119.4248,
              36.145
            ],
            [
              -119.42020327868853,
              36.145
            ],
            [
              -119.41960942622951,
              36.13583565573771
            ],
            [
              -119.4196155737705,
              36.13505
            ],
            [
              -119.4248,
              36.13505
            ],
            [
              -119.4248,
              36.145
            ]
          ]
        ]
      }
    }
  ]
}

Associated-value enumeration should be for geometries, not features

The GeoJSON model types in this library currently mirror the shape classes in the map SDK, which are inconsistent with the GeoJSON specification in several significant ways. In particular, there are multiple feature structs, one for each geometry type, and no single type unifies the various geometry types. Aside from nonconformance with GeoJSON, this approach makes it difficult to support GeometryCollection (#89).

  • Replace the FeatureVariant associated-value enumeration with a single struct Feature that contains a Geometry
  • Replace the Geometry struct with an associated-value enumeration
  • Remove the various *Feature structs in favor of Feature

/ref mapbox/mapbox-gl-native#7454
/cc @mapbox/navigation-ios @frederoni

Sane JSON Representations

There are places in turf-swift where we currently represent a JSON object with [String:AnyJSONType] as opposed to the more common [String:Any] regularly found in iOS frameworks.

As mentioned elsewhere, [AnyJSONType] isn't really worth the hassle of keeping around, since you still have to type-cast for the value at the point-of-use.

public struct AnyJSONType: JSONType {
public let jsonValue: Any
public init(_ value: Any) {
self.jsonValue = value
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() {
jsonValue = NSNull()
} else if let intValue = try? container.decode(Int.self) {
jsonValue = intValue
} else if let stringValue = try? container.decode(String.self) {
jsonValue = stringValue
} else if let boolValue = try? container.decode(Bool.self) {
jsonValue = boolValue
} else if let doubleValue = try? container.decode(Double.self) {
jsonValue = doubleValue
} else if let doubleValue = try? container.decode([AnyJSONType].self) {
jsonValue = doubleValue
} else if let doubleValue = try? container.decode([String: AnyJSONType].self) {
jsonValue = doubleValue
} else {
throw DecodingError.typeMismatch(JSONType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unsupported JSON type"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
if jsonValue is NSNull {
try container.encodeNil()
} else if let intValue = jsonValue as? Int {
try container.encode(intValue)
} else if let stringValue = jsonValue as? String {
try container.encode(stringValue)
} else if let boolValue = jsonValue as? Bool {
try container.encode(boolValue)
} else if let doubleValue = jsonValue as? Double {
try container.encode(doubleValue)
} else if let arrayValue = jsonValue as? [AnyJSONType] {
try container.encode(arrayValue)
} else if let dictionaryValue = jsonValue as? [String: AnyJSONType] {
try container.encode(dictionaryValue)
}
}
}

Let's get a PR going where we remove the replace the bespoke representation with a standard one.

/cc @mapbox/navigation-ios

Confused Regarding Documentation

I like the look of this library, but are there any examples at all of the methods being used? I see on the front page some comparisons between turf.js and turf-swift, but these suggestions are too general. For example, how do I find a destination? My attempt based on turf.js looks like:

`let coordinate = CLLocationCoordinate2D(latitude: -75.343, longitude: 39.984)
let point = Turf.Point(coordinate)
let distance = 50
let bearing = 90
let options = ["units" : "miles"]

let destination = Turf.destination(point, distance, bearing, options)`

But this doesn't work (no Turf.destination). Am I missing some documentation/examples somewhere?

Remove Polyline type alias

#45 renamed Polyline to LineString, for consistency with GeoJSON terminology, but left Polyline as a type alias to LineString, for consistency with the map SDK. For v1.0, we should remove this type alias outright, because it conflicts with the Polyline library, which is commonly used in conjunction with Turf (for instance, in MapboxDirections.swift). Unfortunately, I think the problem would persist even if we leave in the type alias but mark it unavailable. We’ll just have to document that LineString isn’t a kind of String and is what people want for polyline geometries.

The workaround is currently to import Polyline and import struct Turf.LineString in any file that needs to work with the two types simultaneously.

/cc @mapbox/navigation-ios @frederoni

Support Inside and hexbin

@ryanbaumann as discussed in email, need to support turf.inside and turf.hexbin in iOS.
per-email:

iv. iOS - Turf.inside and Turf.hexbin are not yet supported. Please create an issue in this repo with your dev needs for hexbin and inside and tag

cc @julieemunro

CLLocationCoordinate2D conformance to Codable should be private

Turf publicly declares CLLocationCoordinate2D’s conformance to Codable and implements the protocol according to the GeoJSON standard, as an array in longitude, latitude order. But this is problematic if the application or some other library needs to support some other coordinate representation in JSON. For example, Overpass JSON represents coordinate pairs as objects. Turf needs this Codable implementation but doesn’t need to export it publicly. It would be trivial for client code to reimplement this conformance if necessary.

extension CLLocationCoordinate2D: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(longitude)
try container.encode(latitude)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
let longitude = try container.decode(CLLocationDegrees.self)
let latitude = try container.decode(CLLocationDegrees.self)
self.init(latitude: latitude, longitude: longitude)
}
}

/cc @mapbox/navigation-ios @frederoni

Haversine distance should use spherical Earth radius

This library currently defines the radius of the Earth as 6 373 000 m for the purpose of converting between meters and radians in the Haversine formula:

let metersPerRadian = 6_373_000.0

Apparently this value came from an old version of turf-distance that I originally ported to an internal Swift application, before it got copied into another internal Swift application, then copied into the navigation SDK, then moved here. It’s close to the value of 6 372 797.560 856 that Osmium describes as “Earth’s quadratic mean radius for WGS84”.

These days, Turf.js uses a spherical approximation of 6 671 008.8 m for its radian-to-meter conversion and Haversine formula. The Haversine formula was always meant to be used with a spherical meters-per-radian value. We should probably change this value to match Turf.js. 🙀

/ref Turfjs/turf#978 Turfjs/turf#1012 Turfjs/turf#1176 #21 (comment)
/cc @frederoni @bsudekum @captainbarbosa

Split up Turf.swift

Originally, this library was contained in a single file to facilitate manual installation without a package manager. However, as this library grows, it’ll become unwieldy to work with this file. We should move each struct into a file named after the struct. As for the Turf struct, we should replace intersection(_:_:) with a method on Polyline that takes a single other Polyline to intersect with.

新版swift不支持问题

Xcode12.3 error, your library does not support new Version of Compiled Swift language Module with Swift 5.3 cannot be imported by the SWIFT 5.3.2 Compiler

Path is little off from the center of the road

When path is sliced then sometimes it gets off from route. Please see the screenshot.

// Expected Behaviour

Path shouldn't be off from the center of the road

// Actual Behavior

Path is off from the center of the road.

Code to trim the path
turfPolyline.sliced(from: coordinate, to: turfPolyline.coordinates.last)

macOS, tvOS, watchOS

This library only supports iOS, but there's no technical reason it couldn't also support macOS, tvOS, and watchOS. The project and podspec would both need to be extended for these platforms. See MapboxGeocoder.swift, MapboxDirections.swift, and MapboxStatic.swift for examples.

/cc @frederoni @bsudekum @boundsj @friedbunny

Make coordinate arrays mutable or easier to mutate

#98 effectively made the coordinates property of each GeoJSON geometry struct read-only:

public var coordinates: [CLLocationCoordinate2D]
public let coordinates: [CLLocationCoordinate2D]

This forces client code to recreate new struct instances every time they need to modify the coordinate array, which can be inelegant or unperformant in functional code, such as in mapbox/mapbox-navigation-ios#2393 (comment).

We should either make the coordinates property read-write again, and/or we should add custom operators so that a developer can add two LineStrings together, for example.

/cc @mapbox/navigation-ios

Is there a roadmap?

Are you looking for contributors, and is there a roadmap for this project?

Name?

@1ec5 @frederoni you think we should call this anything different? Maybe something a little more informative? Or give a hat tip to turf?

Turf::intersection does not observe edge cases

I think this function does not observe the following edge cases:

  • both lines are colinear (denominator == 0): the line segments could still intersect - the intersection would be another line segment
  • what about the 180th meridian? what about line segments crossing the north and south pole?
  • the current algorithm does not seem to count the start end end point as part of the line segment. This is a matter of definition, but usually at least the start point is counted as part of the line (i.e. the line segment is then closed-open)

Port turf-line-intersect

There’s already a Turf.intersection(_:_:) method for calculating the intersection between two line segments, but it would be nice to support a more generalized turn-line-intersect.

/**
Returns the intersection of two line segments.
*/
public static func intersection(_ line1: LineSegment, _ line2: LineSegment) -> CLLocationCoordinate2D? {

turn-line-intersect optimizes the search for an intersection using RBush. We could port RBush, but first we should investigate other implementations already written in Objective-C or Swift. On iOS, macOS, and tvOS, GameplayKit’s GKRTree implements an R-tree.

/cc @frederoni @mourner

Polygon.contains(_:ignoreBoundary:) returns false for coordinates on boundary coinciding with bounding box

When specifying ignoreBoundary: false in Polygon.contains(_:ignoreBoundary:) (the default value), coordinates on the boundary that coincide with the bounding box are incorrectly considered not to be contained.

Ring.contains(_:ignoreBoundary:) on the other hand works as expected.

The issue is that the optimization used in Polygon.contains(_:ignoreBoundary:) to first do a check whether the point is within the bounding box

let bbox = BoundingBox(from: coordinates.first)
guard bbox?.contains(coordinate) ?? false else {
return false
}

does not pass on ignoreBoundary as BoundingBox.contains(_:) doesn't have this parameter:

public func contains(_ coordinate: CLLocationCoordinate2D) -> Bool {

The following code shows the problem:

let center = CLLocationCoordinate2D(latitude:  0, longitude:  0)
let sw     = CLLocationCoordinate2D(latitude: -1, longitude: -1)
let se     = CLLocationCoordinate2D(latitude: -1, longitude:  1)
let ne     = CLLocationCoordinate2D(latitude:  1, longitude:  1)
let nw     = CLLocationCoordinate2D(latitude:  1, longitude: -1)

let coords = [sw, nw, ne, se, sw]

let polygon = Polygon([coords])
let ring = Ring(coordinates: coords)

// Center is contained:

XCTAssertTrue(ring.contains(center))
XCTAssertTrue(polygon.contains(center))

// Corners are not contained when excluding boundary:

XCTAssertFalse(ring.contains(sw, ignoreBoundary: true))
XCTAssertFalse(ring.contains(nw, ignoreBoundary: true))
XCTAssertFalse(ring.contains(ne, ignoreBoundary: true))
XCTAssertFalse(ring.contains(se, ignoreBoundary: true))

XCTAssertFalse(polygon.contains(sw, ignoreBoundary: true))
XCTAssertFalse(polygon.contains(nw, ignoreBoundary: true))
XCTAssertFalse(polygon.contains(ne, ignoreBoundary: true))
XCTAssertFalse(polygon.contains(se, ignoreBoundary: true))

// Corners are contained when including boundary:

XCTAssertTrue(ring.contains(sw, ignoreBoundary: false))
XCTAssertTrue(ring.contains(nw, ignoreBoundary: false))
XCTAssertTrue(ring.contains(ne, ignoreBoundary: false))
XCTAssertTrue(ring.contains(se, ignoreBoundary: false))

XCTAssertTrue(polygon.contains(sw, ignoreBoundary: false)) // XCTAssertTrue failed
XCTAssertTrue(polygon.contains(nw, ignoreBoundary: false)) // XCTAssertTrue failed
XCTAssertTrue(polygon.contains(ne, ignoreBoundary: false)) // XCTAssertTrue failed
XCTAssertTrue(polygon.contains(se, ignoreBoundary: false)) // XCTAssertTrue failed

I'd suggest to address this in the following way:

  • Change BoundingBox.contains(_:) to BoundingBox.contains(_:ignoreBoundary:) with a default of true to preserve the current behavior.
  • Optionally, move the bounding box optimization from Polygon to Ring in order for Ring to benefit from this optimization as well (Polygon would still benefit indirectly from this optimization).

I'd be happy to make a PR if you agree on the suggested approach.

Core Location compatibility shim on Linux uses CL class prefix

This library publicly exposes a compatibility shim for common Core Location types on Linux. The shim works by aliasing primitive types and defining structs from scratch:

#if os(Linux)
public struct CLLocationCoordinate2D {
let latitude: Double
let longitude: Double
}
public typealias CLLocationDirection = Double
public typealias CLLocationDistance = Double
public typealias CLLocationDegrees = Double
#else
import CoreLocation
#endif

Unfortunately, if an application imports both Turf and another library that implements a similar shim, there could be conflicts that would at least result in client code having to namespace types or import the library more selectively. For example, mapbox/mapbox-directions-swift#488 adds Linux support to a library that imports both Turf and Polyline. Since Turf’s compatibility shim defines types under the original Core Location names, the Linux version of the codebase has to import Turf, even for files that don’t otherwise contain anything related to geometry operations.

In raphaelmor/Polyline#55, I settled on a slightly different approach: standardize the library on a parallel set of slightly differently named types. Primitives continue to be aliased to Core Location types. On Apple platforms, structs are also aliased to the Core Location types, but on Linux, they’re are defined from scratch. This is similar to the Turf approach, but since it doesn’t claim the CL class prefix, the developer can explicitly opt into the compatibility shim and choose which library they want to get it from in a given file.

Migrating to the Polyline approach would be a backwards-incompatible change.

/cc @frederoni @Udumft

Publish documentation

There’s enough documentation in the form of documentation comments that we could use jazzy to generate HTML documentation based on it and publish it using GitHub pages.

/cc @captainbarbosa

功能不全啊

什么时候能把支持安卓的api都迁移到swift上啊? 为什么swift的api这么少

Could not find module 'Turf' for target

when I change the debug of "build active architecture only" of "build setting" of my target to NO,it comes out the error :

/TurfBridgeOC.swift:11:8: Could not find module 'Turf' for target 'armv7-apple-ios'; found: arm64, arm64-apple-ios

why?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.