Skip to content

Commit

Permalink
update to original MapboxDirections Package
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick-Kladek committed Jul 27, 2024
1 parent 5143a0f commit 288e215
Show file tree
Hide file tree
Showing 22 changed files with 616 additions and 541 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
{
"identity" : "mapbox-directions-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/flitsmeister/mapbox-directions-swift",
"location" : "https://github.com/mapbox/mapbox-directions-swift",
"state" : {
"revision" : "6c19ecc4e1324887ae3250802b8d13d8d8b3ff2d",
"version" : "0.23.3"
"revision" : "6512320ee7f0091a4c55abe2bc6414f078da88c8",
"version" : "2.14.0"
}
},
{
Expand Down Expand Up @@ -36,6 +36,15 @@
"version" : "3.0.1"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "41982a3656a71c768319979febd796c6fd111d5c",
"version" : "1.5.0"
}
},
{
"identity" : "swiftformat",
"kind" : "remoteSourceControl",
Expand All @@ -48,10 +57,10 @@
{
"identity" : "turf-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/flitsmeister/turf-swift",
"location" : "https://github.com/mapbox/turf-swift.git",
"state" : {
"revision" : "b05b4658d1b48eac4127a0d9ebbb5a6f965a8251",
"version" : "0.2.2"
"revision" : "213050191cfcb3d5aa76e1fa90c6ff1e182a42ca",
"version" : "2.8.0"
}
}
],
Expand Down
38 changes: 23 additions & 15 deletions MapboxCoreNavigation/CLLocation.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CoreLocation
import MapboxDirections
import Polyline
import Turf

extension CLLocation {
Expand Down Expand Up @@ -61,39 +62,46 @@ extension CLLocation {
Returns a Boolean value indicating whether the receiver is within a given distance of a route step.
*/
func isWithin(_ maximumDistance: CLLocationDistance, of routeStep: RouteStep) -> Bool {
guard let closestCoordinate = Polyline(routeStep.coordinates!).closestCoordinate(to: coordinate) else {
guard let closestCoordinate = routeStep.shape?.closestCoordinate(to: self.coordinate) else {
return false
}
return closestCoordinate.distance < maximumDistance

return closestCoordinate.coordinate.distance(to: self.coordinate) < maximumDistance
}

// MARK: - Route Snapping

func snapped(to legProgress: RouteLegProgress) -> CLLocation? {
let coords = self.coordinates(for: legProgress)
guard let closest = Polyline(coords).closestCoordinate(to: coordinate) else { return nil }
guard let calculatedCourseForLocationOnStep = interpolatedCourse(along: coords) else { return nil }
guard let closest = LineString(coords).closestCoordinate(to: coordinate) else { return nil }
guard let calculatedCourseForLocationOnStep = self.interpolatedCourse(along: coords) else { return nil }

let userCourse = calculatedCourseForLocationOnStep
let userCoordinate = closest.coordinate
guard let firstCoordinate = legProgress.leg.steps.first?.coordinates?.first else { return nil }
guard let firstCoordinate = legProgress.leg.steps.first?.shape?.coordinates.first else { return nil }

guard self.shouldSnapCourse(toRouteWith: calculatedCourseForLocationOnStep, distanceToFirstCoordinateOnLeg: coordinate.distance(to: firstCoordinate)) else { return nil }

guard closest.distance <= (RouteControllerUserLocationSnappingDistance + horizontalAccuracy) else {
guard closest.distance <= (RouteControllerUserLocationSnappingDistance + self.horizontalAccuracy) else {
return nil
}

return CLLocation(coordinate: userCoordinate, altitude: altitude, horizontalAccuracy: horizontalAccuracy, verticalAccuracy: verticalAccuracy, course: userCourse, speed: speed, timestamp: timestamp)
return CLLocation(coordinate: userCoordinate,
altitude: self.altitude,
horizontalAccuracy: self.horizontalAccuracy,
verticalAccuracy: self.verticalAccuracy,
course: userCourse,
speed: self.speed,
timestamp: self.timestamp)
}

/**
Calculates the proper coordinates to use when calculating a snapped location.
*/
func coordinates(for legProgress: RouteLegProgress) -> [CLLocationCoordinate2D] {
let nearbyCoordinates = legProgress.nearbyCoordinates
let stepCoordinates = legProgress.currentStep.coordinates!
let stepCoordinates = legProgress.currentStep.shape!.coordinates

// If the upcoming maneuver a sharp turn, only look at the current step for snapping.
// Otherwise, we may get false positives from nearby step coordinates
Expand All @@ -110,7 +118,7 @@ extension CLLocation {
}
}

if speed <= RouteControllerMaximumSpeedForUsingCurrentStep {
if self.speed <= RouteControllerMaximumSpeedForUsingCurrentStep {
return stepCoordinates
}

Expand All @@ -121,17 +129,17 @@ extension CLLocation {
Given a location and a series of coordinates, compute what the course should be for a the location.
*/
func interpolatedCourse(along coordinates: [CLLocationCoordinate2D]) -> CLLocationDirection? {
let nearByPolyline = Polyline(coordinates)
let nearByPolyline = LineString(coordinates)

guard let closest = nearByPolyline.closestCoordinate(to: coordinate) else { return nil }

let slicedLineBehind = Polyline(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last)
let slicedLineBehind = LineString(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last)
let slicedLineInFront = nearByPolyline.sliced(from: closest.coordinate, to: coordinates.last)
let userDistanceBuffer: CLLocationDistance = max(speed * RouteControllerDeadReckoningTimeInterval / 2, RouteControllerUserLocationSnappingDistance / 2)

guard let pointBehind = slicedLineBehind.coordinateFromStart(distance: userDistanceBuffer) else { return nil }
guard let pointBehind = slicedLineBehind?.coordinateFromStart(distance: userDistanceBuffer) else { return nil }
guard let pointBehindClosest = nearByPolyline.closestCoordinate(to: pointBehind) else { return nil }
guard let pointAhead = slicedLineInFront.coordinateFromStart(distance: userDistanceBuffer) else { return nil }
guard let pointAhead = slicedLineInFront?.coordinateFromStart(distance: userDistanceBuffer) else { return nil }
guard let pointAheadClosest = nearByPolyline.closestCoordinate(to: pointAhead) else { return nil }

// Get direction of these points
Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigation/CoreFeedbackEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class FeedbackEvent: CoreFeedbackEvent {

class RerouteEvent: CoreFeedbackEvent {
func update(newRoute: Route) {
if let geometry = newRoute.coordinates {
if let geometry = newRoute.shape?.coordinates {
eventDictionary["newGeometry"] = Polyline(coordinates: geometry).encodedPolyline
eventDictionary["newDistanceRemaining"] = round(newRoute.distance)
eventDictionary["newDurationRemaining"] = round(newRoute.expectedTravelTime)
Expand Down
9 changes: 4 additions & 5 deletions MapboxCoreNavigation/DistanceFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ public extension NSAttributedString.Key {
}

/// Provides appropriately formatted, localized descriptions of linear distances.
@objc(MBDistanceFormatter)
open class DistanceFormatter: LengthFormatter {
/// True to favor brevity over precision.
var approx: Bool
Expand Down Expand Up @@ -164,7 +163,7 @@ open class DistanceFormatter: LengthFormatter {

- parameter approximate: approximates the distances.
*/
@objc public init(approximate: Bool = false) {
public init(approximate: Bool = false) {
self.approx = approximate
super.init()
self.locale = .nationalizedCurrent
Expand Down Expand Up @@ -199,7 +198,7 @@ open class DistanceFormatter: LengthFormatter {

The user’s `Locale` is used here to set the units.
*/
@objc public func string(from distance: CLLocationDistance) -> String {
public func string(from distance: CLLocationDistance) -> String {
numberFormatter.positivePrefix = ""
numberFormatter.positiveSuffix = ""
numberFormatter.decimalSeparator = self.nonFractionalLengthFormatter.numberFormatter.decimalSeparator
Expand All @@ -208,7 +207,7 @@ open class DistanceFormatter: LengthFormatter {
return self.formattedDistance(distance)
}

@objc override open func string(fromMeters numberInMeters: Double) -> String {
override open func string(fromMeters numberInMeters: Double) -> String {
self.string(from: numberInMeters)
}

Expand All @@ -235,7 +234,7 @@ open class DistanceFormatter: LengthFormatter {

`NSAttributedStringKey.quantity` is applied to the numeric quantity.
*/
@objc override open func attributedString(for obj: Any, withDefaultAttributes attrs: [NSAttributedString.Key: Any]? = nil) -> NSAttributedString? {
override open func attributedString(for obj: Any, withDefaultAttributes attrs: [NSAttributedString.Key: Any]? = nil) -> NSAttributedString? {
guard let distance = obj as? CLLocationDistance else {
return nil
}
Expand Down
36 changes: 21 additions & 15 deletions MapboxCoreNavigation/NavigationRouteOptions.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import CoreLocation
import Foundation
import MapboxDirections
import MapboxDirectionsObjc

/**
A `NavigationRouteOptions` object specifies turn-by-turn-optimized criteria for results returned by the Mapbox Directions API.

`NavigationRouteOptions` is a subclass of `RouteOptions` that has been optimized for navigation. Pass an instance of this class into the `Directions.calculate(_:completionHandler:)` method.
*/
@objc(MBNavigationRouteOptions)
open class NavigationRouteOptions: RouteOptions {
/**
Initializes a navigation route options object for routes between the given waypoints and an optional profile identifier optimized for navigation.

- SeeAlso:
[RouteOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.10.1/Classes/RouteOptions.html)
*/
@objc public required init(waypoints: [Waypoint], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public required init(waypoints: [Waypoint], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
super.init(waypoints: waypoints.map {
$0.coordinateAccuracy = -1
return $0
Expand All @@ -37,7 +36,7 @@ open class NavigationRouteOptions: RouteOptions {
- SeeAlso:
[RouteOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/RouteOptions.html)
*/
@objc public convenience init(locations: [CLLocation], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public convenience init(locations: [CLLocation], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
self.init(waypoints: locations.map { Waypoint(location: $0) }, profileIdentifier: profileIdentifier)
}

Expand All @@ -47,12 +46,16 @@ open class NavigationRouteOptions: RouteOptions {
- SeeAlso:
[RouteOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/RouteOptions.html)
*/
@objc public convenience init(coordinates: [CLLocationCoordinate2D], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public convenience init(coordinates: [CLLocationCoordinate2D], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
self.init(waypoints: coordinates.map { Waypoint(coordinate: $0) }, profileIdentifier: profileIdentifier)
}

@objc public required init?(coder decoder: NSCoder) {
super.init(coder: decoder)

public required init(from decoder: any Decoder) throws {
try super.init(from: decoder)
}

public required init(waypoints: [Waypoint], profileIdentifier: ProfileIdentifier? = nil, queryItems: [URLQueryItem]? = nil) {
super.init(waypoints: waypoints, profileIdentifier: profileIdentifier, queryItems: queryItems)
}
}

Expand All @@ -63,15 +66,14 @@ open class NavigationRouteOptions: RouteOptions {

Note: it is very important you specify the `waypoints` for the route. Usually the only two values for this `IndexSet` will be 0 and the length of the coordinates. Otherwise, all coordinates passed through will be considered waypoints.
*/
@objc(MBNavigationMatchOptions)
open class NavigationMatchOptions: MatchOptions {
/**
Initializes a navigation route options object for routes between the given waypoints and an optional profile identifier optimized for navigation.

- SeeAlso:
[MatchOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/MatchOptions.html)
*/
@objc public required init(waypoints: [Waypoint], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public required init(waypoints: [Waypoint], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
super.init(waypoints: waypoints.map {
$0.coordinateAccuracy = -1
return $0
Expand All @@ -91,7 +93,7 @@ open class NavigationMatchOptions: MatchOptions {
- SeeAlso:
[MatchOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/MatchOptions.html)
*/
@objc public convenience init(locations: [CLLocation], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public convenience init(locations: [CLLocation], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
self.init(waypoints: locations.map { Waypoint(location: $0) }, profileIdentifier: profileIdentifier)
}

Expand All @@ -101,11 +103,15 @@ open class NavigationMatchOptions: MatchOptions {
- SeeAlso:
[MatchOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/MatchOptions.html)
*/
@objc public convenience init(coordinates: [CLLocationCoordinate2D], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
public convenience init(coordinates: [CLLocationCoordinate2D], profileIdentifier: ProfileIdentifier? = .automobileAvoidingTraffic) {
self.init(waypoints: coordinates.map { Waypoint(coordinate: $0) }, profileIdentifier: profileIdentifier)
}

@objc public required init?(coder decoder: NSCoder) {
super.init(coder: decoder)

public required init(waypoints: [Waypoint], profileIdentifier: ProfileIdentifier? = nil, queryItems: [URLQueryItem]? = nil) {
super.init(waypoints: waypoints, profileIdentifier: profileIdentifier, queryItems: queryItems)
}

public required init(from decoder: any Decoder) throws {
try super.init(from: decoder)
}
}
11 changes: 9 additions & 2 deletions MapboxCoreNavigation/Route.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ import CoreLocation
import MapboxDirections

extension Route {
convenience init(jsonFileName: String, waypoints: [CLLocationCoordinate2D], polylineShapeFormat: RouteShapeFormat = .polyline6, bundle: Bundle = .main, accessToken: String) {
static func from(jsonFileName: String, waypoints: [CLLocationCoordinate2D], polylineShapeFormat: RouteShapeFormat = .polyline6, bundle: Bundle = .main, accessToken: String) throws -> Route {
let convertedWaypoints = waypoints.compactMap { waypoint in
Waypoint(coordinate: waypoint)
}
let routeOptions = NavigationRouteOptions(waypoints: convertedWaypoints)
routeOptions.shapeFormat = polylineShapeFormat
self.init(json: Fixture.JSONFromFileNamed(name: jsonFileName, bundle: bundle), waypoints: convertedWaypoints, options: routeOptions)

let path = bundle.url(forResource: jsonFileName, withExtension: "json") ?? bundle.url(forResource: jsonFileName, withExtension: "geojson")!
let data = try Data(contentsOf: path)

let decoder = JSONDecoder()
let result = try decoder.decode(RouteResponse.self, from: data)

return result.routes!.first!
}
}
Loading

0 comments on commit 288e215

Please sign in to comment.