Dziś chciałem się podzielić dwoma funkcjami związanymi z GPS. Pierwsza z nich w oblicza odległość między dwoma punktami. Odległość podawana jest w metrach.

/// <summary>
/// Calculates the distance between two points.
/// </summary>
/// <param name="firstCoordinate">The first coordinate.</param>
/// <param name="secondCoordinate">The second coordinate.</param>
/// <returns>Distance between points in meters</returns>
private static double CalculateDistance(GeoCoordinate firstCoordinate, GeoCoordinate secondCoordinate)
{
    double R = 6371.0; // km
    double lon1 = DegToRad(firstCoordinate.Longitude);
    double lat1 = DegToRad(firstCoordinate.Latitude);

    double lon2 = DegToRad(secondCoordinate.Longitude);
    double lat2 = DegToRad(secondCoordinate.Latitude);

    double dLat = lat2 - lat1;
    double dLon = lon2 - lon1;

    double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
    double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
    return R * c * 1000;
}

Druga natomiast funkcja służy do znalezienia współrzędnych punktu, który znajduje po środku dwóch podanych punktów.

/// <summary>
/// Calculates the middle point coordinate.
/// </summary>
/// <param name="firstCoordinate">The first coordinate.</param>
/// <param name="secondCoordinate">The second coordinate.</param>
/// <returns>Middle point coordinate</returns>
private GeoCoordinate CalculateMidPoint(GeoCoordinate firstCoordinate, GeoCoordinate secondCoordinate)
{
    double lon1 = DegToRad(firstCoordinate.Longitude);
    double lat1 = DegToRad(firstCoordinate.Latitude);

    double lon2 = DegToRad(secondCoordinate.Longitude);
    double lat2 = DegToRad(secondCoordinate.Latitude);

    double deltaLong = lon2 - lon1;

    double Bx = Math.Cos(lat2) * Math.Cos(deltaLong);
    double By = Math.Cos(lat2) * Math.Sin(deltaLong);
    double lat3 = RadToDeg(Math.Atan2(Math.Sin(lat1) + Math.Sin(lat2), Math.Sqrt((Math.Cos(lat1) + Bx) * (Math.Cos(lat1) + Bx) + By * By)));
    double lon3 = RadToDeg(lon1 + Math.Atan2(By, Math.Cos(lat1) + Bx));

    return new GeoCoordinate(lat3, lon3);
}

Obie funkcje korzystają z dwóch metod pomocniczych, które przekształcają stopnie na radiany i odwrotnie.

/// <summary>
/// Converts radians to degrees
/// </summary>
/// <param name="radians">The radians.</param>
/// <returns>The degrees.</returns>
private static double RadToDeg(double radians)
{
    return radians * (180 / Math.PI);
}

/// <summary>
/// Converts degrees to radians
/// </summary>
/// <param name="degrees">The degrees.</param>
/// <returns>The radians</returns>
private static double DegToRad(double degrees)
{
    return degrees * (Math.PI / 180);
}

Mam nadzieję, że komuś przydadzą się te funkcje.