Xamarin - How to calculate distance in realtime vi

2019-08-22 04:34发布

问题:

How can i calculate distance in real time(the distance must increment if there is a movement) via GPS ?

I have an App that shows the travelling speed, and it is accurate. I just need to show the distance that was traveled by the user.

How can i archive this ? Please see my code below :

 public void OnLocationChanged(Location location)
  {
            try
            {
                currentLocation = location;

                if (currentLocation == null)
                {
                    //"Make sure the GPS is on.";
                }
                else
                {
                    gpsLatitude = currentLocation.Latitude.ToString();
                    gpsLongitude = currentLocation.Longitude.ToString();

                    if (currentLocation.Speed != 0)
                    { 
                        kmh = (int)((currentLocation.Speed * 3600) / 1000);
                        //mph = (int)(currentLocation.Speed * 2.2369); 
                    }
                }
            }
            catch (Exception ex)
            {
               LogException(ex);
            }
   }

回答1:

Assuming you are storing the LatLng points as the user travels, the following methods can provide what you need.

There is a ComputeDistanceBetween that returns the meters between to LatLng points and a ComputeLength that returns the total meters between a sequential list of LatLng points.

This is based on SphericalUtil methods from Google's Android Maps Utils and is one of best implementations that I've seen in the public domain.

Note: Google's Java code for that is under Apache License Version 2.0, and I converted it to C#.

Example:

var latlng1 = new LatLng(47.61472695767613, -122.33327865600586);
var latlng2 = new LatLng(47.60269078742121, -122.30581283569336);
var latlng3 = new LatLng(47.608593486245546, -122.3001480102539);
var latlngList = new List<LatLng> { latlng1, latlng2, latlng3 };
var km1 = Meters.ComputeDistanceBetween(latlng1, latlng2);
var km2 = Meters.ComputeDistanceBetween(latlng2, latlng3);
var kmTotal = Meters.ComputeLength(latlngList);

Implementation:

public static class Meters
{
    const double EARTH_RADIUS = 6371009;

    static double ToRadians(double input)
    {
        return input / 180.0 * Math.PI;
    }

    static double DistanceRadians(double lat1, double lng1, double lat2, double lng2)
    {
        double Hav(double x)
        {
            double sinHalf = Math.Sin(x * 0.5);
            return sinHalf * sinHalf;
        }
        double ArcHav(double x)
        {
            return 2 * Math.Asin(Math.Sqrt(x));
        }
        double HavDistance(double lat1b, double lat2b, double dLng)
        {
            return Hav(lat1b - lat2b) + Hav(dLng) * Math.Cos(lat1b) * Math.Cos(lat2b);
        }
        return ArcHav(HavDistance(lat1, lat2, lng1 - lng2));
    }

    public static double ComputeDistanceBetween(LatLng from, LatLng to)
    {
        double ComputeAngleBetween(LatLng From, LatLng To)
        {
            return DistanceRadians(ToRadians(from.Latitude), ToRadians(from.Longitude),
                                          ToRadians(to.Latitude), ToRadians(to.Longitude));
        }
        return ComputeAngleBetween(from, to) * EARTH_RADIUS;
    }

    public static double ComputeLength(List<LatLng> path)
    {
        if (path.Count < 2)
            return 0;

        double length = 0;
        LatLng prev = path[0];
        double prevLat = ToRadians(prev.Latitude);
        double prevLng = ToRadians(prev.Longitude);
        foreach (LatLng point in path)
        {
            double lat = ToRadians(point.Latitude);
            double lng = ToRadians(point.Longitude);
            length += DistanceRadians(prevLat, prevLng, lat, lng);
            prevLat = lat;
            prevLng = lng;
        }
        return length * EARTH_RADIUS;
    }
}

FYI: If you need an area in square meters, see my answer here, also based on Google's Android Maps Utils code

  • Polygon area calculation using Latitude and Longitude