27

Im using dart/flutter and the 'package:latlong/latlong.dart' to parse a GPX file into a list of LatLng objects. That is working fine, but the next step is to find the total distance of the route.

The question here is

how can I get the total distance from a list of LatLng objects in Dart?

I have used Haversine formula before in Java, but not sure the best way to implement it using Dart. Any help of suggestion would be greatly appreciated.

Edit

Below is an attempt to get total distance based on the answer below. For some reason though it doesn't add to totalDistance and doesn't return a double.

The below is suppose to iterate through a list of 60+ LatLng objects and find distance between each one, adding to a totalDistance double which is returned at the end of the loop.

 static double getDistanceFromGPSPointsInRoute(List<LatLng> gpsList) {
    double totalDistance = 0.0;

    for (var i = 0; i < gpsList.length; i++) {
      var p = 0.017453292519943295;
      var c = cos;
      var a = 0.5 -
          c((gpsList[i + 1].latitude - gpsList[i].latitude) * p) / 2 +
          c(gpsList[i].latitude * p) *
              c(gpsList[i + 1].latitude * p) *
              (1 - c((gpsList[i + 1].longitude - gpsList[i].longitude) * p)) /
              2;
      double distance = 12742 * asin(sqrt(a));
      totalDistance += distance;
      print('Distance is ${12742 * asin(sqrt(a))}');
    }
    print('Total distance is $totalDistance');
    return totalDistance;
  }

Output

flutter: Distance is 0.004143962775784678
flutter: Distance is 0.0041439635323316775
flutter: Distance is 0.007796918986828574
flutter: Distance is 0.007285385943437824
flutter: Distance is 0.006890844300938902
flutter: Distance is 0.006353952460010352
flutter: Distance is 0.005560051252981138

As you can see above, there is no mention of Total Distance.

Example of LatLng List

flutter: -36.84975 , 174.646685
flutter: -36.849692 , 174.646497
flutter: -36.84967 , 174.646436
flutter: -36.849578 , 174.646264
flutter: -36.849502 , 174.646164
flutter: -36.849367 , 174.646038
flutter: -36.849209 , 174.645959
flutter: -36.849155 , 174.64594
flutter: -36.849107 , 174.645932
flutter: -36.849058 , 174.645922
flutter: -36.848952 , 174.645895
flutter: -36.84886 , 174.645906
flutter: -36.84879 , 174.645913
flutter: -36.848748 , 174.645836
flutter: -36.848744 , 174.645802
Yonkee
  • 1,781
  • 3
  • 31
  • 56

8 Answers8

71

Try this please. I tested it with Google Maps and works accurately. You can do a loop and find total distance in KM by using 2 points each time. I added some random dummy data to show how it works. Copy this code to https://dartpad.dartlang.org/ and test easily.

import 'dart:math' show cos, sqrt, asin;

void main() {
  double calculateDistance(lat1, lon1, lat2, lon2){
    var p = 0.017453292519943295;
    var c = cos;
    var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;
    return 12742 * asin(sqrt(a));
  }
  
  List<dynamic> data = [
    {
      "lat": 44.968046,
      "lng": -94.420307
    },{
      "lat": 44.33328,
      "lng": -89.132008
    },{
      "lat": 33.755787,
      "lng": -116.359998
    },{
      "lat": 33.844843,
      "lng": -116.54911
    },{
      "lat": 44.92057,
      "lng": -93.44786
    },{
      "lat": 44.240309,
      "lng": -91.493619
    },{
      "lat": 44.968041,
      "lng": -94.419696
    },{
      "lat": 44.333304,
      "lng": -89.132027
    },{
      "lat": 33.755783,
      "lng": -116.360066
    },{
      "lat": 33.844847,
      "lng": -116.549069
    },
  ];
  double totalDistance = 0;
  for(var i = 0; i < data.length-1; i++){
    totalDistance += calculateDistance(data[i]["lat"], data[i]["lng"], data[i+1]["lat"], data[i+1]["lng"]);
  }
  print(totalDistance);
}
Damia Fuentes
  • 5,308
  • 6
  • 33
  • 65
westdabestdb
  • 4,353
  • 20
  • 28
14

I used westdabestdb's answer. It's okay.

And also, you can use geolocator plugin for that.

Geolocator.distanceBetween(lat1, lon1, lat2, lon2);

geolocator doc

or you can use this way without using plugin

BIS Tech
  • 17,000
  • 12
  • 99
  • 148
12

Use the library latlong for common latitude and longitude calculation. This supports both, the "Haversine" and the "Vincenty" algorithm.

List<dynamic> data = [
    {
        "lat": 44.968046,
        "lng": -94.420307
    },
    ...
];


final Distance distance = Distance();
double totalDistanceInM = 0;
double totalDistanceInKm = 0;

