Swift中Google Maps已行驶路径移除问题:现有代码偶发失效求助
Hey there! Let's break down why your path removal logic is hit-or-miss and get it working consistently.
The Core Issues in Your Current Code
First, let's unpack what's going wrong:
- Incorrect location comparison: Checking
currentLat <= pathLat || currentLong <= pathLongdoesn't make sense for geographic coordinates. Paths can go in any direction (south means decreasing latitude, west means decreasing longitude), so this condition can't accurately tell if you've passed a path point. - Rounding precision loss: Even rounding to 5 decimal places can cause mismatches when your current location sits right at the rounding boundary.
- Uneven path point spacing: Since the Direction API returns points with variable distances between them, looping through indices with your current logic often skips segments you should remove or keeps segments you've already traveled.
A Reliable Solution
Instead of comparing coordinate values directly, we'll use distance calculations and Google Maps' geometry utilities to accurately determine which part of the path you've already traveled. Here's the revised code:
import GoogleMapsUtils // Make sure this framework is added to your project func updateTravelledPath(currentLoc: CLLocationCoordinate2D){ // Safely unwrap the original path to avoid crashes guard let originalPath = self.route?.path, originalPath.count() > 0 else { return } let currentLocation = CLLocation(latitude: currentLoc.latitude, longitude: currentLoc.longitude) var splitIndex: UInt = 0 let proximityThreshold: CLLocationDistance = 10.0 // Adjust based on use case (5m for walking, 20m for driving) // Find the closest path point to the current location var closestIndex: UInt = 0 var minDistance = Double.greatestFiniteMagnitude for i in 0..<originalPath.count() { let pathCoord = originalPath.coordinate(at: i) let pathLocation = CLLocation(latitude: pathCoord.latitude, longitude: pathCoord.longitude) let distance = currentLocation.distance(from: pathLocation) if distance < minDistance { minDistance = distance closestIndex = i } } // Only split the path if we're close enough to the closest point if minDistance <= proximityThreshold { splitIndex = closestIndex } else { // Fallback: Use the closest index if we're not near any path point splitIndex = closestIndex } // Build the new path from the split point to the destination let newPath = GMSMutablePath() for i in splitIndex..<originalPath.count() { newPath.add(originalPath.coordinate(at: i)) } // Update the route and refresh the polyline on the main thread self.route?.path = newPath DispatchQueue.main.async { // Clean up the old polyline self.route?.polyLinee?.map = nil // Create and configure the new polyline let newPolyline = GMSPolyline(path: newPath) newPolyline.strokeWidth = 5.0 newPolyline.strokeColor = #colorLiteral(red: 0.02352941176, green: 0.5725490196, blue: 0.4666666667, alpha: 1) newPolyline.map = self.mapView // Update your route's references self.route?.polyLinee = newPolyline self.route?.polyLine = [newPolyline] self.mapView.reloadInputViews() } } extension Double { func rounded(toPlaces places:Int) -> Double { let divisor = pow(10.0, Double(places)) return (self * divisor).rounded() / divisor } }
Key Improvements Explained
- Safe optional handling: Uses
guard letto avoid crashes if the path is nil or empty. - Distance-based location check: Finds the closest path point to your current location, ensuring we're using geographic distance instead of arbitrary coordinate comparisons.
- Proximity threshold: Lets you adjust how close you need to be to a path point before truncating the path, accounting for minor location inaccuracies.
- Cleaner polyline updates: Simplifies removing the old polyline and adding the new one, reducing bugs from redundant code.
Bonus: Even More Precision
For better handling of uneven path spacing, you can use GMSGeometryProjectPointOnPath to find the exact projection of your current location onto the path, then determine which segment it's on. This ensures you truncate the path exactly where you've traveled, even if the API returns sparse points in some areas.
内容的提问来源于stack exchange,提问作者deepak varshney

