Calculate distance of two geo points in km c#

2020-01-30 08:00发布

I`d like calculate the distance of two geo points. the points are given in longitude and latitude.

the coordinates are:

point 1: 36.578581, -118.291994

point 2: 36.23998, -116.83171

here a website to compare the results:

http://www.movable-type.co.uk/scripts/latlong.html

here the code I used from this link: Calculate distance between two points in google maps V3

    const double PIx = Math.PI;
    const double RADIO = 6378.16;

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(double lon1, double lat1, double lon2, double lat2)
    {
        double R = 6371; // km
        double dLat = Radians(lat2 - lat1);
        double dLon = Radians(lon2 - lon1);
        lat1 = Radians(lat1);
        lat2 = Radians(lat2);

        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));
        double d = R * c;

        return d;
    }


Console.WriteLine(DistanceAlgorithm.DistanceBetweenPlaces(36.578581, -118.291994, 36.23998, -116.83171));

the issue is that I get two different results.

my result: 163,307 km

result of the website: 136 km

any suggestions???

torti

7条回答
smile是对你的礼貌
2楼-- · 2020-01-30 08:25

I think you are interchanging latitude and longitude values. Try correcting those or change sequence of parameters.

查看更多
▲ chillily
3楼-- · 2020-01-30 08:30

In my article published several years ago (link: http://www.codeproject.com/Articles/469500/Edumatter-School-Math-Calculators-and-Equation-Sol) I have described 3 useful Functions to calculate the distance between 2 geo-points (in other words, great-circle (orthodromic) distance on Earth between 2 geo-points), which differs in terms of accuracy/performance:

// Haversine formula to calculate great-circle distance between two points on Earth

    private const double _radiusEarthMiles = 3959;
    private const double _radiusEarthKM = 6371;
    private const double _m2km = 1.60934;
    private const double _toRad = Math.PI / 180;

    /// <summary>
    /// Haversine formula to calculate 
    /// great-circle (orthodromic) distance on Earth 
    /// High Accuracy, Medium speed
    /// </summary>
    /// <param name="Lat1">double: 1st point Latitude</param>
    /// <param name="Lon1">double: 1st point Longitude</param>
    /// <param name="Lat2">double: 2nd point Latitude</param>
    /// <param name="Lon2">double: 2nd point Longitude</param>
    /// <returns>double: distance in miles</returns>
    public static double DistanceMilesHaversine(double Lat1,
                                                double Lon1,
                                                double Lat2,
                                                double Lon2)
    {
        try
        {
            double _radLat1 = Lat1 * _toRad;
            double _radLat2 = Lat2 * _toRad;
            double _dLatHalf = (_radLat2 - _radLat1) / 2;
            double _dLonHalf = Math.PI * (Lon2 - Lon1) / 360;

            // intermediate result
            double _a = Math.Sin(_dLatHalf);
            _a *= _a;

            // intermediate result
            double _b = Math.Sin(_dLonHalf);
            _b *= _b * Math.Cos(_radLat1) * Math.Cos(_radLat2);

            // central angle, aka arc segment angular distance
            double _centralAngle = 2 * Math.Atan2(Math.Sqrt(_a + _b), Math.Sqrt(1 - _a - _b));

            // great-circle (orthodromic) distance on Earth between 2 points
            return _radiusEarthMiles * _centralAngle;
        }
        catch { throw; }
    }

// Spherical law of cosines formula to calculate great-circle distance between two points on Earth

       /// <summary>
        /// Spherical Law of Cosines formula to calculate 
        /// great-circle (orthodromic) distance on Earth;
        /// High Accuracy, Medium speed
        /// http://en.wikipedia.org/wiki/Spherical_law_of_cosines
        /// </summary>
        /// <param name="Lat1">double: 1st point Latitude</param>
        /// <param name="Lon1">double: 1st point Longitude</param>
        /// <param name="Lat2">double: 2nd point Latitude</param>
        /// <param name="Lon2">double: 2nd point Longitude</param>
        /// <returns>double: distance in miles</returns>
        public static double DistanceMilesSLC(  double Lat1, 
                                                double Lon1, 
                                                double Lat2, 
                                                double Lon2)
        {
            try
            {
                double _radLat1 = Lat1 * _toRad;
                double _radLat2 = Lat2 * _toRad;
                double _radLon1 = Lon1 * _toRad;
                double _radLon2 = Lon2 * _toRad;

                // central angle, aka arc segment angular distance
                double _centralAngle = Math.Acos(Math.Sin(_radLat1) * Math.Sin(_radLat2) +
                        Math.Cos(_radLat1) * Math.Cos(_radLat2) * Math.Cos(_radLon2 - _radLon1));

                // great-circle (orthodromic) distance on Earth between 2 points
                return _radiusEarthMiles * _centralAngle;
            }
            catch { throw; }
        }

// Great-circle distance calculation using Spherical Earth projection formula**

/// <summary>
/// Spherical Earth projection to a plane formula (using Pythagorean Theorem)
/// to calculate great-circle (orthodromic) distance on Earth.
/// http://en.wikipedia.org/wiki/Geographical_distance
/// central angle = 
/// Sqrt((_radLat2 - _radLat1)^2 + (Cos((_radLat1 + _radLat2)/2) * (Lon2 - Lon1))^2)
/// Medium Accuracy, Fast,
/// relative error less than 0.1% in search area smaller than 250 miles
/// </summary>
/// <param name="Lat1">double: 1st point Latitude</param>
/// <param name="Lon1">double: 1st point Longitude</param>
/// <param name="Lat2">double: 2nd point Latitude</param>
/// <param name="Lon2">double: 2nd point Longitude</param>
/// <returns>double: distance in miles</returns>
public static double DistanceMilesSEP(double Lat1,
                                      double Lon1,
                                      double Lat2,
                                      double Lon2)
{
    try
    {
        double _radLat1 = Lat1 * _toRad;
        double _radLat2 = Lat2 * _toRad;
        double _dLat = (_radLat2 - _radLat1);
        double _dLon = (Lon2 - Lon1) * _toRad;

        double _a = (_dLon) * Math.Cos((_radLat1 + _radLat2) / 2);

        // central angle, aka arc segment angular distance
        double _centralAngle = Math.Sqrt(_a * _a + _dLat * _dLat);

        // great-circle (orthodromic) distance on Earth between 2 points
        return _radiusEarthMiles * _centralAngle;
    }
    catch { throw; }
}

Functions return results in miles; to find the distance in km multiply the result by 1.60934 (see private const double _m2km = 1.60934).

Pertinent to the sample: find the distance point1 (36.578581, -118.291994) and point2 (36.23998, -116.83171) the three aforementioned Function produced the following results (km):

136.00206654936932
136.00206654937023
136.00374497149613

and the calculator (link: http://www.movable-type.co.uk/scripts/latlong.html) gave the result: 136.0

Hope this may help. Best regards,

查看更多
Rolldiameter
4楼-- · 2020-01-30 08:32

I just tried to code at GeoDataSource, and it worked perfectly well: http://www.geodatasource.com/developers/c-sharp

查看更多
Fickle 薄情
5楼-- · 2020-01-30 08:33

I used the formula from Wikipedia and put it in a lambda function:

Func<double, double, double, double, double> CalcDistance = (lat1, lon1, lat2, lon2) =>
        {
            Func<double, double> Radians = (angle) =>
            {
                return angle * (180.0 / Math.PI);
            };

            const double radius = 6371;

            double delataSigma = Math.Acos(Math.Sin(Radians(lat1)) * Math.Sin(Radians(lat2)) +
                Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * Math.Cos(Math.Abs(Radians(lon2) - Radians(lon1))));

            double distance = radius * delataSigma;

            return distance;
        };
查看更多
Summer. ? 凉城
6楼-- · 2020-01-30 08:34

Your formula is almost correct, but you have to swap parameters for longitude an latitude

Console.WriteLine(DistanceAlgorithm.DistanceBetweenPlaces(-118.291994, 36.578581, -116.83171, 36.23998)); // = 136 km

I'm using simplified formula:

// cos(d) = sin(φА)·sin(φB) + cos(φА)·cos(φB)·cos(λА − λB),
//  where φА, φB are latitudes and λА, λB are longitudes
// Distance = d * R
public static double DistanceBetweenPlaces(double lon1, double lat1, double lon2, double lat2)
{
    double R = 6371; // km

    double sLat1 = Math.Sin(Radians(lat1));
    double sLat2 = Math.Sin(Radians(lat2));
    double cLat1 = Math.Cos(Radians(lat1));
    double cLat2 = Math.Cos(Radians(lat2));
    double cLon = Math.Cos(Radians(lon1) - Radians(lon2));

    double cosD = sLat1*sLat2 + cLat1*cLat2*cLon;

    double d = Math.Acos(cosD);

    double dist = R * d;

    return dist;
}

Testing:

(Distance at Equator): Longitudes 0, 100; Latitudes = 0,0; DistanceBetweenPlaces(0, 0, 100, 0) = 11119.5 km

(Distance at North Pole): Longitudes 0, 100; Latitudes = 90,90; DistanceBetweenPlaces(0, 90, 100, 90) = 0 km

Longitudes: -118.291994, -116.83171; Latitudes: 36.578581, 36.23998 = 135.6 km

Longitudes: 36.578581, 36.23998; Latitudes: -118.291994, -116.83171 = 163.2 km

Best regards

P.S. At web site you use for result comparison, for every point first text box is latitude, second - longitude

查看更多
【Aperson】
7楼-- · 2020-01-30 08:34

As you are using the framework 4.0, I would suggest the GeoCoordinate class.

// using System.Device.Location;

GeoCoordinate c1 = new GeoCoordinate(36.578581, -118.291994);
GeoCoordinate c2 = new GeoCoordinate(36.23998, -116.83171);

double distanceInKm = c1.GetDistanceTo(c2) / 1000;
// Your result is: 136,111419742602

You have to add a reference to System.Device.dll.

查看更多
登录 后发表回答