Calculate distance of two geo points in km c#

前端 未结 7 654
夕颜
夕颜 2020-12-03 00:21

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

相关标签:
7条回答
  • 2020-12-03 00:26

    try this... I have used this is apps before -- its pretty accurate. Forgive me for not giving due credit to the brilliant soul who originally published this, I transposed it from java to C#:

    namespace Sample.Geography
    {
        using System;
    
    public class GeodesicDistance
    {
        private static double DegsToRadians(double degrees)
        {
            return (0.017453292519943295 * degrees);
        }
    
        public static double? GetDistance(double lat1, double lon1, double lat2, double lon2)
        {
            long num = 0x615299L;
            double num2 = 6356752.3142;
            double num3 = 0.0033528106647474805;
            double num4 = DegsToRadians(lon2 - lon1);
            double a = Math.Atan((1 - num3) * Math.Tan(DegsToRadians(lat1)));
            double num6 = Math.Atan((1 - num3) * Math.Tan(DegsToRadians(lat2)));
            double num7 = Math.Sin(a);
            double num8 = Math.Sin(num6);
            double num9 = Math.Cos(a);
            double num10 = Math.Cos(num6);
            double num11 = num4;
            double num12 = 6.2831853071795862;
            int num13 = 20;
            double y = 0;
            double x = 0;
            double num18 = 0;
            double num20 = 0;
            double num22 = 0;
            while ((Math.Abs((double) (num11 - num12)) > 1E-12) && (--num13 > 0))
            {
                double num14 = Math.Sin(num11);
                double num15 = Math.Cos(num11);
                y = Math.Sqrt(((num10 * num14) * (num10 * num14)) + (((num9 * num8) - ((num7 * num10) * num15)) * ((num9 * num8) - ((num7 * num10) * num15))));
                if (y == 0)
                {
                    return 0;
                }
                x = (num7 * num8) + ((num9 * num10) * num15);
                num18 = Math.Atan2(y, x);
                double num19 = ((num9 * num10) * num14) / y;
                num20 = 1 - (num19 * num19);
                if (num20 == 0)
                {
                    num22 = 0;
                }
                else
                {
                    num22 = x - (((2 * num7) * num8) / num20);
                }
                double num21 = ((num3 / 16) * num20) * (4 + (num3 * (4 - (3 * num20))));
                num12 = num11;
                num11 = num4 + ((((1 - num21) * num3) * num19) * (num18 + ((num21 * y) * (num22 + ((num21 * x) * (-1 + ((2 * num22) * num22)))))));
            }
            if (num13 == 0)
            {
                return null;
            }
            double num23 = (num20 * ((num * num) - (num2 * num2))) / (num2 * num2);
            double num24 = 1 + ((num23 / 16384) * (4096 + (num23 * (-768 + (num23 * (320 - (175 * num23)))))));
            double num25 = (num23 / 1024) * (256 + (num23 * (-128 + (num23 * (74 - (47 * num23))))));
            double num26 = (num25 * y) * (num22 + ((num25 / 4) * ((x * (-1 + ((2 * num22) * num22))) - ((((num25 / 6) * num22) * (-3 + ((4 * y) * y))) * (-3 + ((4 * num22) * num22))))));
            return new double?((num2 * num24) * (num18 - num26));
        }
    }
    }
    
    0 讨论(0)
  • 2020-12-03 00:30

    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

    0 讨论(0)
  • 2020-12-03 00: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,

    0 讨论(0)
  • 2020-12-03 00:31

    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.

    0 讨论(0)
  • 2020-12-03 00:37

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

    0 讨论(0)
  • 2020-12-03 00:42

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

    0 讨论(0)
提交回复
热议问题