简体   繁体   中英

Remove travelled path from GMSPolyline on GMSMapView Swift iOS

I am using google distance api [" https://maps.googleapis.com/maps/api/directions/json?origin= " +start.latitude + "," + start.longitude +"&destination=" + end.latitude +"," + end.longitude + "&alternatives=false" +"&mode=driving&key=" + key;] to get route from start location to end location.

I am using the following code to draw route between my start and destination location

func drawPath()
{
    if polylines != nil {
        polylines?.map = nil
        polylines = nil
    }

    if animationPolyline != nil {
        self.animationIndex = 0
        self.animationPath = GMSMutablePath()
        self.animationPolyline.map = nil
        if self.timer != nil {
            self.timer.invalidate()
        }
    }


    setupStartRideLocationMarkup(CLLocationCoordinate2D(latitude: (currentLocation?.coordinate.latitude)!, longitude: (currentLocation?.coordinate.longitude)!))

    if currentLocation != nil && destinationLocation != nil {
        let origin = "\((currentLocation?.coordinate.latitude)!),\((currentLocation?.coordinate.longitude)!)"
        let destination = "\((destinationLocation?.latitude)!),\((destinationLocation?.longitude)!)"


        let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving&key=MY_API_KEY"

        Alamofire.request(url).responseJSON { response in


            let json = JSON(data: response.data!)
            self.jsonRoute = json
            let routes = json["routes"].arrayValue

            for route in routes
            {
                let routeOverviewPolyline = route["overview_polyline"].dictionary
                let points = routeOverviewPolyline?["points"]?.stringValue
                self.path = GMSPath.init(fromEncodedPath: points!)!
                self.polylines = GMSPolyline.init(path: self.path)
                self.polylines?.geodesic = true
                self.polylines?.strokeWidth = 5
                self.polylines?.strokeColor = UIColor.black
                self.polylines?.map = self.mapView
            }

            self.shouldDrawPathToStartLocation()
            self.shouldDrawPathToEndLocation()

            if routes.count > 0 {
                self.startAnimatingMap()
            }
        }
    }
}

As you can see I am initialising path with encoded path from the api. Now I want to remove travelled GMSPolyline from the overall path How can I do that? My current intiuation is that it will be from didUpdateLocations Here's my code of didUpdateLocations method

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    currentLocation = locations.last!

    let camera = GMSCameraPosition.camera(withLatitude: (currentLocation?.coordinate.latitude)!,
                                          longitude: (currentLocation?.coordinate.longitude)!,
                                          zoom: zoomLevel)

    if (mapView?.isHidden)! {
        mapView?.isHidden = false
        mapView?.camera = camera
    } else {
        mapView?.animate(to: camera)
    }

    updatePolyLineIfRequired()

}

And in updatePolyLineIfRequired I want to remove travelled poly lines

func updatePolyLineIfRequired(){
    if GMSGeometryIsLocationOnPath((currentLocation?.coordinate)!, path, true) {
        if startPolyline != nil {
            startPolyline?.map = nil
            startPolyline = nil
        }

    }
}

I want to implement solution like Uber or Careem where travelled drawn GMSPolyline gets removed till user current location.

Thanks in Advance PS I am using Alamofire SwiftyJSON

There are two solutions for this:-

  1. Calling Directions Api each time didUpdateLocations function is called.(Not efficient)
  2. Removing the travelled coordinates from the GMSPath.

Calling Directions api will be not useful unless your request limit for Direction api is less.

For removing the travelled coordinates from the path:-

    //Call this function in didUpdateLocations
func updateTravelledPath(currentLoc: CLLocationCoordinate2D){
    var index = 0
    for i in 0..<self.path.count(){
        let pathLat = Double(self.path.coordinate(at: i).latitude).rounded(toPlaces: 3)
        let pathLong = Double(self.path.coordinate(at: i).longitude).rounded(toPlaces: 3)

        let currentLaenter code heret = Double(currentLoc.latitude).rounded(toPlaces: 3)
        let currentLong = Double(currentLoc.longitude).rounded(toPlaces: 3)

        if currentLat == pathLat && currentLong == pathLong{
            index = Int(i)
            break   //Breaking the loop when the index found
        }
    }

   //Creating new path from the current location to the destination
    let newPath = GMSMutablePath()    
    for i in index..<Int(self.path.count()){
        newPath.add(self.path.coordinate(at: UInt(i)))
    }
    self.path = newPath
    self.polyline.map = nil
    self.polyline = GMSPolyline(path: self.path)
    self.polyline.strokeColor = UIColor.darkGray
    self.polyline.strokeWidth = 2.0
    self.polyline.map = self.mapView
}

The lat and longs are rounded of so that if the user is nearby the travelled location. Use the following extension to round of upto 3 decimal places or more according to requirement.

extension Double {
// Rounds the double to decimal places value
func rounded(toPlaces places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return (self * divisor).rounded() / divisor
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM