iosswiftcllocationmanagercllocationcllocationdistance

Calculating trip distance core location swift


I have an application where I calculate distance travelled like the Uber application. When a driver starts a trip, the location begins to change even though a start point has been specified in the search for a ride, a driver could decide to pass an alternative route or pass long places and routes because he/ she does not know the shortest route, how then do I calculate the total distance.

The starting location is the location the driver hits start button The end location is the location the driver hits stop button

this is my code so far

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

        if !hasSetInitialLocation {

            let camera = GMSCameraPosition.camera(withTarget: lastLocation!.coordinate, zoom: 17)
            self.mapView.animate(to: camera)
            hasSetInitialLocation = true
            endTrip(lastLocation)
            MqttManager.instance.connectToServer()
        }
    }



func endTrip(endLoaction: CLLocation) {
        guard let statusChange = source.getStatusChange() else{return}
        var distanceTraveled: Double = 0.0
        let initialLocation = CLLocation(latitude: (statusChange.meta?.location?.lat)!, longitude: (statusChange.meta?.location?.lng)!)
        let distance = initialLocation.distance(from: endLoaction)
        distanceTraveled += distance
        let distanceInKM = Utility.convertCLLocationDistanceToKiloMeters(targetDistance: distanceTraveled)
}

How can i calculate the distance to reflect the total distance moved by the driver since there could be a change in route from the proposed start point and end point.

The driver hits a button called start trip, I want to get the distance from that moment till the moment he hits the button end trip

this implementation could be got from a similar working code like these but the only difference is that their is a start button which passes the coordinates at that point and a stop coordinate which is the end of the coordinate.

enum DistanceValue: Int {
                case meters, miles
            }

            func calculateDistanceBetweenLocations(_ firstLocation: CLLocation, secondLocation: CLLocation, valueType: DistanceValue) -> Double {
                var distance = 0.0
                let meters = firstLocation.distance(from: secondLocation)
                distance += meters
                switch valueType {
                case .meters:
                    return distance
                case .miles:
                    let miles = distance
                    return miles
                }
            }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            if startLocation == nil {
                startLocation = locations.first
            } else if let location = locations.last {
                runDistance += lastLocation.distance(from: location)
                let calc = calculateDistanceBetweenLocations(lastLocation, secondLocation: location, valueType: .meters)

                print("TOTAL LOC 1 \(calc)")
                print("TOTAL LOC 2 \(runDistance)")
            }
            lastLocation = locations.last

        }

as shown in my print statements print("TOTAL LOC 1 \(calc)") print("TOTAL LOC 2 \(runDistance)") how can I make

calc the same with runDistance

here is what is printed in the console

TOTAL LOC 10.29331530774379
TOTAL LOC 2 10.29331530774379
TOTAL LOC 2.2655118031831587
TOTAL LOC 2 12.558827110926948

Solution

  • If you get the distance like this using the first and last coordinate it always returns the wrong value because it can't identify the actual traveling path.

    I did resolve the same issue with using the following code.

    use GoogleMaps

    > pod 'GoogleMaps'
    

    Make the coordinates array while the driver is moving on a route.

    var arr = [Any]() 
    // Driving lat long co-ordinateds continues add in this array according to your expectation either update location or perticuler time duration.
    
    // make GMSMutablePath of your co-ordinates
    let path = GMSMutablePath()
    
        for obj in arr{
    
            print(obj)
    
            if let lat = (obj as? NSDictionary)?.value(forKey: PARAMETERS.LET) as? String{
    
                path.addLatitude(Double(lat)!, longitude: Double(((obj as? NSDictionary)?.value(forKey: PARAMETERS.LONG) as? String)!)!)
    
            }
        }
    
    print(path) // Here is your traveling path
    let km = GMSGeometryLength(path)
    print(km) // your total traveling distance.
    

    I did it in this app and it's working fine. Hope it will helps you :)

    OR without GoogleMaps

    You have to come with locations, an array of CLLocationCoordinate2D, for yourself, as per your code, though.

    class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
        // MARK: - Variables
        let locationManager = CLLocationManager()
    
        // MARK: - IBOutlet
        @IBOutlet weak var mapView: MKMapView!
    
        // MARK: - IBAction
        @IBAction func distanceTapped(_ sender: UIBarButtonItem) {
            let locations: [CLLocationCoordinate2D] = [...]
            var total: Double = 0.0
            for i in 0..<locations.count - 1 {
                let start = locations[i]
                let end = locations[i + 1]
                let distance = getDistance(from: start, to: end)
                total += distance
            }
            print(total)
        }
    
        func getDistance(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) -> CLLocationDistance {
            // By Aviel Gross
            // https://stackoverflow.com/questions/11077425/finding-distance-between-cllocationcoordinate2d-points
            let from = CLLocation(latitude: from.latitude, longitude: from.longitude)
            let to = CLLocation(latitude: to.latitude, longitude: to.longitude)
            return from.distance(from: to)
        }
    }
    

    Output

    enter image description here