From 00880464be0c31cf0a952008a8b8d9abc501541d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 29 Jul 2024 15:36:06 -0700 Subject: [PATCH 1/7] use latest turf --- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- Package.resolved | 6 +++--- Package.swift | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5635fc2c..08bf7fb6 100644 --- a/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -48,10 +48,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" } } ], diff --git a/Package.resolved b/Package.resolved index ff52e3ab..938b4b21 100644 --- a/Package.resolved +++ b/Package.resolved @@ -48,10 +48,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" } } ], diff --git a/Package.swift b/Package.swift index 8209ce58..8cc20bf3 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/flitsmeister/mapbox-directions-swift", exact: "0.23.3"), - .package(url: "https://github.com/flitsmeister/turf-swift", exact: "0.2.2"), + .package(url: "https://github.com/mapbox/turf-swift.git", from: "2.8.0"), .package(url: "https://github.com/maplibre/maplibre-gl-native-distribution.git", from: "6.0.0"), .package(url: "https://github.com/ceeK/Solar.git", exact: "3.0.1"), .package(url: "https://github.com/nicklockwood/SwiftFormat.git", from: "0.53.6") From 0242a01d7fb2cc2ff6345c553d8c7bed08c24f95 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 29 Jul 2024 15:36:37 -0700 Subject: [PATCH 2/7] turf renamed: Polyline -> LineString --- MapboxCoreNavigation/CLLocation.swift | 10 +++++----- MapboxCoreNavigation/RouteController.swift | 10 +++++----- MapboxCoreNavigation/RouteProgress.swift | 2 +- MapboxCoreNavigation/SimulatedLocationManager.swift | 4 ++-- MapboxCoreNavigationTests/RouteControllerTests.swift | 4 ++-- .../TunnelIntersectionManagerTests.swift | 2 +- MapboxNavigation/NavigationMapView.swift | 12 ++++++------ MapboxNavigation/RouteMapViewController.swift | 8 ++++---- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/MapboxCoreNavigation/CLLocation.swift b/MapboxCoreNavigation/CLLocation.swift index 50ba693f..dc962983 100644 --- a/MapboxCoreNavigation/CLLocation.swift +++ b/MapboxCoreNavigation/CLLocation.swift @@ -61,7 +61,7 @@ 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 = LineString(routeStep.coordinates!).closestCoordinate(to: coordinate) else { return false } return closestCoordinate.distance < maximumDistance @@ -72,7 +72,7 @@ extension CLLocation { 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 closest = LineString(coords).closestCoordinate(to: coordinate) else { return nil } guard let calculatedCourseForLocationOnStep = interpolatedCourse(along: coords) else { return nil } let userCourse = calculatedCourseForLocationOnStep @@ -121,11 +121,11 @@ 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) diff --git a/MapboxCoreNavigation/RouteController.swift b/MapboxCoreNavigation/RouteController.swift index cd85d545..2c3c5cab 100644 --- a/MapboxCoreNavigation/RouteController.swift +++ b/MapboxCoreNavigation/RouteController.swift @@ -254,7 +254,7 @@ open class RouteController: NSObject, Router { self.userSnapToStepDistanceFromManeuver = nil return } - self.userSnapToStepDistanceFromManeuver = Polyline(coordinates).distance(from: coordinate) + self.userSnapToStepDistanceFromManeuver = LineString(coordinates).distance(from: coordinate) } /** @@ -303,7 +303,7 @@ extension RouteController: CLLocationManagerDelegate { @objc func interpolateLocation() { guard let location = locationManager.lastKnownLocation else { return } guard let coordinates = routeProgress.route.coordinates else { return } - let polyline = Polyline(coordinates) + let polyline = LineString(coordinates) let distance = location.speed as CLLocationDistance @@ -380,7 +380,7 @@ extension RouteController: CLLocationManagerDelegate { self.updateIntersectionIndex(for: currentStepProgress) // Notify observers if the step’s remaining distance has changed. - let polyline = Polyline(routeProgress.currentLegProgress.currentStep.coordinates!) + let polyline = LineString(routeProgress.currentLegProgress.currentStep.coordinates!) if let closestCoordinate = polyline.closestCoordinate(to: location.coordinate) { let remainingDistance = polyline.distance(from: closestCoordinate.coordinate) let distanceTraveled = currentStep.distance - remainingDistance @@ -727,7 +727,7 @@ extension RouteController: CLLocationManagerDelegate { self.routeProgress.currentLegProgress.currentStepProgress.intersectionsIncludingUpcomingManeuverIntersection = intersections if let upcomingIntersection = routeProgress.currentLegProgress.currentStepProgress.upcomingIntersection { - self.routeProgress.currentLegProgress.currentStepProgress.userDistanceToUpcomingIntersection = Polyline(currentStepProgress.step.coordinates!).distance(from: location.coordinate, to: upcomingIntersection.location) + self.routeProgress.currentLegProgress.currentStepProgress.userDistanceToUpcomingIntersection = LineString(currentStepProgress.step.coordinates!).distance(from: location.coordinate, to: upcomingIntersection.location) } if self.routeProgress.currentLegProgress.currentStepProgress.intersectionDistances == nil { @@ -828,7 +828,7 @@ extension RouteController: CLLocationManagerDelegate { func updateIntersectionDistances() { if let coordinates = routeProgress.currentLegProgress.currentStep.coordinates, let intersections = routeProgress.currentLegProgress.currentStep.intersections { - let polyline = Polyline(coordinates) + let polyline = LineString(coordinates) let distances: [CLLocationDistance] = intersections.map { polyline.distance(from: coordinates.first, to: $0.location) } self.routeProgress.currentLegProgress.currentStepProgress.intersectionDistances = distances } diff --git a/MapboxCoreNavigation/RouteProgress.swift b/MapboxCoreNavigation/RouteProgress.swift index 66305811..ecef0ab9 100644 --- a/MapboxCoreNavigation/RouteProgress.swift +++ b/MapboxCoreNavigation/RouteProgress.swift @@ -368,7 +368,7 @@ open class RouteLegProgress: NSObject { for (currentStepIndex, step) in remainingSteps.enumerated() { guard let coords = step.coordinates else { continue } - guard let closestCoordOnStep = Polyline(coords).closestCoordinate(to: coordinate) else { continue } + guard let closestCoordOnStep = LineString(coords).closestCoordinate(to: coordinate) else { continue } let foundIndex = currentStepIndex + self.stepIndex // First time around, currentClosest will be `nil`. diff --git a/MapboxCoreNavigation/SimulatedLocationManager.swift b/MapboxCoreNavigation/SimulatedLocationManager.swift index c66a7bfa..cdc4c9c2 100644 --- a/MapboxCoreNavigation/SimulatedLocationManager.swift +++ b/MapboxCoreNavigation/SimulatedLocationManager.swift @@ -163,7 +163,7 @@ open class SimulatedLocationManager: NavigationLocationManager { @objc fileprivate func tick() { NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self.tick), object: nil) - let polyline = Polyline(routeLine) + let polyline = LineString(routeLine) guard let newCoordinate = polyline.coordinateFromStart(distance: currentDistance) else { return @@ -182,7 +182,7 @@ open class SimulatedLocationManager: NavigationLocationManager { // Simulate speed based on expected segment travel time if let expectedSegmentTravelTimes = routeProgress?.currentLeg.expectedSegmentTravelTimes, let coordinates = routeProgress?.route.coordinates, - let closestCoordinateOnRoute = Polyline(routeProgress!.route.coordinates!).closestCoordinate(to: newCoordinate), + let closestCoordinateOnRoute = LineString(routeProgress!.route.coordinates!).closestCoordinate(to: newCoordinate), let nextCoordinateOnRoute = coordinates.after(element: coordinates[closestCoordinateOnRoute.index]), let time = expectedSegmentTravelTimes.optional[closestCoordinateOnRoute.index] { let distance = coordinates[closestCoordinateOnRoute.index].distance(to: nextCoordinateOnRoute) diff --git a/MapboxCoreNavigationTests/RouteControllerTests.swift b/MapboxCoreNavigationTests/RouteControllerTests.swift index 41c5817b..fee21de7 100644 --- a/MapboxCoreNavigationTests/RouteControllerTests.swift +++ b/MapboxCoreNavigationTests/RouteControllerTests.swift @@ -145,7 +145,7 @@ class RouteControllerTests: XCTestCase { navigation.locationManager(navigation.locationManager, didUpdateLocations: [firstLocation]) XCTAssertEqual(navigation.location!.coordinate, firstLocation.coordinate, "Check snapped location is working") - let futureCoord = Polyline(navigation.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 100)! + let futureCoord = LineString(navigation.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 100)! let futureInaccurateLocation = CLLocation(coordinate: futureCoord, altitude: 0, horizontalAccuracy: 1, verticalAccuracy: 200, course: 0, speed: 5, timestamp: Date()) navigation.locationManager(navigation.locationManager, didUpdateLocations: [futureInaccurateLocation]) @@ -165,7 +165,7 @@ class RouteControllerTests: XCTestCase { let navigation = RouteController(along: route, directions: directions) let firstCoord = navigation.routeProgress.currentLegProgress.nearbyCoordinates.first! let firstLocation = CLLocation(latitude: firstCoord.latitude, longitude: firstCoord.longitude) - let coordNearStart = Polyline(navigation.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 10)! + let coordNearStart = LineString(navigation.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 10)! navigation.locationManager(navigation.locationManager, didUpdateLocations: [firstLocation]) diff --git a/MapboxCoreNavigationTests/TunnelIntersectionManagerTests.swift b/MapboxCoreNavigationTests/TunnelIntersectionManagerTests.swift index adb46d9e..deffc757 100644 --- a/MapboxCoreNavigationTests/TunnelIntersectionManagerTests.swift +++ b/MapboxCoreNavigationTests/TunnelIntersectionManagerTests.swift @@ -186,7 +186,7 @@ private extension TunnelIntersectionManagerTests { for routeController: RouteController, intersection: Intersection, distance: CLLocationDistance? = 200) -> CLLocation { - let polyline = Polyline(routeController.routeProgress.currentLegProgress.currentStep.coordinates!) + let polyline = LineString(routeController.routeProgress.currentLegProgress.currentStep.coordinates!) let newLocation = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude).coordinate( at: distance!, diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index e6cbeb02..5d41f598 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -600,7 +600,7 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { let minimumZoomLevel: Float = 14.5 let shaftLength = max(min(30 * metersPerPoint(atLatitude: maneuverCoordinate.latitude), 30), 10) - let polyline = Polyline(routeCoordinates) + let polyline = LineString(routeCoordinates) let shaftCoordinates = Array(polyline.trimmed(from: maneuverCoordinate, distance: -shaftLength).coordinates.reversed() + polyline.trimmed(from: maneuverCoordinate, distance: shaftLength).coordinates.suffix(from: 1)) if shaftCoordinates.count > 1 { @@ -781,8 +781,8 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { let closest = routes.sorted { left, right -> Bool in // existance has been assured through use of filter. - let leftLine = Polyline(left.coordinates!) - let rightLine = Polyline(right.coordinates!) + let leftLine = LineString(left.coordinates!) + let rightLine = LineString(right.coordinates!) let leftDistance = leftLine.closestCoordinate(to: tapCoordinate)!.distance let rightDistance = rightLine.closestCoordinate(to: tapCoordinate)!.distance @@ -791,7 +791,7 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { // filter closest coordinates by which ones are under threshold. let candidates = closest.filter { - let closestCoordinate = Polyline($0.coordinates!).closestCoordinate(to: tapCoordinate)!.coordinate + let closestCoordinate = LineString($0.coordinates!).closestCoordinate(to: tapCoordinate)!.coordinate let closestPoint = self.convert(closestCoordinate, toPointTo: self) return closestPoint.distance(to: point) < self.tapGestureDistanceThreshold @@ -1037,7 +1037,7 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { for (stepIndex, step) in leg.steps.enumerated() { for instruction in step.instructionsSpokenAlongStep! { let feature = MLNPointFeature() - feature.coordinate = Polyline(route.legs[legIndex].steps[stepIndex].coordinates!.reversed()).coordinateFromStart(distance: instruction.distanceAlongStep)! + feature.coordinate = LineString(route.legs[legIndex].steps[stepIndex].coordinates!.reversed()).coordinateFromStart(distance: instruction.distanceAlongStep)! feature.attributes = ["instruction": instruction.text] features.append(feature) } @@ -1076,7 +1076,7 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { */ @objc public func setOverheadCameraView(from userLocation: CLLocationCoordinate2D, along coordinates: [CLLocationCoordinate2D], for bounds: UIEdgeInsets) { self.isAnimatingToOverheadMode = true - let slicedLine = Polyline(coordinates).sliced(from: userLocation).coordinates + let slicedLine = LineString(coordinates).sliced(from: userLocation).coordinates let line = MLNPolyline(coordinates: slicedLine, count: UInt(slicedLine.count)) self.tracksUserCourse = false diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index c16efb13..55ea1f8b 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -402,13 +402,13 @@ class RouteMapViewController: UIViewController { for line in allLines { let featureCoordinates = Array(UnsafeBufferPointer(start: line.coordinates, count: Int(line.pointCount))) - let featurePolyline = Polyline(featureCoordinates) - let slicedLine = Polyline(stepCoordinates).sliced(from: closestCoordinate) + let featurePolyline = LineString(featureCoordinates) + let slicedLine = LineString(stepCoordinates).sliced(from: closestCoordinate) let lookAheadDistance: CLLocationDistance = 10 guard let pointAheadFeature = featurePolyline.sliced(from: closestCoordinate).coordinateFromStart(distance: lookAheadDistance) else { continue } guard let pointAheadUser = slicedLine.coordinateFromStart(distance: lookAheadDistance) else { continue } - guard let reversedPoint = Polyline(featureCoordinates.reversed()).sliced(from: closestCoordinate).coordinateFromStart(distance: lookAheadDistance) else { continue } + guard let reversedPoint = LineString(featureCoordinates.reversed()).sliced(from: closestCoordinate).coordinateFromStart(distance: lookAheadDistance) else { continue } let distanceBetweenPointsAhead = pointAheadFeature.distance(to: pointAheadUser) let distanceBetweenReversedPoint = reversedPoint.distance(to: pointAheadUser) @@ -487,7 +487,7 @@ class RouteMapViewController: UIViewController { // zoom in a bit to focus on the arrived destination if let coordinates = routeController?.routeProgress.route.coordinates, let userLocation = routeController?.locationManager.location?.coordinate { - let slicedLine = Polyline(coordinates).sliced(from: userLocation).coordinates + let slicedLine = LineString(coordinates).sliced(from: userLocation).coordinates let line = MLNPolyline(coordinates: slicedLine, count: UInt(slicedLine.count)) let camera = self.navigationView.mapView.cameraThatFitsShape(line, direction: self.navigationView.mapView.camera.heading, edgePadding: insets) From 8ad4e664564d5f7a82aaac126b468ef6d7755cb3 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 29 Jul 2024 15:52:44 -0700 Subject: [PATCH 3/7] turf made these methods fallible --- MapboxCoreNavigation/CLLocation.swift | 4 ++-- MapboxCoreNavigation/RouteController.swift | 6 +++--- MapboxCoreNavigation/SimulatedLocationManager.swift | 4 ++-- MapboxNavigation/NavigationMapView.swift | 13 +++++++++---- MapboxNavigation/RouteMapViewController.swift | 11 ++++++----- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/MapboxCoreNavigation/CLLocation.swift b/MapboxCoreNavigation/CLLocation.swift index dc962983..5c141dfe 100644 --- a/MapboxCoreNavigation/CLLocation.swift +++ b/MapboxCoreNavigation/CLLocation.swift @@ -125,8 +125,8 @@ extension CLLocation { guard let closest = nearByPolyline.closestCoordinate(to: coordinate) else { return nil } - let slicedLineBehind = LineString(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last) - let slicedLineInFront = nearByPolyline.sliced(from: closest.coordinate, to: coordinates.last) + guard let slicedLineBehind = LineString(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last) else { return nil } + guard let slicedLineInFront = nearByPolyline.sliced(from: closest.coordinate, to: coordinates.last) else { return nil } let userDistanceBuffer: CLLocationDistance = max(speed * RouteControllerDeadReckoningTimeInterval / 2, RouteControllerUserLocationSnappingDistance / 2) guard let pointBehind = slicedLineBehind.coordinateFromStart(distance: userDistanceBuffer) else { return nil } diff --git a/MapboxCoreNavigation/RouteController.swift b/MapboxCoreNavigation/RouteController.swift index 2c3c5cab..d0ead1c9 100644 --- a/MapboxCoreNavigation/RouteController.swift +++ b/MapboxCoreNavigation/RouteController.swift @@ -381,8 +381,8 @@ extension RouteController: CLLocationManagerDelegate { self.updateIntersectionIndex(for: currentStepProgress) // Notify observers if the step’s remaining distance has changed. let polyline = LineString(routeProgress.currentLegProgress.currentStep.coordinates!) - if let closestCoordinate = polyline.closestCoordinate(to: location.coordinate) { - let remainingDistance = polyline.distance(from: closestCoordinate.coordinate) + if let closestCoordinate = polyline.closestCoordinate(to: location.coordinate), + let remainingDistance = polyline.distance(from: closestCoordinate.coordinate) { let distanceTraveled = currentStep.distance - remainingDistance currentStepProgress.distanceTraveled = distanceTraveled NotificationCenter.default.post(name: .routeControllerProgressDidChange, object: self, userInfo: [ @@ -829,7 +829,7 @@ extension RouteController: CLLocationManagerDelegate { func updateIntersectionDistances() { if let coordinates = routeProgress.currentLegProgress.currentStep.coordinates, let intersections = routeProgress.currentLegProgress.currentStep.intersections { let polyline = LineString(coordinates) - let distances: [CLLocationDistance] = intersections.map { polyline.distance(from: coordinates.first, to: $0.location) } + let distances: [CLLocationDistance] = intersections.compactMap { polyline.distance(from: coordinates.first, to: $0.location) } self.routeProgress.currentLegProgress.currentStepProgress.intersectionDistances = distances } } diff --git a/MapboxCoreNavigation/SimulatedLocationManager.swift b/MapboxCoreNavigation/SimulatedLocationManager.swift index cdc4c9c2..a2061c86 100644 --- a/MapboxCoreNavigation/SimulatedLocationManager.swift +++ b/MapboxCoreNavigation/SimulatedLocationManager.swift @@ -177,8 +177,8 @@ open class SimulatedLocationManager: NavigationLocationManager { let distanceToClosest = closestLocation.distance(from: CLLocation(newCoordinate)) let distance = min(max(distanceToClosest, 10), safeDistance) - let coordinatesNearby = polyline.trimmed(from: newCoordinate, distance: 100).coordinates - + guard let coordinatesNearby = polyline.trimmed(from: newCoordinate, distance: 100)?.coordinates else { return } + // Simulate speed based on expected segment travel time if let expectedSegmentTravelTimes = routeProgress?.currentLeg.expectedSegmentTravelTimes, let coordinates = routeProgress?.route.coordinates, diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 5d41f598..e33bddf1 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -601,15 +601,18 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { let shaftLength = max(min(30 * metersPerPoint(atLatitude: maneuverCoordinate.latitude), 30), 10) let polyline = LineString(routeCoordinates) - let shaftCoordinates = Array(polyline.trimmed(from: maneuverCoordinate, distance: -shaftLength).coordinates.reversed() - + polyline.trimmed(from: maneuverCoordinate, distance: shaftLength).coordinates.suffix(from: 1)) + guard let beforeTrimmedPolyline = polyline.trimmed(from: maneuverCoordinate, distance: -shaftLength), + let afterTrimmedPolyline = polyline.trimmed(from: maneuverCoordinate, distance: shaftLength) else { + return + } + let shaftCoordinates = Array(beforeTrimmedPolyline.coordinates.reversed() + afterTrimmedPolyline.coordinates.suffix(from: 1)) if shaftCoordinates.count > 1 { var shaftStrokeCoordinates = shaftCoordinates let shaftStrokePolyline = ArrowStrokePolyline(coordinates: &shaftStrokeCoordinates, count: UInt(shaftStrokeCoordinates.count)) let shaftDirection = shaftStrokeCoordinates[shaftStrokeCoordinates.count - 2].direction(to: shaftStrokeCoordinates.last!) let maneuverArrowStrokePolylines = [shaftStrokePolyline] let shaftPolyline = ArrowFillPolyline(coordinates: shaftCoordinates, count: UInt(shaftCoordinates.count)) - + let arrowShape = MLNShapeCollection(shapes: [shaftPolyline]) let arrowStrokeShape = MLNShapeCollection(shapes: maneuverArrowStrokePolylines) @@ -1076,7 +1079,9 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { */ @objc public func setOverheadCameraView(from userLocation: CLLocationCoordinate2D, along coordinates: [CLLocationCoordinate2D], for bounds: UIEdgeInsets) { self.isAnimatingToOverheadMode = true - let slicedLine = LineString(coordinates).sliced(from: userLocation).coordinates + guard let slicedLine = LineString(coordinates).sliced(from: userLocation)?.coordinates else { + return + } let line = MLNPolyline(coordinates: slicedLine, count: UInt(slicedLine.count)) self.tracksUserCourse = false diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 55ea1f8b..5f1382e3 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -406,9 +406,9 @@ class RouteMapViewController: UIViewController { let slicedLine = LineString(stepCoordinates).sliced(from: closestCoordinate) let lookAheadDistance: CLLocationDistance = 10 - guard let pointAheadFeature = featurePolyline.sliced(from: closestCoordinate).coordinateFromStart(distance: lookAheadDistance) else { continue } - guard let pointAheadUser = slicedLine.coordinateFromStart(distance: lookAheadDistance) else { continue } - guard let reversedPoint = LineString(featureCoordinates.reversed()).sliced(from: closestCoordinate).coordinateFromStart(distance: lookAheadDistance) else { continue } + guard let pointAheadFeature = featurePolyline.sliced(from: closestCoordinate)?.coordinateFromStart(distance: lookAheadDistance) else { continue } + guard let pointAheadUser = slicedLine?.coordinateFromStart(distance: lookAheadDistance) else { continue } + guard let reversedPoint = LineString(featureCoordinates.reversed()).sliced(from: closestCoordinate)?.coordinateFromStart(distance: lookAheadDistance) else { continue } let distanceBetweenPointsAhead = pointAheadFeature.distance(to: pointAheadUser) let distanceBetweenReversedPoint = reversedPoint.distance(to: pointAheadUser) @@ -486,8 +486,9 @@ class RouteMapViewController: UIViewController { let insets = UIEdgeInsets(top: navigationView.instructionsBannerView.bounds.height, left: 20, bottom: height + 20, right: 20) // zoom in a bit to focus on the arrived destination - if let coordinates = routeController?.routeProgress.route.coordinates, let userLocation = routeController?.locationManager.location?.coordinate { - let slicedLine = LineString(coordinates).sliced(from: userLocation).coordinates + if let coordinates = routeController?.routeProgress.route.coordinates, + let userLocation = routeController?.locationManager.location?.coordinate, + let slicedLine = LineString(coordinates).sliced(from: userLocation)?.coordinates { let line = MLNPolyline(coordinates: slicedLine, count: UInt(slicedLine.count)) let camera = self.navigationView.mapView.cameraThatFitsShape(line, direction: self.navigationView.mapView.camera.heading, edgePadding: insets) From 4cbdf30d0193a67a07fa27ce5ff699e62a17dcef Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 29 Jul 2024 16:12:28 -0700 Subject: [PATCH 4/7] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db97c5c..dbfb3f38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ * Custom location snapping in the `RouteController` via the delegate * Fix: If the directions API endpoint doesn't include audio instructions, `didArrive:` would never be called. * Merged in +* Updated "turf" geometry library from 0.2.2 to 2.8.0 + * Merged in https://github.com/maplibre/maplibre-navigation-ios/pull/91 ## 3.0.0 (Jun 15, 2024) * The `speak` method in `RouteVoiceController` can be used without a given `RouteProgress` or the `RouteProgress` can explicitly ignored so that it will not be added to the voice instruction. From 9e3c7a90d2c0258d341cf6edd71435365727853f Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 30 Jul 2024 16:27:34 -0700 Subject: [PATCH 5/7] Adapt to new Turf: IndexedCoordinate.distance is distance to *start* Previously the IndexedCoordinate returned from `closestPoint` had its `distance` field set to the distance from the closest point on the Line. But it was always intended to be distance from the `start` of the line. Upstream fixed this in: https://github.com/mapbox/turf-swift/pull/107/files So this commit adapts to this new behavior. --- MapboxCoreNavigation/CLLocation.swift | 13 ++++++++----- MapboxCoreNavigation/RouteProgress.swift | 8 ++++---- MapboxNavigation/NavigationMapView.swift | 6 +++--- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/MapboxCoreNavigation/CLLocation.swift b/MapboxCoreNavigation/CLLocation.swift index 5c141dfe..f8088b73 100644 --- a/MapboxCoreNavigation/CLLocation.swift +++ b/MapboxCoreNavigation/CLLocation.swift @@ -64,7 +64,8 @@ extension CLLocation { guard let closestCoordinate = LineString(routeStep.coordinates!).closestCoordinate(to: coordinate) else { return false } - return closestCoordinate.distance < maximumDistance + let distance = closestCoordinate.coordinate.distance(to: self.coordinate) + return distance < maximumDistance } // MARK: - Route Snapping @@ -80,8 +81,9 @@ extension CLLocation { guard let firstCoordinate = legProgress.leg.steps.first?.coordinates?.first else { return nil } guard self.shouldSnapCourse(toRouteWith: calculatedCourseForLocationOnStep, distanceToFirstCoordinateOnLeg: coordinate.distance(to: firstCoordinate)) else { return nil } - - guard closest.distance <= (RouteControllerUserLocationSnappingDistance + horizontalAccuracy) else { + + let distanceFromLeg = closest.coordinate.distance(to: self.coordinate) + guard distanceFromLeg <= (RouteControllerUserLocationSnappingDistance + horizontalAccuracy) else { return nil } @@ -145,10 +147,11 @@ extension CLLocation { let averageRelativeAngle: Double // User is at the beginning of the route, there is no closest point behind the user. - = if pointBehindClosest.distance <= 0, pointAheadClosest.distance > 0 { + = if pointBehindClosest.coordinate.distance(to: pointBehind) <= 0, pointAheadClosest.coordinate.distance(to: pointAhead) > 0 { relativeAnglepointAhead // User is at the end of the route, there is no closest point in front of the user. - } else if pointAheadClosest.distance <= 0, pointBehindClosest.distance > 0 { + } else if pointAheadClosest.coordinate.distance(to: pointAhead) <= 0, + pointBehindClosest.coordinate.distance(to: pointBehind) > 0 { relativeAnglepointBehind } else { (relativeAnglepointBehind + relativeAnglepointAhead) / 2 diff --git a/MapboxCoreNavigation/RouteProgress.swift b/MapboxCoreNavigation/RouteProgress.swift index ecef0ab9..bfa2eecb 100644 --- a/MapboxCoreNavigation/RouteProgress.swift +++ b/MapboxCoreNavigation/RouteProgress.swift @@ -371,14 +371,14 @@ open class RouteLegProgress: NSObject { guard let closestCoordOnStep = LineString(coords).closestCoordinate(to: coordinate) else { continue } let foundIndex = currentStepIndex + self.stepIndex - // First time around, currentClosest will be `nil`. + let distanceFromLine = closestCoordOnStep.coordinate.distance(to: coordinate) guard let currentClosestDistance = currentClosest?.distance else { - currentClosest = (index: foundIndex, distance: closestCoordOnStep.distance) + currentClosest = (index: foundIndex, distance: distanceFromLine) continue } - if closestCoordOnStep.distance < currentClosestDistance { - currentClosest = (index: foundIndex, distance: closestCoordOnStep.distance) + if distanceFromLine < currentClosestDistance { + currentClosest = (index: foundIndex, distance: distanceFromLine) } } diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index e33bddf1..11951c3d 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -786,9 +786,9 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { // existance has been assured through use of filter. let leftLine = LineString(left.coordinates!) let rightLine = LineString(right.coordinates!) - let leftDistance = leftLine.closestCoordinate(to: tapCoordinate)!.distance - let rightDistance = rightLine.closestCoordinate(to: tapCoordinate)!.distance - + let leftDistance = leftLine.closestCoordinate(to: tapCoordinate)!.coordinate.distance(to: tapCoordinate) + let rightDistance = rightLine.closestCoordinate(to: tapCoordinate)!.coordinate.distance(to: tapCoordinate) + return leftDistance < rightDistance } From aa7b8beebc3d161621e09e2653580051b1fc7c5f Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 15 Aug 2024 14:54:54 -0700 Subject: [PATCH 6/7] restore accidentally deleted comment --- MapboxCoreNavigation/RouteProgress.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MapboxCoreNavigation/RouteProgress.swift b/MapboxCoreNavigation/RouteProgress.swift index bfa2eecb..7f186c30 100644 --- a/MapboxCoreNavigation/RouteProgress.swift +++ b/MapboxCoreNavigation/RouteProgress.swift @@ -372,6 +372,7 @@ open class RouteLegProgress: NSObject { let foundIndex = currentStepIndex + self.stepIndex let distanceFromLine = closestCoordOnStep.coordinate.distance(to: coordinate) + // First time around, currentClosest will be `nil`. guard let currentClosestDistance = currentClosest?.distance else { currentClosest = (index: foundIndex, distance: distanceFromLine) continue From b1eb01cd3902f4562a6d3ab853aeba4f732fc3e8 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 15 Aug 2024 15:14:27 -0700 Subject: [PATCH 7/7] add debug assert to make sure this method is used how we expect --- MapboxNavigation/NavigationMapView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 11951c3d..ec05641d 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -1078,6 +1078,8 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate { Sets the camera directly over a series of coordinates. */ @objc public func setOverheadCameraView(from userLocation: CLLocationCoordinate2D, along coordinates: [CLLocationCoordinate2D], for bounds: UIEdgeInsets) { + assert(!coordinates.isEmpty, "must specify coordinates when setting overhead camera view") + self.isAnimatingToOverheadMode = true guard let slicedLine = LineString(coordinates).sliced(from: userLocation)?.coordinates else { return