for(var i = 0; i < data.length - 1; i++){
    totalDistanceInM += distance(
        LatLng(data[i]["lat"], data[i]["lng"]),
        LatLng(data[i+1]["lat"], data[i+1]["lng"])
    );

    totalDistanceInKm += distance.as(
        LengthUnit.Kilometer, 
        LatLng(data[i]["lat"], data[i]["lng"]), 
        LatLng(data[i+1]["lat"], data[i+1]["lng"]),
    );
}

Update:

Use instead latlong2 that introduce null safety as @Mehul Pamale said in the comments.

Alberto Favaro
  • 1,824
  • 3
  • 21
  • 46
1

This function calculates the distance between two points (given the latitude/longitude of those points).

unit = the unit you desire for results              
      where: 'M' is statute miles (default) 
             'K' is kilometers            
             'N' is nautical miles
String distance(
          double lat1, double lon1, double lat2, double lon2, String unit) {
         double theta = lon1 - lon2;
         double dist = sin(deg2rad(lat1)) * sin(deg2rad(lat2)) +
         cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * cos(deg2rad(theta));
         dist = acos(dist);
         dist = rad2deg(dist);
         dist = dist * 60 * 1.1515;
          if (unit == 'K') {
            dist = dist * 1.609344;
          } else if (unit == 'N') {
            dist = dist * 0.8684;
          }
          return dist.toStringAsFixed(2);
        }

    double deg2rad(double deg) {
      return (deg * pi / 180.0);
    }

    double rad2deg(double rad) {
      return (rad * 180.0 / pi);
    }

    void main() {
      print("Distance : " + distance(32.9697, -96.80322, 29.46786, -98.53506, 'K'));
    }
Mirza Obaid
  • 1,707
  • 3
  • 23
  • 35
  • Please format the code in your question correctly. *[Editing Help- Code](https://stackoverflow.com/editing-help#code) – ejderuby Aug 16 '19 at 14:36
1

I've used the vector_math for converting degree to radians and also the geolocator for getting the current user latitude and longitude if in case searching from the current location also there is a method where in you can calculate the distance between two locations directly as Geolocator.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude).

import 'dart:math' show sin, cos, sqrt, atan2;
import 'package:vector_math/vector_math.dart';
import 'package:geolocator/geolocator.dart';

Position _currentPosition;
double earthRadius = 6371000; 

//Using pLat and pLng as dummy location
double pLat = 22.8965265;   double pLng = 76.2545445; 


//Use Geolocator to find the current location(latitude & longitude)
getUserLocation() async {
   _currentPosition = await GeoLocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
}

//Calculating the distance between two points without Geolocator plugin
getDistance(){
   var dLat = radians(pLat - _currentPosition.latitude);
   var dLng = radians(pLng - _currentPosition.longitude);
   var a = sin(dLat/2) * sin(dLat/2) + cos(radians(_currentPosition.latitude)) 
           * cos(radians(pLat)) * sin(dLng/2) * sin(dLng/2);
   var c = 2 * atan2(sqrt(a), sqrt(1-a));
   var d = earthRadius * c;
   print(d); //d is the distance in meters
}

//Calculating the distance between two points with Geolocator plugin
getDistance(){
   final double distance = Geolocator.distanceBetween(pLat, pLng, 
           _currentPosition.latitude, _currentPosition.longitude); 
   print(distance);
}
Niroop Nife
  • 356
  • 1
  • 5
  • 18
1
  1. Geolocator.distanceBetween(lat1, lon1, lat2, lon2);
  2. print("distance: ${(distance / 1000).toStringAsFixed(0)} KM");
0

You can calculate distance by using this function and pass the latlon from and to destinations it will return the required distance

import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'dart:math';

class DistanceService{
  static double findDistance(LatLng from, LatLng to){
    var lat1 = toRadian(from.latitude);
    var lng1 = toRadian(from.longitude);
    var lat2 = toRadian(to.latitude);
    var lng2 = toRadian(to.longitude);
    
    // Haversine Formula
    var dlong = lng2 - lng1;
    var dlat = lat2 - lat1;

    var res = pow(sin((dlat / 2)), 2) + cos(lat1) * cos(lat2) * pow(sin(dlong / 2), 2);
    res = 2 * asin(sqrt(res));
    double R = 6371;
    res = res * R;
    return res;
  }

  static double toRadian(double val){
    double one_deg = (pi) / 180;
    return (one_deg * val);
  }
}
Noman Hassan
  • 239
  • 2
  • 10
-2
add  geolocator: ^7.1.1 in pubyml


//get current lat and long

  var currentLocation = myLocation;
    dynamic coordinates =
        new Coordinates(myLocation.latitude, myLocation.longitude);

 //getting in meter distance

//Latitude2 and Longitude2 can get anywhere to measure the distance

double distanceInMeters = Geolocator.distanceBetween(Latitude1, Longitude1, Latitude2, Longitude2);