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);
}
}
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