How to find distance from the latitude and longitude of two locations?












22















I have a set of latitudes and longitudes of locations.




  • How to find distance from one location in the set to another?

  • Is there a formula ?










share|improve this question





























    22















    I have a set of latitudes and longitudes of locations.




    • How to find distance from one location in the set to another?

    • Is there a formula ?










    share|improve this question



























      22












      22








      22


      13






      I have a set of latitudes and longitudes of locations.




      • How to find distance from one location in the set to another?

      • Is there a formula ?










      share|improve this question
















      I have a set of latitudes and longitudes of locations.




      • How to find distance from one location in the set to another?

      • Is there a formula ?







      algorithm math geography






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 27 '12 at 5:13







      ArK

















      asked Sep 14 '09 at 6:56









      ArKArK

      11.7k3796133




      11.7k3796133
























          13 Answers
          13






          active

          oldest

          votes


















          29














          The Haversine formula assumes a spherical earth. However, the shape of the earh is more complex. An oblate spheroid model will give better results.



          If such accuracy is needed, you should better use Vincenty inverse formula.
          See http://en.wikipedia.org/wiki/Vincenty's_formulae for details. Using it, you can get a 0.5mm accuracy for the spheroid model.



          There is no perfect formula, since the real shape of the earth is too complex to be expressed by a formula. Moreover, the shape of earth changes due to climate events (see http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), and also changes over time due to the rotation of the earth.



          You should also note that the method above does not take altitudes into account, and assumes a sea-level oblate spheroid.



          Edit 10-Jul-2010: I found out that there are rare situations for which Vincenty inverse formula does not converge to the declared accuracy. A better idea is to use GeographicLib (see http://sourceforge.net/projects/geographiclib/) which is also more accurate.






          share|improve this answer





















          • 3





            +1 this caught quite a few people off guard at a previous employer.

            – Dan Blair
            Sep 14 '09 at 16:34











          • Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

            – PeterAllenWebb
            Sep 17 '09 at 17:45











          • +1 for "answer depends on the degree of accuracy required"

            – Piskvor
            Sep 26 '10 at 16:19











          • I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

            – ToolmakerSteve
            Nov 25 '18 at 19:10





















          9














          Here's one: http://www.movable-type.co.uk/scripts/latlong.html



          Using Haversine formula:



          R = earth’s radius (mean radius = 6,371km)
          Δlat = lat2− lat1
          Δlong = long2− long1
          a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
          c = 2.atan2(√a, √(1−a))
          d = R.c





          share|improve this answer































            5














            Apply the Haversine formula to find the distance. See the C# code below to find the distance between 2 coordinates. Better still if you want to say find a list of stores within a certain radius, you could apply a WHERE clause in SQL or a LINQ filter in C# to it.



            The formula here is in kilometres, you will have to change the relevant numbers and it will work for miles.



            E.g: Convert 6371.392896 to miles.



                DECLARE @radiusInKm AS FLOAT
            DECLARE @lat2Compare AS FLOAT
            DECLARE @long2Compare AS FLOAT
            SET @radiusInKm = 5.000
            SET @lat2Compare = insert_your_lat_to_compare_here
            SET @long2Compare = insert_you_long_to_compare_here

            SELECT * FROM insert_your_table_here WITH(NOLOCK)
            WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
            , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
            ))) <= @radiusInKm


            If you would like to perform the Haversine formula in C#,



                double resultDistance = 0.0;
            double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average.

            //Haversine formula
            //distance = R * 2 * aTan2 ( square root of A, square root of 1 - A )
            // where A = sinus squared (difference in latitude / 2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude / 2))
            // and R = the circumference of the earth

            double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
            double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
            double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong / 2) * Math.Sin(differenceInLong / 2);
            double aFormula = (Math.Sin((differenceInLat) / 2) * Math.Sin((differenceInLat) / 2)) + (aInnerFormula);
            resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula));


            DegreesToRadian is a function I custom created, its is a simple 1 liner of"Math.PI * angle / 180.0



            My blog entry - SQL Haversine






            share|improve this answer

































              4














              Are you looking for



              Haversine formula




              The haversine formula is an equation
              important in navigation, giving
              great-circle distances between two
              points on a sphere from their
              longitudes and latitudes. It is a
              special case of a more general formula
              in spherical trigonometry, the law of
              haversines, relating the sides and
              angles of spherical "triangles".







              share|improve this answer































                3














                Have a look at this.. has a javascript example as well.



                Find Distance






                share|improve this answer
























                • Very cool! nice find

                  – Paul Gregoire
                  Sep 27 '10 at 16:34











                • Link only answers can invalidate over time, and so are less useful.

                  – Richard
                  Nov 25 '18 at 18:41



















                2














                Use the Great Circle Distance Formula.






                share|improve this answer
























                • Link only answers can invalidate over time, and so are less useful.

                  – Richard
                  Nov 25 '18 at 18:41



















                1














                This link has all the info you need, either on it or linked.






                share|improve this answer
























                • Link only answers can invalidate over time, and so are less useful.

                  – Richard
                  Nov 25 '18 at 18:41



















                1














                here is a fiddle with finding locations / near locations to long/lat by given IP:



                http://jsfiddle.net/bassta/zrgd9qc3/2/



                And here is the function I use to calculate the distance in straight line:



                function distance(lat1, lng1, lat2, lng2) {
                var radlat1 = Math.PI * lat1 / 180;
                var radlat2 = Math.PI * lat2 / 180;
                var radlon1 = Math.PI * lng1 / 180;
                var radlon2 = Math.PI * lng2 / 180;
                var theta = lng1 - lng2;
                var radtheta = Math.PI * theta / 180;
                var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
                dist = Math.acos(dist);
                dist = dist * 180 / Math.PI;
                dist = dist * 60 * 1.1515;

                //Get in in kilometers
                dist = dist * 1.609344;

                return dist;
                }


                It returns the distance in Kilometers






                share|improve this answer
























                • Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                  – ToolmakerSteve
                  Nov 25 '18 at 12:53











                • Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                  – Христо Панайотов
                  Nov 25 '18 at 13:10











                • Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                  – ToolmakerSteve
                  Nov 25 '18 at 15:04











                • This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                  – Richard
                  Nov 25 '18 at 18:44



















                1














                If you are measuring distances less than (perhaps) 1 degree lat/long change, are looking for a very high performance approximation, and are willing to accept more inaccuracy than Haversine formula, consider these two alternatives:



                (1) "Polar Coordinate Flat-Earth Formula" from Computing Distances:



                a = pi/2 - lat1  
                b = pi/2 - lat2
                c = sqrt( a^2 + b^2 - 2 * a * b * cos(lon2 - lon1) )
                d = R * c


                (2) Pythagorean theorem adjusted for latitude, as seen in Ewan Todd's SO post:



                d_ew = (long1 - long0) * cos(average(lat0, lat1))  
                d_ns = (lat1 - lat0)
                d = sqrt(d_ew * d_ew + d_ns * d_ns)


                NOTES:

                Compared to Ewan's post, I've substituted average(lat0, lat1) for lat0 inside of cos( lat0 ).



                #2 is vague on whether values are degrees, radians, or kilometers; you will need some conversion code as well. See my complete code at bottom of this post.



                #1 is designed to work well even near the poles, though if you are measuring a distance whose endpoints are on "opposite" sides of the pole (longitudes differ by more than 90 degrees?), Haversine is recommended instead, even for small distances.



                I haven't thoroughly measured errors of these approaches, so you should take representative points for your application, and compare results to some high-quality library, to decide if the accuracies are acceptable. For distances less than a few kilometers my gut sense is that these are within 1% of correct measurement.





                An alternative way to gain high performance (when applicable):



                If you have a large set of static points, within one or two degrees of longitude/latitude, that you will then be calculating distances from a small number of dynamic (moving) points, consider converting your static points ONCE to the containing UTM zone (or to any other local Cartesian coordinate system), and then doing all your math in that Cartesian coordinate system.

                Cartesian = flat earth = Pythagorean theorem applies, so distance = sqrt(dx^2 + dy^2).



                Then the cost of accurately converting the few moving points to UTM is easily afforded.





                CAVEAT for #1 (Polar): May be very wrong for distances less than 0.1 (?) meter. Even with double precision math, the following coordinates, whose true distance is about 0.005 meters, was given as "zero" by my implementation of Polar algorithm:



                inputs:



                    lon1Xdeg    16.6564465477996    double
                lat1Ydeg 57.7760262271983 double
                lon2Xdeg 16.6564466358281 double
                lat2Ydeg 57.776026248554 double


                results:



                Oblate spheroid formula:  
                0.00575254911118364 double
                Haversine:
                0.00573422966122257 double
                Polar:
                0


                this was due to the two factors u and v exactly canceling each other:



                    u   0.632619944868587   double
                v -0.632619944868587 double


                In another case, it gave a distance of 0.067129 m when the oblate spheroid answer was 0.002887 m. The problem was that cos(lon2 - lon1) was too close to 1, so cos function returned exactly 1.



                Other than measuring sub-meter distances, the max errors (compared to an oblate spheroid formula) I found for the limited small-distance data I've fed in so far:



                    maxHaversineErrorRatio  0.00350976281908381 double
                maxPolarErrorRatio 0.0510789996931342 double


                where "1" would represent a 100% error in the answer; e.g. when it returned "0", that was an error of "1" (excluded from above "maxPolar"). So "0.01" would be an error of "1 part in 100" or 1%.



                Comparing Polar error with Haversine error over distances less than 2000 meters to see how much worse this simpler formula is. So far, the worst I've seen is 51 parts per 1000 for Polar vs 4 parts per 1000 for Haversine. At about 58 degrees latitude.





                Now implemented "Pythagorean with Latitude Adjustment".



                It is MUCH more consistent than Polar for distances < 2000 m.

                I originally thought the Polar problems were only when < 1 m,

                but the result shown immediately below is quite troubling.



                As distances approach zero, pythagorean/latitude approaches haversine.
                For example this measurement ~ 217 meters:



                    lon1Xdeg    16.6531667510102    double
                lat1Ydeg 57.7751705615804 double
                lon2Xdeg 16.6564468739869 double
                lat2Ydeg 57.7760263007586 double

                oblate 217.201200413731
                haversine 216.518428601051
                polar 226.128616011973
                pythag-cos 216.518428631907
                havErrRatio 0.00314349925958048
                polErrRatio 0.041102054598393
                pycErrRatio 0.00314349911751603


                Polar has a much worse error with these inputs; either there is some mistake in my code, or in Cos function I am running on, or I have to recommend not using Polar, even though most Polar measurements were much closer than this.



                OTOH, Pythagorean, even with * cos(latitude) adjustment, has error that increases more rapidly than distance (ratio of max_error/distance increases for larger distances), so you need to carefully consider the maximum distance you will measure, and the acceptable error. In addition, it is not advisable to COMPARE two nearly-equal distances using Pythagorean, to decide which is shorter, as the error is different in different DIRECTIONS (evidence not shown).



                Worst case measurements, errorRatio = Abs(error) / distance (Sweden; up to 2000 m):



                    t_maxHaversineErrorRatio    0.00351012021578681 double
                t_maxPolarErrorRatio 66.0825360597085 double
                t_maxPythagoreanErrorRatio 0.00350976281416454 double


                As mentioned before, the extreme polar errors are for sub-meter distances, where it could report zero instead of 6 cm, or report over 0.5 m for a distance of 1 cm (hence the "66 x" worst case shown in t_maxPolarErrorRatio), but there are also some poor results at larger distances. [Needs to be tested again with a Cosine function that is known to be highly accurate.]



                Measurements taken in C# code in Xamarin.Android running on a Moto E4.





                C# code:



                    // x=longitude, y= latitude. oblate spheroid formula. TODO: From where?
                public static double calculateDistanceDD_AED( double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg )
                {
                double c_dblEarthRadius = 6378.135; // km
                double c_dblFlattening = 1.0 / 298.257223563; // WGS84 inverse
                // flattening
                // Q: Why "-" for longitudes??
                double p1x = -degreesToRadians( lon1Xdeg );
                double p1y = degreesToRadians( lat1Ydeg );
                double p2x = -degreesToRadians( lon2Xdeg );
                double p2y = degreesToRadians( lat2Ydeg );

                double F = (p1y + p2y) / 2;
                double G = (p1y - p2y) / 2;
                double L = (p1x - p2x) / 2;

                double sing = Math.Sin( G );
                double cosl = Math.Cos( L );
                double cosf = Math.Cos( F );
                double sinl = Math.Sin( L );
                double sinf = Math.Sin( F );
                double cosg = Math.Cos( G );

                double S = sing * sing * cosl * cosl + cosf * cosf * sinl * sinl;
                double C = cosg * cosg * cosl * cosl + sinf * sinf * sinl * sinl;
                double W = Math.Atan2( Math.Sqrt( S ), Math.Sqrt( C ) );
                if (W == 0.0)
                return 0.0;

                double R = Math.Sqrt( (S * C) ) / W;
                double H1 = (3 * R - 1.0) / (2.0 * C);
                double H2 = (3 * R + 1.0) / (2.0 * S);
                double D = 2 * W * c_dblEarthRadius;

                // Apply flattening factor
                D = D * (1.0 + c_dblFlattening * H1 * sinf * sinf * cosg * cosg - c_dblFlattening * H2 * cosf * cosf * sing * sing);

                // Transform to meters
                D = D * 1000.0;

                // tmstest
                if (true)
                {
                // Compare Haversine.
                double haversine = HaversineApproxDistanceGeo( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg );
                double error = haversine - D;
                double absError = Math.Abs( error );
                double errorRatio = absError / D;
                if (errorRatio > t_maxHaversineErrorRatio)
                {
                if (errorRatio > t_maxHaversineErrorRatio * 1.1)
                Helper.test();
                t_maxHaversineErrorRatio = errorRatio;
                }

                // Compare Polar Coordinate Flat Earth.
                double polarDistanceGeo = ApproxDistanceGeo_Polar( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                double error2 = polarDistanceGeo - D;
                double absError2 = Math.Abs( error2 );
                double errorRatio2 = absError2 / D;
                if (errorRatio2 > t_maxPolarErrorRatio)
                {
                if (polarDistanceGeo > 0)
                {
                if (errorRatio2 > t_maxPolarErrorRatio * 1.1)
                Helper.test();
                t_maxPolarErrorRatio = errorRatio2;
                }
                else
                Helper.dubious();
                }

                // Compare Pythagorean Theorem with Latitude Adjustment.
                double pythagoreanDistanceGeo = ApproxDistanceGeo_PythagoreanCosLatitude( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                double error3 = pythagoreanDistanceGeo - D;
                double absError3 = Math.Abs( error3 );
                double errorRatio3 = absError3 / D;
                if (errorRatio3 > t_maxPythagoreanErrorRatio)
                {
                if (D < 2000)
                {
                if (errorRatio3 > t_maxPythagoreanErrorRatio * 1.05)
                Helper.test();
                t_maxPythagoreanErrorRatio = errorRatio3;
                }
                }
                }


                return D;
                }

                // As a fraction of the distance.
                private static double t_maxHaversineErrorRatio, t_maxPolarErrorRatio, t_maxPythagoreanErrorRatio;


                // Average of equatorial and polar radii (meters).
                public const double EarthAvgRadius = 6371000;
                public const double EarthAvgCircumference = EarthAvgRadius * 2 * PI;
                // CAUTION: This is an average of great circles; won't be the actual distance of any longitude or latitude degree.
                public const double EarthAvgMeterPerGreatCircleDegree = EarthAvgCircumference / 360;

                // Haversine formula (assumes Earth is sphere).
                // "deg" = degrees.
                // Perhaps based on Haversine Formula in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                public static double HaversineApproxDistanceGeo(double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg)
                {
                double lon1 = degreesToRadians( lon1Xdeg );
                double lat1 = degreesToRadians( lat1Ydeg );
                double lon2 = degreesToRadians( lon2Xdeg );
                double lat2 = degreesToRadians( lat2Ydeg );

                double dlon = lon2 - lon1;
                double dlat = lat2 - lat1;
                double sinDLat2 = Sin( dlat / 2 );
                double sinDLon2 = Sin( dlon / 2 );
                double a = sinDLat2 * sinDLat2 + Cos( lat1 ) * Cos( lat2 ) * sinDLon2 * sinDLon2;
                double c = 2 * Atan2( Sqrt( a ), Sqrt( 1 - a ) );
                double d = EarthAvgRadius * c;
                return d;
                }

                // From https://stackoverflow.com/a/19772119/199364
                // Based on Polar Coordinate Flat Earth in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                public static double ApproxDistanceGeo_Polar( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                {
                double approxUnitDistSq = ApproxUnitDistSq_Polar(lon1deg, lat1deg, lon2deg, lat2deg, D);
                double c = Sqrt( approxUnitDistSq );
                return EarthAvgRadius * c;
                }

                // Might be useful to avoid taking Sqrt, when comparing to some threshold.
                // Threshold would have to be adjusted to match: Power(threshold / EarthAvgRadius, 2)
                private static double ApproxUnitDistSq_Polar(double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                {
                const double HalfPi = PI / 2; //1.5707963267949;

                double lon1 = degreesToRadians(lon1deg);
                double lat1 = degreesToRadians(lat1deg);
                double lon2 = degreesToRadians(lon2deg);
                double lat2 = degreesToRadians(lat2deg);

                double a = HalfPi - lat1;
                double b = HalfPi - lat2;
                double u = a * a + b * b;
                double dlon21 = lon2 - lon1;
                double cosDeltaLon = Cos( dlon21 );
                double v = -2 * a * b * cosDeltaLon;
                // TBD: Is "Abs" necessary? That is, is "u + v" ever negative?
                // (I think not; "v" looks like a secondary term. Though might be round-off issue near zero when a~=b.)
                double approxUnitDistSq = Abs(u + v);

                //if (approxUnitDistSq.nearlyEquals(0, 1E-16))
                // Helper.dubious();
                //else if (D > 0)
                //{
                // double dba = b - a;
                // double unitD = D / EarthAvgRadius;
                // double unitDSq = unitD * unitD;
                // if (approxUnitDistSq > 2 * unitDSq)
                // Helper.dubious();
                // else if (approxUnitDistSq * 2 < unitDSq)
                // Helper.dubious();
                //}

                return approxUnitDistSq;
                }

                // Pythagorean Theorem with Latitude Adjustment - from Ewan Todd - https://stackoverflow.com/a/1664836/199364
                // Refined by ToolmakerSteve - https://stackoverflow.com/a/53468745/199364
                public static double ApproxDistanceGeo_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                {
                double approxDegreesSq = ApproxDegreesSq_PythagoreanCosLatitude( lon1deg, lat1deg, lon2deg, lat2deg );
                // approximate degrees on the great circle between the points.
                double d_degrees = Sqrt( approxDegreesSq );
                return d_degrees * EarthAvgMeterPerGreatCircleDegree;
                }

                public static double ApproxDegreesSq_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg )
                {
                double avgLatDeg = average( lat1deg , lat2deg );
                double avgLat = degreesToRadians( avgLatDeg );

                double d_ew = (lon2deg - lon1deg) * Cos( avgLat );
                double d_ns = (lat2deg - lat1deg);
                double approxDegreesSq = d_ew * d_ew + d_ns * d_ns;
                return approxDegreesSq;
                }





                share|improve this answer

































                  0














                  I am done using SQL query



                  select *, (acos(sin(input_lat* 0.01745329)*sin(lattitude *0.01745329) + cos(input_lat *0.01745329)*cos(lattitude *0.01745329)*cos((input_long -longitude)*0.01745329))* 57.29577951 )* 69.16 As D  from table_name 





                  share|improve this answer

































                    0














                    Following is the module (coded in f90) containing three formulas discussed in the previous answers. You can either put this module at the top of your program
                    (before PROGRAM MAIN) or compile it separately and include the module directory during compilation. The following module contains three formulas. First two are great-circle distances based on the assumption that earth is spherical.



                    module spherical_dists

                    contains

                    subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist)
                    !https://en.wikipedia.org/wiki/Great-circle_distance
                    ! It takes lon, lats of two points on an assumed spherical earth and
                    ! calculates the distance between them along the great circle connecting the two points
                    implicit none
                    real,intent(in)::lon1,lon2,lat1,lat2
                    real,intent(out)::dist
                    real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                    real::lonr1,lonr2,latr1,latr2
                    real::delangl,dellon
                    lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                    latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                    dellon=lonr2-lonr1
                    delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon))
                    dist=delangl*mean_earth_radius
                    end subroutine

                    subroutine haversine_formula(lon1,lat1,lon2,lat2,dist)
                    ! https://en.wikipedia.org/wiki/Haversine_formula
                    ! This is similar above but numerically better conditioned for small distances
                    implicit none
                    real,intent(in)::lon1,lon2,lat1,lat2
                    !lon, lats of two points
                    real,intent(out)::dist
                    real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                    real::lonr1,lonr2,latr1,latr2
                    real::delangl,dellon,dellat,a
                    ! degrees are converted to radians
                    lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                    latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                    dellon=lonr2-lonr1 ! These dels simplify the haversine formula
                    dellat=latr2-latr1
                    ! The actual haversine formula
                    a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2
                    delangl=2*asin(sqrt(a)) !2*asin(sqrt(a))
                    dist=delangl*mean_earth_radius
                    end subroutine

                    subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist)
                    !https://en.wikipedia.org/wiki/Vincenty%27s_formulae
                    !It's a better approximation over previous two, since it considers earth to in oblate spheroid, which better approximates the shape of the earth
                    implicit none
                    real,intent(in)::lon1,lon2,lat1,lat2
                    real,intent(out)::dist
                    real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                    real::lonr1,lonr2,latr1,latr2
                    real::delangl,dellon,nom,denom
                    lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                    latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                    dellon=lonr2-lonr1
                    nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.)
                    denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)
                    delangl=atan2(nom,denom)
                    dist=delangl*mean_earth_radius
                    end subroutine

                    end module





                    share|improve this answer





















                    • 1





                      This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                      – Richard
                      Nov 25 '18 at 18:42











                    • I edited my answer to add more details and format the code.

                      – srinivasu u
                      Nov 28 '18 at 6:24











                    • Awesome, thank you.

                      – Richard
                      Nov 28 '18 at 7:02



















                    0














                    On this page you can see the whole code and formulas how distances of locations are calculated in Android Location class



                    android/location/Location.java



                    EDIT: According the hint from @Richard I put the code of the linked function into my answer, to avoid invalidated link:



                    private static void computeDistanceAndBearing(double lat1, double lon1,
                    double lat2, double lon2, BearingDistanceCache results) {
                    // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
                    // using the "Inverse Formula" (section 4)
                    int MAXITERS = 20;
                    // Convert lat/long to radians
                    lat1 *= Math.PI / 180.0;
                    lat2 *= Math.PI / 180.0;
                    lon1 *= Math.PI / 180.0;
                    lon2 *= Math.PI / 180.0;
                    double a = 6378137.0; // WGS84 major axis
                    double b = 6356752.3142; // WGS84 semi-major axis
                    double f = (a - b) / a;
                    double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
                    double L = lon2 - lon1;
                    double A = 0.0;
                    double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
                    double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
                    double cosU1 = Math.cos(U1);
                    double cosU2 = Math.cos(U2);
                    double sinU1 = Math.sin(U1);
                    double sinU2 = Math.sin(U2);
                    double cosU1cosU2 = cosU1 * cosU2;
                    double sinU1sinU2 = sinU1 * sinU2;
                    double sigma = 0.0;
                    double deltaSigma = 0.0;
                    double cosSqAlpha = 0.0;
                    double cos2SM = 0.0;
                    double cosSigma = 0.0;
                    double sinSigma = 0.0;
                    double cosLambda = 0.0;
                    double sinLambda = 0.0;
                    double lambda = L; // initial guess
                    for (int iter = 0; iter < MAXITERS; iter++) {
                    double lambdaOrig = lambda;
                    cosLambda = Math.cos(lambda);
                    sinLambda = Math.sin(lambda);
                    double t1 = cosU2 * sinLambda;
                    double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
                    double sinSqSigma = t1 * t1 + t2 * t2; // (14)
                    sinSigma = Math.sqrt(sinSqSigma);
                    cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
                    sigma = Math.atan2(sinSigma, cosSigma); // (16)
                    double sinAlpha = (sinSigma == 0) ? 0.0 :
                    cosU1cosU2 * sinLambda / sinSigma; // (17)
                    cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
                    cos2SM = (cosSqAlpha == 0) ? 0.0 :
                    cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
                    double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
                    A = 1 + (uSquared / 16384.0) * // (3)
                    (4096.0 + uSquared *
                    (-768 + uSquared * (320.0 - 175.0 * uSquared)));
                    double B = (uSquared / 1024.0) * // (4)
                    (256.0 + uSquared *
                    (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
                    double C = (f / 16.0) *
                    cosSqAlpha *
                    (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
                    double cos2SMSq = cos2SM * cos2SM;
                    deltaSigma = B * sinSigma * // (6)
                    (cos2SM + (B / 4.0) *
                    (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                    (B / 6.0) * cos2SM *
                    (-3.0 + 4.0 * sinSigma * sinSigma) *
                    (-3.0 + 4.0 * cos2SMSq)));
                    lambda = L +
                    (1.0 - C) * f * sinAlpha *
                    (sigma + C * sinSigma *
                    (cos2SM + C * cosSigma *
                    (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
                    double delta = (lambda - lambdaOrig) / lambda;
                    if (Math.abs(delta) < 1.0e-12) {
                    break;
                    }
                    }
                    float distance = (float) (b * A * (sigma - deltaSigma));
                    results.mDistance = distance;
                    float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                    cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
                    initialBearing *= 180.0 / Math.PI;
                    results.mInitialBearing = initialBearing;
                    float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                    -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
                    finalBearing *= 180.0 / Math.PI;
                    results.mFinalBearing = finalBearing;
                    results.mLat1 = lat1;
                    results.mLat2 = lat2;
                    results.mLon1 = lon1;
                    results.mLon2 = lon2;
                    }





                    share|improve this answer


























                    • Link only answers can invalidate over time, and so are less useful.

                      – Richard
                      Nov 25 '18 at 18:42











                    • You are right @Richard I updated the link and added the linkt function code to my answer.

                      – Radon8472
                      Nov 28 '18 at 12:22











                    • Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                      – Richard
                      Nov 28 '18 at 17:28



















                    -3














                    just use the distance formula Sqrt( (x2-x1)^2 + (y2-y1)^2 )






                    share|improve this answer





















                    • 1





                      Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                      – ToolmakerSteve
                      Nov 25 '18 at 12:55













                    • This is so very wrong.

                      – Richard
                      Nov 25 '18 at 18:43










                    protected by Neil Lunn Jan 20 '15 at 8:11



                    Thank you for your interest in this question.
                    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                    Would you like to answer one of these unanswered questions instead?














                    13 Answers
                    13






                    active

                    oldest

                    votes








                    13 Answers
                    13






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    29














                    The Haversine formula assumes a spherical earth. However, the shape of the earh is more complex. An oblate spheroid model will give better results.



                    If such accuracy is needed, you should better use Vincenty inverse formula.
                    See http://en.wikipedia.org/wiki/Vincenty's_formulae for details. Using it, you can get a 0.5mm accuracy for the spheroid model.



                    There is no perfect formula, since the real shape of the earth is too complex to be expressed by a formula. Moreover, the shape of earth changes due to climate events (see http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), and also changes over time due to the rotation of the earth.



                    You should also note that the method above does not take altitudes into account, and assumes a sea-level oblate spheroid.



                    Edit 10-Jul-2010: I found out that there are rare situations for which Vincenty inverse formula does not converge to the declared accuracy. A better idea is to use GeographicLib (see http://sourceforge.net/projects/geographiclib/) which is also more accurate.






                    share|improve this answer





















                    • 3





                      +1 this caught quite a few people off guard at a previous employer.

                      – Dan Blair
                      Sep 14 '09 at 16:34











                    • Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                      – PeterAllenWebb
                      Sep 17 '09 at 17:45











                    • +1 for "answer depends on the degree of accuracy required"

                      – Piskvor
                      Sep 26 '10 at 16:19











                    • I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                      – ToolmakerSteve
                      Nov 25 '18 at 19:10


















                    29














                    The Haversine formula assumes a spherical earth. However, the shape of the earh is more complex. An oblate spheroid model will give better results.



                    If such accuracy is needed, you should better use Vincenty inverse formula.
                    See http://en.wikipedia.org/wiki/Vincenty's_formulae for details. Using it, you can get a 0.5mm accuracy for the spheroid model.



                    There is no perfect formula, since the real shape of the earth is too complex to be expressed by a formula. Moreover, the shape of earth changes due to climate events (see http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), and also changes over time due to the rotation of the earth.



                    You should also note that the method above does not take altitudes into account, and assumes a sea-level oblate spheroid.



                    Edit 10-Jul-2010: I found out that there are rare situations for which Vincenty inverse formula does not converge to the declared accuracy. A better idea is to use GeographicLib (see http://sourceforge.net/projects/geographiclib/) which is also more accurate.






                    share|improve this answer





















                    • 3





                      +1 this caught quite a few people off guard at a previous employer.

                      – Dan Blair
                      Sep 14 '09 at 16:34











                    • Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                      – PeterAllenWebb
                      Sep 17 '09 at 17:45











                    • +1 for "answer depends on the degree of accuracy required"

                      – Piskvor
                      Sep 26 '10 at 16:19











                    • I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                      – ToolmakerSteve
                      Nov 25 '18 at 19:10
















                    29












                    29








                    29







                    The Haversine formula assumes a spherical earth. However, the shape of the earh is more complex. An oblate spheroid model will give better results.



                    If such accuracy is needed, you should better use Vincenty inverse formula.
                    See http://en.wikipedia.org/wiki/Vincenty's_formulae for details. Using it, you can get a 0.5mm accuracy for the spheroid model.



                    There is no perfect formula, since the real shape of the earth is too complex to be expressed by a formula. Moreover, the shape of earth changes due to climate events (see http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), and also changes over time due to the rotation of the earth.



                    You should also note that the method above does not take altitudes into account, and assumes a sea-level oblate spheroid.



                    Edit 10-Jul-2010: I found out that there are rare situations for which Vincenty inverse formula does not converge to the declared accuracy. A better idea is to use GeographicLib (see http://sourceforge.net/projects/geographiclib/) which is also more accurate.






                    share|improve this answer















                    The Haversine formula assumes a spherical earth. However, the shape of the earh is more complex. An oblate spheroid model will give better results.



                    If such accuracy is needed, you should better use Vincenty inverse formula.
                    See http://en.wikipedia.org/wiki/Vincenty's_formulae for details. Using it, you can get a 0.5mm accuracy for the spheroid model.



                    There is no perfect formula, since the real shape of the earth is too complex to be expressed by a formula. Moreover, the shape of earth changes due to climate events (see http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), and also changes over time due to the rotation of the earth.



                    You should also note that the method above does not take altitudes into account, and assumes a sea-level oblate spheroid.



                    Edit 10-Jul-2010: I found out that there are rare situations for which Vincenty inverse formula does not converge to the declared accuracy. A better idea is to use GeographicLib (see http://sourceforge.net/projects/geographiclib/) which is also more accurate.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jul 10 '10 at 12:47

























                    answered Sep 14 '09 at 16:17









                    Lior KoganLior Kogan

                    15.2k34574




                    15.2k34574








                    • 3





                      +1 this caught quite a few people off guard at a previous employer.

                      – Dan Blair
                      Sep 14 '09 at 16:34











                    • Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                      – PeterAllenWebb
                      Sep 17 '09 at 17:45











                    • +1 for "answer depends on the degree of accuracy required"

                      – Piskvor
                      Sep 26 '10 at 16:19











                    • I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                      – ToolmakerSteve
                      Nov 25 '18 at 19:10
















                    • 3





                      +1 this caught quite a few people off guard at a previous employer.

                      – Dan Blair
                      Sep 14 '09 at 16:34











                    • Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                      – PeterAllenWebb
                      Sep 17 '09 at 17:45











                    • +1 for "answer depends on the degree of accuracy required"

                      – Piskvor
                      Sep 26 '10 at 16:19











                    • I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                      – ToolmakerSteve
                      Nov 25 '18 at 19:10










                    3




                    3





                    +1 this caught quite a few people off guard at a previous employer.

                    – Dan Blair
                    Sep 14 '09 at 16:34





                    +1 this caught quite a few people off guard at a previous employer.

                    – Dan Blair
                    Sep 14 '09 at 16:34













                    Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                    – PeterAllenWebb
                    Sep 17 '09 at 17:45





                    Indeed. When values cannot be more than a few meters off, this question gets much more complicated.

                    – PeterAllenWebb
                    Sep 17 '09 at 17:45













                    +1 for "answer depends on the degree of accuracy required"

                    – Piskvor
                    Sep 26 '10 at 16:19





                    +1 for "answer depends on the degree of accuracy required"

                    – Piskvor
                    Sep 26 '10 at 16:19













                    I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                    – ToolmakerSteve
                    Nov 25 '18 at 19:10







                    I've provided C# code that implements oblate spheroid (I'm not sure if it is VIncenty), Haversine, and two often-mentioned high-performance approximations for up to 1 km or so. Considering the oblate spheroid to be "correct", shows measured errors of the other formulas, in one region in Sweden (latitude ~58 degrees).

                    – ToolmakerSteve
                    Nov 25 '18 at 19:10















                    9














                    Here's one: http://www.movable-type.co.uk/scripts/latlong.html



                    Using Haversine formula:



                    R = earth’s radius (mean radius = 6,371km)
                    Δlat = lat2− lat1
                    Δlong = long2− long1
                    a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                    c = 2.atan2(√a, √(1−a))
                    d = R.c





                    share|improve this answer




























                      9














                      Here's one: http://www.movable-type.co.uk/scripts/latlong.html



                      Using Haversine formula:



                      R = earth’s radius (mean radius = 6,371km)
                      Δlat = lat2− lat1
                      Δlong = long2− long1
                      a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                      c = 2.atan2(√a, √(1−a))
                      d = R.c





                      share|improve this answer


























                        9












                        9








                        9







                        Here's one: http://www.movable-type.co.uk/scripts/latlong.html



                        Using Haversine formula:



                        R = earth’s radius (mean radius = 6,371km)
                        Δlat = lat2− lat1
                        Δlong = long2− long1
                        a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                        c = 2.atan2(√a, √(1−a))
                        d = R.c





                        share|improve this answer













                        Here's one: http://www.movable-type.co.uk/scripts/latlong.html



                        Using Haversine formula:



                        R = earth’s radius (mean radius = 6,371km)
                        Δlat = lat2− lat1
                        Δlong = long2− long1
                        a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                        c = 2.atan2(√a, √(1−a))
                        d = R.c






                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Sep 14 '09 at 7:00









                        maurismauris

                        33.8k1385124




                        33.8k1385124























                            5














                            Apply the Haversine formula to find the distance. See the C# code below to find the distance between 2 coordinates. Better still if you want to say find a list of stores within a certain radius, you could apply a WHERE clause in SQL or a LINQ filter in C# to it.



                            The formula here is in kilometres, you will have to change the relevant numbers and it will work for miles.



                            E.g: Convert 6371.392896 to miles.



                                DECLARE @radiusInKm AS FLOAT
                            DECLARE @lat2Compare AS FLOAT
                            DECLARE @long2Compare AS FLOAT
                            SET @radiusInKm = 5.000
                            SET @lat2Compare = insert_your_lat_to_compare_here
                            SET @long2Compare = insert_you_long_to_compare_here

                            SELECT * FROM insert_your_table_here WITH(NOLOCK)
                            WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                            , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                            ))) <= @radiusInKm


                            If you would like to perform the Haversine formula in C#,



                                double resultDistance = 0.0;
                            double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average.

                            //Haversine formula
                            //distance = R * 2 * aTan2 ( square root of A, square root of 1 - A )
                            // where A = sinus squared (difference in latitude / 2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude / 2))
                            // and R = the circumference of the earth

                            double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
                            double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
                            double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong / 2) * Math.Sin(differenceInLong / 2);
                            double aFormula = (Math.Sin((differenceInLat) / 2) * Math.Sin((differenceInLat) / 2)) + (aInnerFormula);
                            resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula));


                            DegreesToRadian is a function I custom created, its is a simple 1 liner of"Math.PI * angle / 180.0



                            My blog entry - SQL Haversine






                            share|improve this answer






























                              5














                              Apply the Haversine formula to find the distance. See the C# code below to find the distance between 2 coordinates. Better still if you want to say find a list of stores within a certain radius, you could apply a WHERE clause in SQL or a LINQ filter in C# to it.



                              The formula here is in kilometres, you will have to change the relevant numbers and it will work for miles.



                              E.g: Convert 6371.392896 to miles.



                                  DECLARE @radiusInKm AS FLOAT
                              DECLARE @lat2Compare AS FLOAT
                              DECLARE @long2Compare AS FLOAT
                              SET @radiusInKm = 5.000
                              SET @lat2Compare = insert_your_lat_to_compare_here
                              SET @long2Compare = insert_you_long_to_compare_here

                              SELECT * FROM insert_your_table_here WITH(NOLOCK)
                              WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                              , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                              ))) <= @radiusInKm


                              If you would like to perform the Haversine formula in C#,



                                  double resultDistance = 0.0;
                              double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average.

                              //Haversine formula
                              //distance = R * 2 * aTan2 ( square root of A, square root of 1 - A )
                              // where A = sinus squared (difference in latitude / 2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude / 2))
                              // and R = the circumference of the earth

                              double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
                              double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
                              double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong / 2) * Math.Sin(differenceInLong / 2);
                              double aFormula = (Math.Sin((differenceInLat) / 2) * Math.Sin((differenceInLat) / 2)) + (aInnerFormula);
                              resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula));


                              DegreesToRadian is a function I custom created, its is a simple 1 liner of"Math.PI * angle / 180.0



                              My blog entry - SQL Haversine






                              share|improve this answer




























                                5












                                5








                                5







                                Apply the Haversine formula to find the distance. See the C# code below to find the distance between 2 coordinates. Better still if you want to say find a list of stores within a certain radius, you could apply a WHERE clause in SQL or a LINQ filter in C# to it.



                                The formula here is in kilometres, you will have to change the relevant numbers and it will work for miles.



                                E.g: Convert 6371.392896 to miles.



                                    DECLARE @radiusInKm AS FLOAT
                                DECLARE @lat2Compare AS FLOAT
                                DECLARE @long2Compare AS FLOAT
                                SET @radiusInKm = 5.000
                                SET @lat2Compare = insert_your_lat_to_compare_here
                                SET @long2Compare = insert_you_long_to_compare_here

                                SELECT * FROM insert_your_table_here WITH(NOLOCK)
                                WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                                , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                                ))) <= @radiusInKm


                                If you would like to perform the Haversine formula in C#,



                                    double resultDistance = 0.0;
                                double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average.

                                //Haversine formula
                                //distance = R * 2 * aTan2 ( square root of A, square root of 1 - A )
                                // where A = sinus squared (difference in latitude / 2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude / 2))
                                // and R = the circumference of the earth

                                double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
                                double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
                                double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong / 2) * Math.Sin(differenceInLong / 2);
                                double aFormula = (Math.Sin((differenceInLat) / 2) * Math.Sin((differenceInLat) / 2)) + (aInnerFormula);
                                resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula));


                                DegreesToRadian is a function I custom created, its is a simple 1 liner of"Math.PI * angle / 180.0



                                My blog entry - SQL Haversine






                                share|improve this answer















                                Apply the Haversine formula to find the distance. See the C# code below to find the distance between 2 coordinates. Better still if you want to say find a list of stores within a certain radius, you could apply a WHERE clause in SQL or a LINQ filter in C# to it.



                                The formula here is in kilometres, you will have to change the relevant numbers and it will work for miles.



                                E.g: Convert 6371.392896 to miles.



                                    DECLARE @radiusInKm AS FLOAT
                                DECLARE @lat2Compare AS FLOAT
                                DECLARE @long2Compare AS FLOAT
                                SET @radiusInKm = 5.000
                                SET @lat2Compare = insert_your_lat_to_compare_here
                                SET @long2Compare = insert_you_long_to_compare_here

                                SELECT * FROM insert_your_table_here WITH(NOLOCK)
                                WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                                , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare)) / 2) * sin((radians(GeoLatitude - @lat2Compare)) / 2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2)))
                                ))) <= @radiusInKm


                                If you would like to perform the Haversine formula in C#,



                                    double resultDistance = 0.0;
                                double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average.

                                //Haversine formula
                                //distance = R * 2 * aTan2 ( square root of A, square root of 1 - A )
                                // where A = sinus squared (difference in latitude / 2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude / 2))
                                // and R = the circumference of the earth

                                double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
                                double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
                                double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong / 2) * Math.Sin(differenceInLong / 2);
                                double aFormula = (Math.Sin((differenceInLat) / 2) * Math.Sin((differenceInLat) / 2)) + (aInnerFormula);
                                resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula));


                                DegreesToRadian is a function I custom created, its is a simple 1 liner of"Math.PI * angle / 180.0



                                My blog entry - SQL Haversine







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Jul 15 '11 at 11:40









                                Alex K.

                                141k22203241




                                141k22203241










                                answered Jun 11 '10 at 7:36









                                ZacZac

                                10715




                                10715























                                    4














                                    Are you looking for



                                    Haversine formula




                                    The haversine formula is an equation
                                    important in navigation, giving
                                    great-circle distances between two
                                    points on a sphere from their
                                    longitudes and latitudes. It is a
                                    special case of a more general formula
                                    in spherical trigonometry, the law of
                                    haversines, relating the sides and
                                    angles of spherical "triangles".







                                    share|improve this answer




























                                      4














                                      Are you looking for



                                      Haversine formula




                                      The haversine formula is an equation
                                      important in navigation, giving
                                      great-circle distances between two
                                      points on a sphere from their
                                      longitudes and latitudes. It is a
                                      special case of a more general formula
                                      in spherical trigonometry, the law of
                                      haversines, relating the sides and
                                      angles of spherical "triangles".







                                      share|improve this answer


























                                        4












                                        4








                                        4







                                        Are you looking for



                                        Haversine formula




                                        The haversine formula is an equation
                                        important in navigation, giving
                                        great-circle distances between two
                                        points on a sphere from their
                                        longitudes and latitudes. It is a
                                        special case of a more general formula
                                        in spherical trigonometry, the law of
                                        haversines, relating the sides and
                                        angles of spherical "triangles".







                                        share|improve this answer













                                        Are you looking for



                                        Haversine formula




                                        The haversine formula is an equation
                                        important in navigation, giving
                                        great-circle distances between two
                                        points on a sphere from their
                                        longitudes and latitudes. It is a
                                        special case of a more general formula
                                        in spherical trigonometry, the law of
                                        haversines, relating the sides and
                                        angles of spherical "triangles".








                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Sep 14 '09 at 6:58









                                        rahulrahul

                                        152k43206248




                                        152k43206248























                                            3














                                            Have a look at this.. has a javascript example as well.



                                            Find Distance






                                            share|improve this answer
























                                            • Very cool! nice find

                                              – Paul Gregoire
                                              Sep 27 '10 at 16:34











                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41
















                                            3














                                            Have a look at this.. has a javascript example as well.



                                            Find Distance






                                            share|improve this answer
























                                            • Very cool! nice find

                                              – Paul Gregoire
                                              Sep 27 '10 at 16:34











                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41














                                            3












                                            3








                                            3







                                            Have a look at this.. has a javascript example as well.



                                            Find Distance






                                            share|improve this answer













                                            Have a look at this.. has a javascript example as well.



                                            Find Distance







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Sep 14 '09 at 6:59









                                            rajesh pillairajesh pillai

                                            6,52273856




                                            6,52273856













                                            • Very cool! nice find

                                              – Paul Gregoire
                                              Sep 27 '10 at 16:34











                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41



















                                            • Very cool! nice find

                                              – Paul Gregoire
                                              Sep 27 '10 at 16:34











                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41

















                                            Very cool! nice find

                                            – Paul Gregoire
                                            Sep 27 '10 at 16:34





                                            Very cool! nice find

                                            – Paul Gregoire
                                            Sep 27 '10 at 16:34













                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41





                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41











                                            2














                                            Use the Great Circle Distance Formula.






                                            share|improve this answer
























                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41
















                                            2














                                            Use the Great Circle Distance Formula.






                                            share|improve this answer
























                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41














                                            2












                                            2








                                            2







                                            Use the Great Circle Distance Formula.






                                            share|improve this answer













                                            Use the Great Circle Distance Formula.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Sep 14 '09 at 6:59









                                            FragsworthFragsworth

                                            12.5k226793




                                            12.5k226793













                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41



















                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41

















                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41





                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41











                                            1














                                            This link has all the info you need, either on it or linked.






                                            share|improve this answer
























                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41
















                                            1














                                            This link has all the info you need, either on it or linked.






                                            share|improve this answer
























                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41














                                            1












                                            1








                                            1







                                            This link has all the info you need, either on it or linked.






                                            share|improve this answer













                                            This link has all the info you need, either on it or linked.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Sep 14 '09 at 6:59









                                            Lance RobertsLance Roberts

                                            17.6k2798127




                                            17.6k2798127













                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41



















                                            • Link only answers can invalidate over time, and so are less useful.

                                              – Richard
                                              Nov 25 '18 at 18:41

















                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41





                                            Link only answers can invalidate over time, and so are less useful.

                                            – Richard
                                            Nov 25 '18 at 18:41











                                            1














                                            here is a fiddle with finding locations / near locations to long/lat by given IP:



                                            http://jsfiddle.net/bassta/zrgd9qc3/2/



                                            And here is the function I use to calculate the distance in straight line:



                                            function distance(lat1, lng1, lat2, lng2) {
                                            var radlat1 = Math.PI * lat1 / 180;
                                            var radlat2 = Math.PI * lat2 / 180;
                                            var radlon1 = Math.PI * lng1 / 180;
                                            var radlon2 = Math.PI * lng2 / 180;
                                            var theta = lng1 - lng2;
                                            var radtheta = Math.PI * theta / 180;
                                            var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
                                            dist = Math.acos(dist);
                                            dist = dist * 180 / Math.PI;
                                            dist = dist * 60 * 1.1515;

                                            //Get in in kilometers
                                            dist = dist * 1.609344;

                                            return dist;
                                            }


                                            It returns the distance in Kilometers






                                            share|improve this answer
























                                            • Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                              – ToolmakerSteve
                                              Nov 25 '18 at 12:53











                                            • Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                              – Христо Панайотов
                                              Nov 25 '18 at 13:10











                                            • Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                              – ToolmakerSteve
                                              Nov 25 '18 at 15:04











                                            • This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                              – Richard
                                              Nov 25 '18 at 18:44
















                                            1














                                            here is a fiddle with finding locations / near locations to long/lat by given IP:



                                            http://jsfiddle.net/bassta/zrgd9qc3/2/



                                            And here is the function I use to calculate the distance in straight line:



                                            function distance(lat1, lng1, lat2, lng2) {
                                            var radlat1 = Math.PI * lat1 / 180;
                                            var radlat2 = Math.PI * lat2 / 180;
                                            var radlon1 = Math.PI * lng1 / 180;
                                            var radlon2 = Math.PI * lng2 / 180;
                                            var theta = lng1 - lng2;
                                            var radtheta = Math.PI * theta / 180;
                                            var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
                                            dist = Math.acos(dist);
                                            dist = dist * 180 / Math.PI;
                                            dist = dist * 60 * 1.1515;

                                            //Get in in kilometers
                                            dist = dist * 1.609344;

                                            return dist;
                                            }


                                            It returns the distance in Kilometers






                                            share|improve this answer
























                                            • Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                              – ToolmakerSteve
                                              Nov 25 '18 at 12:53











                                            • Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                              – Христо Панайотов
                                              Nov 25 '18 at 13:10











                                            • Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                              – ToolmakerSteve
                                              Nov 25 '18 at 15:04











                                            • This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                              – Richard
                                              Nov 25 '18 at 18:44














                                            1












                                            1








                                            1







                                            here is a fiddle with finding locations / near locations to long/lat by given IP:



                                            http://jsfiddle.net/bassta/zrgd9qc3/2/



                                            And here is the function I use to calculate the distance in straight line:



                                            function distance(lat1, lng1, lat2, lng2) {
                                            var radlat1 = Math.PI * lat1 / 180;
                                            var radlat2 = Math.PI * lat2 / 180;
                                            var radlon1 = Math.PI * lng1 / 180;
                                            var radlon2 = Math.PI * lng2 / 180;
                                            var theta = lng1 - lng2;
                                            var radtheta = Math.PI * theta / 180;
                                            var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
                                            dist = Math.acos(dist);
                                            dist = dist * 180 / Math.PI;
                                            dist = dist * 60 * 1.1515;

                                            //Get in in kilometers
                                            dist = dist * 1.609344;

                                            return dist;
                                            }


                                            It returns the distance in Kilometers






                                            share|improve this answer













                                            here is a fiddle with finding locations / near locations to long/lat by given IP:



                                            http://jsfiddle.net/bassta/zrgd9qc3/2/



                                            And here is the function I use to calculate the distance in straight line:



                                            function distance(lat1, lng1, lat2, lng2) {
                                            var radlat1 = Math.PI * lat1 / 180;
                                            var radlat2 = Math.PI * lat2 / 180;
                                            var radlon1 = Math.PI * lng1 / 180;
                                            var radlon2 = Math.PI * lng2 / 180;
                                            var theta = lng1 - lng2;
                                            var radtheta = Math.PI * theta / 180;
                                            var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
                                            dist = Math.acos(dist);
                                            dist = dist * 180 / Math.PI;
                                            dist = dist * 60 * 1.1515;

                                            //Get in in kilometers
                                            dist = dist * 1.609344;

                                            return dist;
                                            }


                                            It returns the distance in Kilometers







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Mar 31 '15 at 14:36









                                            Христо ПанайотовХристо Панайотов

                                            866918




                                            866918













                                            • Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                              – ToolmakerSteve
                                              Nov 25 '18 at 12:53











                                            • Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                              – Христо Панайотов
                                              Nov 25 '18 at 13:10











                                            • Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                              – ToolmakerSteve
                                              Nov 25 '18 at 15:04











                                            • This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                              – Richard
                                              Nov 25 '18 at 18:44



















                                            • Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                              – ToolmakerSteve
                                              Nov 25 '18 at 12:53











                                            • Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                              – Христо Панайотов
                                              Nov 25 '18 at 13:10











                                            • Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                              – ToolmakerSteve
                                              Nov 25 '18 at 15:04











                                            • This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                              – Richard
                                              Nov 25 '18 at 18:44

















                                            Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                            – ToolmakerSteve
                                            Nov 25 '18 at 12:53





                                            Please say what technique this is based on. Haversine? Vincenty? Some other approximation? And provide link to original source justifying your code.

                                            – ToolmakerSteve
                                            Nov 25 '18 at 12:53













                                            Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                            – Христо Панайотов
                                            Nov 25 '18 at 13:10





                                            Hi, the code is JavaScript implementation of orthodromic distance formula for finding distance between two points on perfect sphere. I know the Earth is not a perfect sphere, but in my case I didn't wanted greater accuracy.

                                            – Христо Панайотов
                                            Nov 25 '18 at 13:10













                                            Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                            – ToolmakerSteve
                                            Nov 25 '18 at 15:04





                                            Thanks, that helps me understand what you have. I see several different formulas for great-circle distance. Do you know whether your code is derived from Haversine, Vicenty, or chord length formula, or some other mathematical representation of a sphere?

                                            – ToolmakerSteve
                                            Nov 25 '18 at 15:04













                                            This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                            – Richard
                                            Nov 25 '18 at 18:44





                                            This answer doesn't indicate what distance formula is being used, which can have important effects on accuracy.

                                            – Richard
                                            Nov 25 '18 at 18:44











                                            1














                                            If you are measuring distances less than (perhaps) 1 degree lat/long change, are looking for a very high performance approximation, and are willing to accept more inaccuracy than Haversine formula, consider these two alternatives:



                                            (1) "Polar Coordinate Flat-Earth Formula" from Computing Distances:



                                            a = pi/2 - lat1  
                                            b = pi/2 - lat2
                                            c = sqrt( a^2 + b^2 - 2 * a * b * cos(lon2 - lon1) )
                                            d = R * c


                                            (2) Pythagorean theorem adjusted for latitude, as seen in Ewan Todd's SO post:



                                            d_ew = (long1 - long0) * cos(average(lat0, lat1))  
                                            d_ns = (lat1 - lat0)
                                            d = sqrt(d_ew * d_ew + d_ns * d_ns)


                                            NOTES:

                                            Compared to Ewan's post, I've substituted average(lat0, lat1) for lat0 inside of cos( lat0 ).



                                            #2 is vague on whether values are degrees, radians, or kilometers; you will need some conversion code as well. See my complete code at bottom of this post.



                                            #1 is designed to work well even near the poles, though if you are measuring a distance whose endpoints are on "opposite" sides of the pole (longitudes differ by more than 90 degrees?), Haversine is recommended instead, even for small distances.



                                            I haven't thoroughly measured errors of these approaches, so you should take representative points for your application, and compare results to some high-quality library, to decide if the accuracies are acceptable. For distances less than a few kilometers my gut sense is that these are within 1% of correct measurement.





                                            An alternative way to gain high performance (when applicable):



                                            If you have a large set of static points, within one or two degrees of longitude/latitude, that you will then be calculating distances from a small number of dynamic (moving) points, consider converting your static points ONCE to the containing UTM zone (or to any other local Cartesian coordinate system), and then doing all your math in that Cartesian coordinate system.

                                            Cartesian = flat earth = Pythagorean theorem applies, so distance = sqrt(dx^2 + dy^2).



                                            Then the cost of accurately converting the few moving points to UTM is easily afforded.





                                            CAVEAT for #1 (Polar): May be very wrong for distances less than 0.1 (?) meter. Even with double precision math, the following coordinates, whose true distance is about 0.005 meters, was given as "zero" by my implementation of Polar algorithm:



                                            inputs:



                                                lon1Xdeg    16.6564465477996    double
                                            lat1Ydeg 57.7760262271983 double
                                            lon2Xdeg 16.6564466358281 double
                                            lat2Ydeg 57.776026248554 double


                                            results:



                                            Oblate spheroid formula:  
                                            0.00575254911118364 double
                                            Haversine:
                                            0.00573422966122257 double
                                            Polar:
                                            0


                                            this was due to the two factors u and v exactly canceling each other:



                                                u   0.632619944868587   double
                                            v -0.632619944868587 double


                                            In another case, it gave a distance of 0.067129 m when the oblate spheroid answer was 0.002887 m. The problem was that cos(lon2 - lon1) was too close to 1, so cos function returned exactly 1.



                                            Other than measuring sub-meter distances, the max errors (compared to an oblate spheroid formula) I found for the limited small-distance data I've fed in so far:



                                                maxHaversineErrorRatio  0.00350976281908381 double
                                            maxPolarErrorRatio 0.0510789996931342 double


                                            where "1" would represent a 100% error in the answer; e.g. when it returned "0", that was an error of "1" (excluded from above "maxPolar"). So "0.01" would be an error of "1 part in 100" or 1%.



                                            Comparing Polar error with Haversine error over distances less than 2000 meters to see how much worse this simpler formula is. So far, the worst I've seen is 51 parts per 1000 for Polar vs 4 parts per 1000 for Haversine. At about 58 degrees latitude.





                                            Now implemented "Pythagorean with Latitude Adjustment".



                                            It is MUCH more consistent than Polar for distances < 2000 m.

                                            I originally thought the Polar problems were only when < 1 m,

                                            but the result shown immediately below is quite troubling.



                                            As distances approach zero, pythagorean/latitude approaches haversine.
                                            For example this measurement ~ 217 meters:



                                                lon1Xdeg    16.6531667510102    double
                                            lat1Ydeg 57.7751705615804 double
                                            lon2Xdeg 16.6564468739869 double
                                            lat2Ydeg 57.7760263007586 double

                                            oblate 217.201200413731
                                            haversine 216.518428601051
                                            polar 226.128616011973
                                            pythag-cos 216.518428631907
                                            havErrRatio 0.00314349925958048
                                            polErrRatio 0.041102054598393
                                            pycErrRatio 0.00314349911751603


                                            Polar has a much worse error with these inputs; either there is some mistake in my code, or in Cos function I am running on, or I have to recommend not using Polar, even though most Polar measurements were much closer than this.



                                            OTOH, Pythagorean, even with * cos(latitude) adjustment, has error that increases more rapidly than distance (ratio of max_error/distance increases for larger distances), so you need to carefully consider the maximum distance you will measure, and the acceptable error. In addition, it is not advisable to COMPARE two nearly-equal distances using Pythagorean, to decide which is shorter, as the error is different in different DIRECTIONS (evidence not shown).



                                            Worst case measurements, errorRatio = Abs(error) / distance (Sweden; up to 2000 m):



                                                t_maxHaversineErrorRatio    0.00351012021578681 double
                                            t_maxPolarErrorRatio 66.0825360597085 double
                                            t_maxPythagoreanErrorRatio 0.00350976281416454 double


                                            As mentioned before, the extreme polar errors are for sub-meter distances, where it could report zero instead of 6 cm, or report over 0.5 m for a distance of 1 cm (hence the "66 x" worst case shown in t_maxPolarErrorRatio), but there are also some poor results at larger distances. [Needs to be tested again with a Cosine function that is known to be highly accurate.]



                                            Measurements taken in C# code in Xamarin.Android running on a Moto E4.





                                            C# code:



                                                // x=longitude, y= latitude. oblate spheroid formula. TODO: From where?
                                            public static double calculateDistanceDD_AED( double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg )
                                            {
                                            double c_dblEarthRadius = 6378.135; // km
                                            double c_dblFlattening = 1.0 / 298.257223563; // WGS84 inverse
                                            // flattening
                                            // Q: Why "-" for longitudes??
                                            double p1x = -degreesToRadians( lon1Xdeg );
                                            double p1y = degreesToRadians( lat1Ydeg );
                                            double p2x = -degreesToRadians( lon2Xdeg );
                                            double p2y = degreesToRadians( lat2Ydeg );

                                            double F = (p1y + p2y) / 2;
                                            double G = (p1y - p2y) / 2;
                                            double L = (p1x - p2x) / 2;

                                            double sing = Math.Sin( G );
                                            double cosl = Math.Cos( L );
                                            double cosf = Math.Cos( F );
                                            double sinl = Math.Sin( L );
                                            double sinf = Math.Sin( F );
                                            double cosg = Math.Cos( G );

                                            double S = sing * sing * cosl * cosl + cosf * cosf * sinl * sinl;
                                            double C = cosg * cosg * cosl * cosl + sinf * sinf * sinl * sinl;
                                            double W = Math.Atan2( Math.Sqrt( S ), Math.Sqrt( C ) );
                                            if (W == 0.0)
                                            return 0.0;

                                            double R = Math.Sqrt( (S * C) ) / W;
                                            double H1 = (3 * R - 1.0) / (2.0 * C);
                                            double H2 = (3 * R + 1.0) / (2.0 * S);
                                            double D = 2 * W * c_dblEarthRadius;

                                            // Apply flattening factor
                                            D = D * (1.0 + c_dblFlattening * H1 * sinf * sinf * cosg * cosg - c_dblFlattening * H2 * cosf * cosf * sing * sing);

                                            // Transform to meters
                                            D = D * 1000.0;

                                            // tmstest
                                            if (true)
                                            {
                                            // Compare Haversine.
                                            double haversine = HaversineApproxDistanceGeo( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg );
                                            double error = haversine - D;
                                            double absError = Math.Abs( error );
                                            double errorRatio = absError / D;
                                            if (errorRatio > t_maxHaversineErrorRatio)
                                            {
                                            if (errorRatio > t_maxHaversineErrorRatio * 1.1)
                                            Helper.test();
                                            t_maxHaversineErrorRatio = errorRatio;
                                            }

                                            // Compare Polar Coordinate Flat Earth.
                                            double polarDistanceGeo = ApproxDistanceGeo_Polar( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                            double error2 = polarDistanceGeo - D;
                                            double absError2 = Math.Abs( error2 );
                                            double errorRatio2 = absError2 / D;
                                            if (errorRatio2 > t_maxPolarErrorRatio)
                                            {
                                            if (polarDistanceGeo > 0)
                                            {
                                            if (errorRatio2 > t_maxPolarErrorRatio * 1.1)
                                            Helper.test();
                                            t_maxPolarErrorRatio = errorRatio2;
                                            }
                                            else
                                            Helper.dubious();
                                            }

                                            // Compare Pythagorean Theorem with Latitude Adjustment.
                                            double pythagoreanDistanceGeo = ApproxDistanceGeo_PythagoreanCosLatitude( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                            double error3 = pythagoreanDistanceGeo - D;
                                            double absError3 = Math.Abs( error3 );
                                            double errorRatio3 = absError3 / D;
                                            if (errorRatio3 > t_maxPythagoreanErrorRatio)
                                            {
                                            if (D < 2000)
                                            {
                                            if (errorRatio3 > t_maxPythagoreanErrorRatio * 1.05)
                                            Helper.test();
                                            t_maxPythagoreanErrorRatio = errorRatio3;
                                            }
                                            }
                                            }


                                            return D;
                                            }

                                            // As a fraction of the distance.
                                            private static double t_maxHaversineErrorRatio, t_maxPolarErrorRatio, t_maxPythagoreanErrorRatio;


                                            // Average of equatorial and polar radii (meters).
                                            public const double EarthAvgRadius = 6371000;
                                            public const double EarthAvgCircumference = EarthAvgRadius * 2 * PI;
                                            // CAUTION: This is an average of great circles; won't be the actual distance of any longitude or latitude degree.
                                            public const double EarthAvgMeterPerGreatCircleDegree = EarthAvgCircumference / 360;

                                            // Haversine formula (assumes Earth is sphere).
                                            // "deg" = degrees.
                                            // Perhaps based on Haversine Formula in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                            public static double HaversineApproxDistanceGeo(double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg)
                                            {
                                            double lon1 = degreesToRadians( lon1Xdeg );
                                            double lat1 = degreesToRadians( lat1Ydeg );
                                            double lon2 = degreesToRadians( lon2Xdeg );
                                            double lat2 = degreesToRadians( lat2Ydeg );

                                            double dlon = lon2 - lon1;
                                            double dlat = lat2 - lat1;
                                            double sinDLat2 = Sin( dlat / 2 );
                                            double sinDLon2 = Sin( dlon / 2 );
                                            double a = sinDLat2 * sinDLat2 + Cos( lat1 ) * Cos( lat2 ) * sinDLon2 * sinDLon2;
                                            double c = 2 * Atan2( Sqrt( a ), Sqrt( 1 - a ) );
                                            double d = EarthAvgRadius * c;
                                            return d;
                                            }

                                            // From https://stackoverflow.com/a/19772119/199364
                                            // Based on Polar Coordinate Flat Earth in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                            public static double ApproxDistanceGeo_Polar( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                            {
                                            double approxUnitDistSq = ApproxUnitDistSq_Polar(lon1deg, lat1deg, lon2deg, lat2deg, D);
                                            double c = Sqrt( approxUnitDistSq );
                                            return EarthAvgRadius * c;
                                            }

                                            // Might be useful to avoid taking Sqrt, when comparing to some threshold.
                                            // Threshold would have to be adjusted to match: Power(threshold / EarthAvgRadius, 2)
                                            private static double ApproxUnitDistSq_Polar(double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                            {
                                            const double HalfPi = PI / 2; //1.5707963267949;

                                            double lon1 = degreesToRadians(lon1deg);
                                            double lat1 = degreesToRadians(lat1deg);
                                            double lon2 = degreesToRadians(lon2deg);
                                            double lat2 = degreesToRadians(lat2deg);

                                            double a = HalfPi - lat1;
                                            double b = HalfPi - lat2;
                                            double u = a * a + b * b;
                                            double dlon21 = lon2 - lon1;
                                            double cosDeltaLon = Cos( dlon21 );
                                            double v = -2 * a * b * cosDeltaLon;
                                            // TBD: Is "Abs" necessary? That is, is "u + v" ever negative?
                                            // (I think not; "v" looks like a secondary term. Though might be round-off issue near zero when a~=b.)
                                            double approxUnitDistSq = Abs(u + v);

                                            //if (approxUnitDistSq.nearlyEquals(0, 1E-16))
                                            // Helper.dubious();
                                            //else if (D > 0)
                                            //{
                                            // double dba = b - a;
                                            // double unitD = D / EarthAvgRadius;
                                            // double unitDSq = unitD * unitD;
                                            // if (approxUnitDistSq > 2 * unitDSq)
                                            // Helper.dubious();
                                            // else if (approxUnitDistSq * 2 < unitDSq)
                                            // Helper.dubious();
                                            //}

                                            return approxUnitDistSq;
                                            }

                                            // Pythagorean Theorem with Latitude Adjustment - from Ewan Todd - https://stackoverflow.com/a/1664836/199364
                                            // Refined by ToolmakerSteve - https://stackoverflow.com/a/53468745/199364
                                            public static double ApproxDistanceGeo_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                            {
                                            double approxDegreesSq = ApproxDegreesSq_PythagoreanCosLatitude( lon1deg, lat1deg, lon2deg, lat2deg );
                                            // approximate degrees on the great circle between the points.
                                            double d_degrees = Sqrt( approxDegreesSq );
                                            return d_degrees * EarthAvgMeterPerGreatCircleDegree;
                                            }

                                            public static double ApproxDegreesSq_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg )
                                            {
                                            double avgLatDeg = average( lat1deg , lat2deg );
                                            double avgLat = degreesToRadians( avgLatDeg );

                                            double d_ew = (lon2deg - lon1deg) * Cos( avgLat );
                                            double d_ns = (lat2deg - lat1deg);
                                            double approxDegreesSq = d_ew * d_ew + d_ns * d_ns;
                                            return approxDegreesSq;
                                            }





                                            share|improve this answer






























                                              1














                                              If you are measuring distances less than (perhaps) 1 degree lat/long change, are looking for a very high performance approximation, and are willing to accept more inaccuracy than Haversine formula, consider these two alternatives:



                                              (1) "Polar Coordinate Flat-Earth Formula" from Computing Distances:



                                              a = pi/2 - lat1  
                                              b = pi/2 - lat2
                                              c = sqrt( a^2 + b^2 - 2 * a * b * cos(lon2 - lon1) )
                                              d = R * c


                                              (2) Pythagorean theorem adjusted for latitude, as seen in Ewan Todd's SO post:



                                              d_ew = (long1 - long0) * cos(average(lat0, lat1))  
                                              d_ns = (lat1 - lat0)
                                              d = sqrt(d_ew * d_ew + d_ns * d_ns)


                                              NOTES:

                                              Compared to Ewan's post, I've substituted average(lat0, lat1) for lat0 inside of cos( lat0 ).



                                              #2 is vague on whether values are degrees, radians, or kilometers; you will need some conversion code as well. See my complete code at bottom of this post.



                                              #1 is designed to work well even near the poles, though if you are measuring a distance whose endpoints are on "opposite" sides of the pole (longitudes differ by more than 90 degrees?), Haversine is recommended instead, even for small distances.



                                              I haven't thoroughly measured errors of these approaches, so you should take representative points for your application, and compare results to some high-quality library, to decide if the accuracies are acceptable. For distances less than a few kilometers my gut sense is that these are within 1% of correct measurement.





                                              An alternative way to gain high performance (when applicable):



                                              If you have a large set of static points, within one or two degrees of longitude/latitude, that you will then be calculating distances from a small number of dynamic (moving) points, consider converting your static points ONCE to the containing UTM zone (or to any other local Cartesian coordinate system), and then doing all your math in that Cartesian coordinate system.

                                              Cartesian = flat earth = Pythagorean theorem applies, so distance = sqrt(dx^2 + dy^2).



                                              Then the cost of accurately converting the few moving points to UTM is easily afforded.





                                              CAVEAT for #1 (Polar): May be very wrong for distances less than 0.1 (?) meter. Even with double precision math, the following coordinates, whose true distance is about 0.005 meters, was given as "zero" by my implementation of Polar algorithm:



                                              inputs:



                                                  lon1Xdeg    16.6564465477996    double
                                              lat1Ydeg 57.7760262271983 double
                                              lon2Xdeg 16.6564466358281 double
                                              lat2Ydeg 57.776026248554 double


                                              results:



                                              Oblate spheroid formula:  
                                              0.00575254911118364 double
                                              Haversine:
                                              0.00573422966122257 double
                                              Polar:
                                              0


                                              this was due to the two factors u and v exactly canceling each other:



                                                  u   0.632619944868587   double
                                              v -0.632619944868587 double


                                              In another case, it gave a distance of 0.067129 m when the oblate spheroid answer was 0.002887 m. The problem was that cos(lon2 - lon1) was too close to 1, so cos function returned exactly 1.



                                              Other than measuring sub-meter distances, the max errors (compared to an oblate spheroid formula) I found for the limited small-distance data I've fed in so far:



                                                  maxHaversineErrorRatio  0.00350976281908381 double
                                              maxPolarErrorRatio 0.0510789996931342 double


                                              where "1" would represent a 100% error in the answer; e.g. when it returned "0", that was an error of "1" (excluded from above "maxPolar"). So "0.01" would be an error of "1 part in 100" or 1%.



                                              Comparing Polar error with Haversine error over distances less than 2000 meters to see how much worse this simpler formula is. So far, the worst I've seen is 51 parts per 1000 for Polar vs 4 parts per 1000 for Haversine. At about 58 degrees latitude.





                                              Now implemented "Pythagorean with Latitude Adjustment".



                                              It is MUCH more consistent than Polar for distances < 2000 m.

                                              I originally thought the Polar problems were only when < 1 m,

                                              but the result shown immediately below is quite troubling.



                                              As distances approach zero, pythagorean/latitude approaches haversine.
                                              For example this measurement ~ 217 meters:



                                                  lon1Xdeg    16.6531667510102    double
                                              lat1Ydeg 57.7751705615804 double
                                              lon2Xdeg 16.6564468739869 double
                                              lat2Ydeg 57.7760263007586 double

                                              oblate 217.201200413731
                                              haversine 216.518428601051
                                              polar 226.128616011973
                                              pythag-cos 216.518428631907
                                              havErrRatio 0.00314349925958048
                                              polErrRatio 0.041102054598393
                                              pycErrRatio 0.00314349911751603


                                              Polar has a much worse error with these inputs; either there is some mistake in my code, or in Cos function I am running on, or I have to recommend not using Polar, even though most Polar measurements were much closer than this.



                                              OTOH, Pythagorean, even with * cos(latitude) adjustment, has error that increases more rapidly than distance (ratio of max_error/distance increases for larger distances), so you need to carefully consider the maximum distance you will measure, and the acceptable error. In addition, it is not advisable to COMPARE two nearly-equal distances using Pythagorean, to decide which is shorter, as the error is different in different DIRECTIONS (evidence not shown).



                                              Worst case measurements, errorRatio = Abs(error) / distance (Sweden; up to 2000 m):



                                                  t_maxHaversineErrorRatio    0.00351012021578681 double
                                              t_maxPolarErrorRatio 66.0825360597085 double
                                              t_maxPythagoreanErrorRatio 0.00350976281416454 double


                                              As mentioned before, the extreme polar errors are for sub-meter distances, where it could report zero instead of 6 cm, or report over 0.5 m for a distance of 1 cm (hence the "66 x" worst case shown in t_maxPolarErrorRatio), but there are also some poor results at larger distances. [Needs to be tested again with a Cosine function that is known to be highly accurate.]



                                              Measurements taken in C# code in Xamarin.Android running on a Moto E4.





                                              C# code:



                                                  // x=longitude, y= latitude. oblate spheroid formula. TODO: From where?
                                              public static double calculateDistanceDD_AED( double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg )
                                              {
                                              double c_dblEarthRadius = 6378.135; // km
                                              double c_dblFlattening = 1.0 / 298.257223563; // WGS84 inverse
                                              // flattening
                                              // Q: Why "-" for longitudes??
                                              double p1x = -degreesToRadians( lon1Xdeg );
                                              double p1y = degreesToRadians( lat1Ydeg );
                                              double p2x = -degreesToRadians( lon2Xdeg );
                                              double p2y = degreesToRadians( lat2Ydeg );

                                              double F = (p1y + p2y) / 2;
                                              double G = (p1y - p2y) / 2;
                                              double L = (p1x - p2x) / 2;

                                              double sing = Math.Sin( G );
                                              double cosl = Math.Cos( L );
                                              double cosf = Math.Cos( F );
                                              double sinl = Math.Sin( L );
                                              double sinf = Math.Sin( F );
                                              double cosg = Math.Cos( G );

                                              double S = sing * sing * cosl * cosl + cosf * cosf * sinl * sinl;
                                              double C = cosg * cosg * cosl * cosl + sinf * sinf * sinl * sinl;
                                              double W = Math.Atan2( Math.Sqrt( S ), Math.Sqrt( C ) );
                                              if (W == 0.0)
                                              return 0.0;

                                              double R = Math.Sqrt( (S * C) ) / W;
                                              double H1 = (3 * R - 1.0) / (2.0 * C);
                                              double H2 = (3 * R + 1.0) / (2.0 * S);
                                              double D = 2 * W * c_dblEarthRadius;

                                              // Apply flattening factor
                                              D = D * (1.0 + c_dblFlattening * H1 * sinf * sinf * cosg * cosg - c_dblFlattening * H2 * cosf * cosf * sing * sing);

                                              // Transform to meters
                                              D = D * 1000.0;

                                              // tmstest
                                              if (true)
                                              {
                                              // Compare Haversine.
                                              double haversine = HaversineApproxDistanceGeo( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg );
                                              double error = haversine - D;
                                              double absError = Math.Abs( error );
                                              double errorRatio = absError / D;
                                              if (errorRatio > t_maxHaversineErrorRatio)
                                              {
                                              if (errorRatio > t_maxHaversineErrorRatio * 1.1)
                                              Helper.test();
                                              t_maxHaversineErrorRatio = errorRatio;
                                              }

                                              // Compare Polar Coordinate Flat Earth.
                                              double polarDistanceGeo = ApproxDistanceGeo_Polar( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                              double error2 = polarDistanceGeo - D;
                                              double absError2 = Math.Abs( error2 );
                                              double errorRatio2 = absError2 / D;
                                              if (errorRatio2 > t_maxPolarErrorRatio)
                                              {
                                              if (polarDistanceGeo > 0)
                                              {
                                              if (errorRatio2 > t_maxPolarErrorRatio * 1.1)
                                              Helper.test();
                                              t_maxPolarErrorRatio = errorRatio2;
                                              }
                                              else
                                              Helper.dubious();
                                              }

                                              // Compare Pythagorean Theorem with Latitude Adjustment.
                                              double pythagoreanDistanceGeo = ApproxDistanceGeo_PythagoreanCosLatitude( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                              double error3 = pythagoreanDistanceGeo - D;
                                              double absError3 = Math.Abs( error3 );
                                              double errorRatio3 = absError3 / D;
                                              if (errorRatio3 > t_maxPythagoreanErrorRatio)
                                              {
                                              if (D < 2000)
                                              {
                                              if (errorRatio3 > t_maxPythagoreanErrorRatio * 1.05)
                                              Helper.test();
                                              t_maxPythagoreanErrorRatio = errorRatio3;
                                              }
                                              }
                                              }


                                              return D;
                                              }

                                              // As a fraction of the distance.
                                              private static double t_maxHaversineErrorRatio, t_maxPolarErrorRatio, t_maxPythagoreanErrorRatio;


                                              // Average of equatorial and polar radii (meters).
                                              public const double EarthAvgRadius = 6371000;
                                              public const double EarthAvgCircumference = EarthAvgRadius * 2 * PI;
                                              // CAUTION: This is an average of great circles; won't be the actual distance of any longitude or latitude degree.
                                              public const double EarthAvgMeterPerGreatCircleDegree = EarthAvgCircumference / 360;

                                              // Haversine formula (assumes Earth is sphere).
                                              // "deg" = degrees.
                                              // Perhaps based on Haversine Formula in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                              public static double HaversineApproxDistanceGeo(double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg)
                                              {
                                              double lon1 = degreesToRadians( lon1Xdeg );
                                              double lat1 = degreesToRadians( lat1Ydeg );
                                              double lon2 = degreesToRadians( lon2Xdeg );
                                              double lat2 = degreesToRadians( lat2Ydeg );

                                              double dlon = lon2 - lon1;
                                              double dlat = lat2 - lat1;
                                              double sinDLat2 = Sin( dlat / 2 );
                                              double sinDLon2 = Sin( dlon / 2 );
                                              double a = sinDLat2 * sinDLat2 + Cos( lat1 ) * Cos( lat2 ) * sinDLon2 * sinDLon2;
                                              double c = 2 * Atan2( Sqrt( a ), Sqrt( 1 - a ) );
                                              double d = EarthAvgRadius * c;
                                              return d;
                                              }

                                              // From https://stackoverflow.com/a/19772119/199364
                                              // Based on Polar Coordinate Flat Earth in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                              public static double ApproxDistanceGeo_Polar( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                              {
                                              double approxUnitDistSq = ApproxUnitDistSq_Polar(lon1deg, lat1deg, lon2deg, lat2deg, D);
                                              double c = Sqrt( approxUnitDistSq );
                                              return EarthAvgRadius * c;
                                              }

                                              // Might be useful to avoid taking Sqrt, when comparing to some threshold.
                                              // Threshold would have to be adjusted to match: Power(threshold / EarthAvgRadius, 2)
                                              private static double ApproxUnitDistSq_Polar(double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                              {
                                              const double HalfPi = PI / 2; //1.5707963267949;

                                              double lon1 = degreesToRadians(lon1deg);
                                              double lat1 = degreesToRadians(lat1deg);
                                              double lon2 = degreesToRadians(lon2deg);
                                              double lat2 = degreesToRadians(lat2deg);

                                              double a = HalfPi - lat1;
                                              double b = HalfPi - lat2;
                                              double u = a * a + b * b;
                                              double dlon21 = lon2 - lon1;
                                              double cosDeltaLon = Cos( dlon21 );
                                              double v = -2 * a * b * cosDeltaLon;
                                              // TBD: Is "Abs" necessary? That is, is "u + v" ever negative?
                                              // (I think not; "v" looks like a secondary term. Though might be round-off issue near zero when a~=b.)
                                              double approxUnitDistSq = Abs(u + v);

                                              //if (approxUnitDistSq.nearlyEquals(0, 1E-16))
                                              // Helper.dubious();
                                              //else if (D > 0)
                                              //{
                                              // double dba = b - a;
                                              // double unitD = D / EarthAvgRadius;
                                              // double unitDSq = unitD * unitD;
                                              // if (approxUnitDistSq > 2 * unitDSq)
                                              // Helper.dubious();
                                              // else if (approxUnitDistSq * 2 < unitDSq)
                                              // Helper.dubious();
                                              //}

                                              return approxUnitDistSq;
                                              }

                                              // Pythagorean Theorem with Latitude Adjustment - from Ewan Todd - https://stackoverflow.com/a/1664836/199364
                                              // Refined by ToolmakerSteve - https://stackoverflow.com/a/53468745/199364
                                              public static double ApproxDistanceGeo_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                              {
                                              double approxDegreesSq = ApproxDegreesSq_PythagoreanCosLatitude( lon1deg, lat1deg, lon2deg, lat2deg );
                                              // approximate degrees on the great circle between the points.
                                              double d_degrees = Sqrt( approxDegreesSq );
                                              return d_degrees * EarthAvgMeterPerGreatCircleDegree;
                                              }

                                              public static double ApproxDegreesSq_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg )
                                              {
                                              double avgLatDeg = average( lat1deg , lat2deg );
                                              double avgLat = degreesToRadians( avgLatDeg );

                                              double d_ew = (lon2deg - lon1deg) * Cos( avgLat );
                                              double d_ns = (lat2deg - lat1deg);
                                              double approxDegreesSq = d_ew * d_ew + d_ns * d_ns;
                                              return approxDegreesSq;
                                              }





                                              share|improve this answer




























                                                1












                                                1








                                                1







                                                If you are measuring distances less than (perhaps) 1 degree lat/long change, are looking for a very high performance approximation, and are willing to accept more inaccuracy than Haversine formula, consider these two alternatives:



                                                (1) "Polar Coordinate Flat-Earth Formula" from Computing Distances:



                                                a = pi/2 - lat1  
                                                b = pi/2 - lat2
                                                c = sqrt( a^2 + b^2 - 2 * a * b * cos(lon2 - lon1) )
                                                d = R * c


                                                (2) Pythagorean theorem adjusted for latitude, as seen in Ewan Todd's SO post:



                                                d_ew = (long1 - long0) * cos(average(lat0, lat1))  
                                                d_ns = (lat1 - lat0)
                                                d = sqrt(d_ew * d_ew + d_ns * d_ns)


                                                NOTES:

                                                Compared to Ewan's post, I've substituted average(lat0, lat1) for lat0 inside of cos( lat0 ).



                                                #2 is vague on whether values are degrees, radians, or kilometers; you will need some conversion code as well. See my complete code at bottom of this post.



                                                #1 is designed to work well even near the poles, though if you are measuring a distance whose endpoints are on "opposite" sides of the pole (longitudes differ by more than 90 degrees?), Haversine is recommended instead, even for small distances.



                                                I haven't thoroughly measured errors of these approaches, so you should take representative points for your application, and compare results to some high-quality library, to decide if the accuracies are acceptable. For distances less than a few kilometers my gut sense is that these are within 1% of correct measurement.





                                                An alternative way to gain high performance (when applicable):



                                                If you have a large set of static points, within one or two degrees of longitude/latitude, that you will then be calculating distances from a small number of dynamic (moving) points, consider converting your static points ONCE to the containing UTM zone (or to any other local Cartesian coordinate system), and then doing all your math in that Cartesian coordinate system.

                                                Cartesian = flat earth = Pythagorean theorem applies, so distance = sqrt(dx^2 + dy^2).



                                                Then the cost of accurately converting the few moving points to UTM is easily afforded.





                                                CAVEAT for #1 (Polar): May be very wrong for distances less than 0.1 (?) meter. Even with double precision math, the following coordinates, whose true distance is about 0.005 meters, was given as "zero" by my implementation of Polar algorithm:



                                                inputs:



                                                    lon1Xdeg    16.6564465477996    double
                                                lat1Ydeg 57.7760262271983 double
                                                lon2Xdeg 16.6564466358281 double
                                                lat2Ydeg 57.776026248554 double


                                                results:



                                                Oblate spheroid formula:  
                                                0.00575254911118364 double
                                                Haversine:
                                                0.00573422966122257 double
                                                Polar:
                                                0


                                                this was due to the two factors u and v exactly canceling each other:



                                                    u   0.632619944868587   double
                                                v -0.632619944868587 double


                                                In another case, it gave a distance of 0.067129 m when the oblate spheroid answer was 0.002887 m. The problem was that cos(lon2 - lon1) was too close to 1, so cos function returned exactly 1.



                                                Other than measuring sub-meter distances, the max errors (compared to an oblate spheroid formula) I found for the limited small-distance data I've fed in so far:



                                                    maxHaversineErrorRatio  0.00350976281908381 double
                                                maxPolarErrorRatio 0.0510789996931342 double


                                                where "1" would represent a 100% error in the answer; e.g. when it returned "0", that was an error of "1" (excluded from above "maxPolar"). So "0.01" would be an error of "1 part in 100" or 1%.



                                                Comparing Polar error with Haversine error over distances less than 2000 meters to see how much worse this simpler formula is. So far, the worst I've seen is 51 parts per 1000 for Polar vs 4 parts per 1000 for Haversine. At about 58 degrees latitude.





                                                Now implemented "Pythagorean with Latitude Adjustment".



                                                It is MUCH more consistent than Polar for distances < 2000 m.

                                                I originally thought the Polar problems were only when < 1 m,

                                                but the result shown immediately below is quite troubling.



                                                As distances approach zero, pythagorean/latitude approaches haversine.
                                                For example this measurement ~ 217 meters:



                                                    lon1Xdeg    16.6531667510102    double
                                                lat1Ydeg 57.7751705615804 double
                                                lon2Xdeg 16.6564468739869 double
                                                lat2Ydeg 57.7760263007586 double

                                                oblate 217.201200413731
                                                haversine 216.518428601051
                                                polar 226.128616011973
                                                pythag-cos 216.518428631907
                                                havErrRatio 0.00314349925958048
                                                polErrRatio 0.041102054598393
                                                pycErrRatio 0.00314349911751603


                                                Polar has a much worse error with these inputs; either there is some mistake in my code, or in Cos function I am running on, or I have to recommend not using Polar, even though most Polar measurements were much closer than this.



                                                OTOH, Pythagorean, even with * cos(latitude) adjustment, has error that increases more rapidly than distance (ratio of max_error/distance increases for larger distances), so you need to carefully consider the maximum distance you will measure, and the acceptable error. In addition, it is not advisable to COMPARE two nearly-equal distances using Pythagorean, to decide which is shorter, as the error is different in different DIRECTIONS (evidence not shown).



                                                Worst case measurements, errorRatio = Abs(error) / distance (Sweden; up to 2000 m):



                                                    t_maxHaversineErrorRatio    0.00351012021578681 double
                                                t_maxPolarErrorRatio 66.0825360597085 double
                                                t_maxPythagoreanErrorRatio 0.00350976281416454 double


                                                As mentioned before, the extreme polar errors are for sub-meter distances, where it could report zero instead of 6 cm, or report over 0.5 m for a distance of 1 cm (hence the "66 x" worst case shown in t_maxPolarErrorRatio), but there are also some poor results at larger distances. [Needs to be tested again with a Cosine function that is known to be highly accurate.]



                                                Measurements taken in C# code in Xamarin.Android running on a Moto E4.





                                                C# code:



                                                    // x=longitude, y= latitude. oblate spheroid formula. TODO: From where?
                                                public static double calculateDistanceDD_AED( double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg )
                                                {
                                                double c_dblEarthRadius = 6378.135; // km
                                                double c_dblFlattening = 1.0 / 298.257223563; // WGS84 inverse
                                                // flattening
                                                // Q: Why "-" for longitudes??
                                                double p1x = -degreesToRadians( lon1Xdeg );
                                                double p1y = degreesToRadians( lat1Ydeg );
                                                double p2x = -degreesToRadians( lon2Xdeg );
                                                double p2y = degreesToRadians( lat2Ydeg );

                                                double F = (p1y + p2y) / 2;
                                                double G = (p1y - p2y) / 2;
                                                double L = (p1x - p2x) / 2;

                                                double sing = Math.Sin( G );
                                                double cosl = Math.Cos( L );
                                                double cosf = Math.Cos( F );
                                                double sinl = Math.Sin( L );
                                                double sinf = Math.Sin( F );
                                                double cosg = Math.Cos( G );

                                                double S = sing * sing * cosl * cosl + cosf * cosf * sinl * sinl;
                                                double C = cosg * cosg * cosl * cosl + sinf * sinf * sinl * sinl;
                                                double W = Math.Atan2( Math.Sqrt( S ), Math.Sqrt( C ) );
                                                if (W == 0.0)
                                                return 0.0;

                                                double R = Math.Sqrt( (S * C) ) / W;
                                                double H1 = (3 * R - 1.0) / (2.0 * C);
                                                double H2 = (3 * R + 1.0) / (2.0 * S);
                                                double D = 2 * W * c_dblEarthRadius;

                                                // Apply flattening factor
                                                D = D * (1.0 + c_dblFlattening * H1 * sinf * sinf * cosg * cosg - c_dblFlattening * H2 * cosf * cosf * sing * sing);

                                                // Transform to meters
                                                D = D * 1000.0;

                                                // tmstest
                                                if (true)
                                                {
                                                // Compare Haversine.
                                                double haversine = HaversineApproxDistanceGeo( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg );
                                                double error = haversine - D;
                                                double absError = Math.Abs( error );
                                                double errorRatio = absError / D;
                                                if (errorRatio > t_maxHaversineErrorRatio)
                                                {
                                                if (errorRatio > t_maxHaversineErrorRatio * 1.1)
                                                Helper.test();
                                                t_maxHaversineErrorRatio = errorRatio;
                                                }

                                                // Compare Polar Coordinate Flat Earth.
                                                double polarDistanceGeo = ApproxDistanceGeo_Polar( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                                double error2 = polarDistanceGeo - D;
                                                double absError2 = Math.Abs( error2 );
                                                double errorRatio2 = absError2 / D;
                                                if (errorRatio2 > t_maxPolarErrorRatio)
                                                {
                                                if (polarDistanceGeo > 0)
                                                {
                                                if (errorRatio2 > t_maxPolarErrorRatio * 1.1)
                                                Helper.test();
                                                t_maxPolarErrorRatio = errorRatio2;
                                                }
                                                else
                                                Helper.dubious();
                                                }

                                                // Compare Pythagorean Theorem with Latitude Adjustment.
                                                double pythagoreanDistanceGeo = ApproxDistanceGeo_PythagoreanCosLatitude( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                                double error3 = pythagoreanDistanceGeo - D;
                                                double absError3 = Math.Abs( error3 );
                                                double errorRatio3 = absError3 / D;
                                                if (errorRatio3 > t_maxPythagoreanErrorRatio)
                                                {
                                                if (D < 2000)
                                                {
                                                if (errorRatio3 > t_maxPythagoreanErrorRatio * 1.05)
                                                Helper.test();
                                                t_maxPythagoreanErrorRatio = errorRatio3;
                                                }
                                                }
                                                }


                                                return D;
                                                }

                                                // As a fraction of the distance.
                                                private static double t_maxHaversineErrorRatio, t_maxPolarErrorRatio, t_maxPythagoreanErrorRatio;


                                                // Average of equatorial and polar radii (meters).
                                                public const double EarthAvgRadius = 6371000;
                                                public const double EarthAvgCircumference = EarthAvgRadius * 2 * PI;
                                                // CAUTION: This is an average of great circles; won't be the actual distance of any longitude or latitude degree.
                                                public const double EarthAvgMeterPerGreatCircleDegree = EarthAvgCircumference / 360;

                                                // Haversine formula (assumes Earth is sphere).
                                                // "deg" = degrees.
                                                // Perhaps based on Haversine Formula in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                                public static double HaversineApproxDistanceGeo(double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg)
                                                {
                                                double lon1 = degreesToRadians( lon1Xdeg );
                                                double lat1 = degreesToRadians( lat1Ydeg );
                                                double lon2 = degreesToRadians( lon2Xdeg );
                                                double lat2 = degreesToRadians( lat2Ydeg );

                                                double dlon = lon2 - lon1;
                                                double dlat = lat2 - lat1;
                                                double sinDLat2 = Sin( dlat / 2 );
                                                double sinDLon2 = Sin( dlon / 2 );
                                                double a = sinDLat2 * sinDLat2 + Cos( lat1 ) * Cos( lat2 ) * sinDLon2 * sinDLon2;
                                                double c = 2 * Atan2( Sqrt( a ), Sqrt( 1 - a ) );
                                                double d = EarthAvgRadius * c;
                                                return d;
                                                }

                                                // From https://stackoverflow.com/a/19772119/199364
                                                // Based on Polar Coordinate Flat Earth in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                                public static double ApproxDistanceGeo_Polar( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                double approxUnitDistSq = ApproxUnitDistSq_Polar(lon1deg, lat1deg, lon2deg, lat2deg, D);
                                                double c = Sqrt( approxUnitDistSq );
                                                return EarthAvgRadius * c;
                                                }

                                                // Might be useful to avoid taking Sqrt, when comparing to some threshold.
                                                // Threshold would have to be adjusted to match: Power(threshold / EarthAvgRadius, 2)
                                                private static double ApproxUnitDistSq_Polar(double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                const double HalfPi = PI / 2; //1.5707963267949;

                                                double lon1 = degreesToRadians(lon1deg);
                                                double lat1 = degreesToRadians(lat1deg);
                                                double lon2 = degreesToRadians(lon2deg);
                                                double lat2 = degreesToRadians(lat2deg);

                                                double a = HalfPi - lat1;
                                                double b = HalfPi - lat2;
                                                double u = a * a + b * b;
                                                double dlon21 = lon2 - lon1;
                                                double cosDeltaLon = Cos( dlon21 );
                                                double v = -2 * a * b * cosDeltaLon;
                                                // TBD: Is "Abs" necessary? That is, is "u + v" ever negative?
                                                // (I think not; "v" looks like a secondary term. Though might be round-off issue near zero when a~=b.)
                                                double approxUnitDistSq = Abs(u + v);

                                                //if (approxUnitDistSq.nearlyEquals(0, 1E-16))
                                                // Helper.dubious();
                                                //else if (D > 0)
                                                //{
                                                // double dba = b - a;
                                                // double unitD = D / EarthAvgRadius;
                                                // double unitDSq = unitD * unitD;
                                                // if (approxUnitDistSq > 2 * unitDSq)
                                                // Helper.dubious();
                                                // else if (approxUnitDistSq * 2 < unitDSq)
                                                // Helper.dubious();
                                                //}

                                                return approxUnitDistSq;
                                                }

                                                // Pythagorean Theorem with Latitude Adjustment - from Ewan Todd - https://stackoverflow.com/a/1664836/199364
                                                // Refined by ToolmakerSteve - https://stackoverflow.com/a/53468745/199364
                                                public static double ApproxDistanceGeo_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                double approxDegreesSq = ApproxDegreesSq_PythagoreanCosLatitude( lon1deg, lat1deg, lon2deg, lat2deg );
                                                // approximate degrees on the great circle between the points.
                                                double d_degrees = Sqrt( approxDegreesSq );
                                                return d_degrees * EarthAvgMeterPerGreatCircleDegree;
                                                }

                                                public static double ApproxDegreesSq_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg )
                                                {
                                                double avgLatDeg = average( lat1deg , lat2deg );
                                                double avgLat = degreesToRadians( avgLatDeg );

                                                double d_ew = (lon2deg - lon1deg) * Cos( avgLat );
                                                double d_ns = (lat2deg - lat1deg);
                                                double approxDegreesSq = d_ew * d_ew + d_ns * d_ns;
                                                return approxDegreesSq;
                                                }





                                                share|improve this answer















                                                If you are measuring distances less than (perhaps) 1 degree lat/long change, are looking for a very high performance approximation, and are willing to accept more inaccuracy than Haversine formula, consider these two alternatives:



                                                (1) "Polar Coordinate Flat-Earth Formula" from Computing Distances:



                                                a = pi/2 - lat1  
                                                b = pi/2 - lat2
                                                c = sqrt( a^2 + b^2 - 2 * a * b * cos(lon2 - lon1) )
                                                d = R * c


                                                (2) Pythagorean theorem adjusted for latitude, as seen in Ewan Todd's SO post:



                                                d_ew = (long1 - long0) * cos(average(lat0, lat1))  
                                                d_ns = (lat1 - lat0)
                                                d = sqrt(d_ew * d_ew + d_ns * d_ns)


                                                NOTES:

                                                Compared to Ewan's post, I've substituted average(lat0, lat1) for lat0 inside of cos( lat0 ).



                                                #2 is vague on whether values are degrees, radians, or kilometers; you will need some conversion code as well. See my complete code at bottom of this post.



                                                #1 is designed to work well even near the poles, though if you are measuring a distance whose endpoints are on "opposite" sides of the pole (longitudes differ by more than 90 degrees?), Haversine is recommended instead, even for small distances.



                                                I haven't thoroughly measured errors of these approaches, so you should take representative points for your application, and compare results to some high-quality library, to decide if the accuracies are acceptable. For distances less than a few kilometers my gut sense is that these are within 1% of correct measurement.





                                                An alternative way to gain high performance (when applicable):



                                                If you have a large set of static points, within one or two degrees of longitude/latitude, that you will then be calculating distances from a small number of dynamic (moving) points, consider converting your static points ONCE to the containing UTM zone (or to any other local Cartesian coordinate system), and then doing all your math in that Cartesian coordinate system.

                                                Cartesian = flat earth = Pythagorean theorem applies, so distance = sqrt(dx^2 + dy^2).



                                                Then the cost of accurately converting the few moving points to UTM is easily afforded.





                                                CAVEAT for #1 (Polar): May be very wrong for distances less than 0.1 (?) meter. Even with double precision math, the following coordinates, whose true distance is about 0.005 meters, was given as "zero" by my implementation of Polar algorithm:



                                                inputs:



                                                    lon1Xdeg    16.6564465477996    double
                                                lat1Ydeg 57.7760262271983 double
                                                lon2Xdeg 16.6564466358281 double
                                                lat2Ydeg 57.776026248554 double


                                                results:



                                                Oblate spheroid formula:  
                                                0.00575254911118364 double
                                                Haversine:
                                                0.00573422966122257 double
                                                Polar:
                                                0


                                                this was due to the two factors u and v exactly canceling each other:



                                                    u   0.632619944868587   double
                                                v -0.632619944868587 double


                                                In another case, it gave a distance of 0.067129 m when the oblate spheroid answer was 0.002887 m. The problem was that cos(lon2 - lon1) was too close to 1, so cos function returned exactly 1.



                                                Other than measuring sub-meter distances, the max errors (compared to an oblate spheroid formula) I found for the limited small-distance data I've fed in so far:



                                                    maxHaversineErrorRatio  0.00350976281908381 double
                                                maxPolarErrorRatio 0.0510789996931342 double


                                                where "1" would represent a 100% error in the answer; e.g. when it returned "0", that was an error of "1" (excluded from above "maxPolar"). So "0.01" would be an error of "1 part in 100" or 1%.



                                                Comparing Polar error with Haversine error over distances less than 2000 meters to see how much worse this simpler formula is. So far, the worst I've seen is 51 parts per 1000 for Polar vs 4 parts per 1000 for Haversine. At about 58 degrees latitude.





                                                Now implemented "Pythagorean with Latitude Adjustment".



                                                It is MUCH more consistent than Polar for distances < 2000 m.

                                                I originally thought the Polar problems were only when < 1 m,

                                                but the result shown immediately below is quite troubling.



                                                As distances approach zero, pythagorean/latitude approaches haversine.
                                                For example this measurement ~ 217 meters:



                                                    lon1Xdeg    16.6531667510102    double
                                                lat1Ydeg 57.7751705615804 double
                                                lon2Xdeg 16.6564468739869 double
                                                lat2Ydeg 57.7760263007586 double

                                                oblate 217.201200413731
                                                haversine 216.518428601051
                                                polar 226.128616011973
                                                pythag-cos 216.518428631907
                                                havErrRatio 0.00314349925958048
                                                polErrRatio 0.041102054598393
                                                pycErrRatio 0.00314349911751603


                                                Polar has a much worse error with these inputs; either there is some mistake in my code, or in Cos function I am running on, or I have to recommend not using Polar, even though most Polar measurements were much closer than this.



                                                OTOH, Pythagorean, even with * cos(latitude) adjustment, has error that increases more rapidly than distance (ratio of max_error/distance increases for larger distances), so you need to carefully consider the maximum distance you will measure, and the acceptable error. In addition, it is not advisable to COMPARE two nearly-equal distances using Pythagorean, to decide which is shorter, as the error is different in different DIRECTIONS (evidence not shown).



                                                Worst case measurements, errorRatio = Abs(error) / distance (Sweden; up to 2000 m):



                                                    t_maxHaversineErrorRatio    0.00351012021578681 double
                                                t_maxPolarErrorRatio 66.0825360597085 double
                                                t_maxPythagoreanErrorRatio 0.00350976281416454 double


                                                As mentioned before, the extreme polar errors are for sub-meter distances, where it could report zero instead of 6 cm, or report over 0.5 m for a distance of 1 cm (hence the "66 x" worst case shown in t_maxPolarErrorRatio), but there are also some poor results at larger distances. [Needs to be tested again with a Cosine function that is known to be highly accurate.]



                                                Measurements taken in C# code in Xamarin.Android running on a Moto E4.





                                                C# code:



                                                    // x=longitude, y= latitude. oblate spheroid formula. TODO: From where?
                                                public static double calculateDistanceDD_AED( double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg )
                                                {
                                                double c_dblEarthRadius = 6378.135; // km
                                                double c_dblFlattening = 1.0 / 298.257223563; // WGS84 inverse
                                                // flattening
                                                // Q: Why "-" for longitudes??
                                                double p1x = -degreesToRadians( lon1Xdeg );
                                                double p1y = degreesToRadians( lat1Ydeg );
                                                double p2x = -degreesToRadians( lon2Xdeg );
                                                double p2y = degreesToRadians( lat2Ydeg );

                                                double F = (p1y + p2y) / 2;
                                                double G = (p1y - p2y) / 2;
                                                double L = (p1x - p2x) / 2;

                                                double sing = Math.Sin( G );
                                                double cosl = Math.Cos( L );
                                                double cosf = Math.Cos( F );
                                                double sinl = Math.Sin( L );
                                                double sinf = Math.Sin( F );
                                                double cosg = Math.Cos( G );

                                                double S = sing * sing * cosl * cosl + cosf * cosf * sinl * sinl;
                                                double C = cosg * cosg * cosl * cosl + sinf * sinf * sinl * sinl;
                                                double W = Math.Atan2( Math.Sqrt( S ), Math.Sqrt( C ) );
                                                if (W == 0.0)
                                                return 0.0;

                                                double R = Math.Sqrt( (S * C) ) / W;
                                                double H1 = (3 * R - 1.0) / (2.0 * C);
                                                double H2 = (3 * R + 1.0) / (2.0 * S);
                                                double D = 2 * W * c_dblEarthRadius;

                                                // Apply flattening factor
                                                D = D * (1.0 + c_dblFlattening * H1 * sinf * sinf * cosg * cosg - c_dblFlattening * H2 * cosf * cosf * sing * sing);

                                                // Transform to meters
                                                D = D * 1000.0;

                                                // tmstest
                                                if (true)
                                                {
                                                // Compare Haversine.
                                                double haversine = HaversineApproxDistanceGeo( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg );
                                                double error = haversine - D;
                                                double absError = Math.Abs( error );
                                                double errorRatio = absError / D;
                                                if (errorRatio > t_maxHaversineErrorRatio)
                                                {
                                                if (errorRatio > t_maxHaversineErrorRatio * 1.1)
                                                Helper.test();
                                                t_maxHaversineErrorRatio = errorRatio;
                                                }

                                                // Compare Polar Coordinate Flat Earth.
                                                double polarDistanceGeo = ApproxDistanceGeo_Polar( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                                double error2 = polarDistanceGeo - D;
                                                double absError2 = Math.Abs( error2 );
                                                double errorRatio2 = absError2 / D;
                                                if (errorRatio2 > t_maxPolarErrorRatio)
                                                {
                                                if (polarDistanceGeo > 0)
                                                {
                                                if (errorRatio2 > t_maxPolarErrorRatio * 1.1)
                                                Helper.test();
                                                t_maxPolarErrorRatio = errorRatio2;
                                                }
                                                else
                                                Helper.dubious();
                                                }

                                                // Compare Pythagorean Theorem with Latitude Adjustment.
                                                double pythagoreanDistanceGeo = ApproxDistanceGeo_PythagoreanCosLatitude( lon1Xdeg, lat1Ydeg, lon2Xdeg, lat2Ydeg, D );
                                                double error3 = pythagoreanDistanceGeo - D;
                                                double absError3 = Math.Abs( error3 );
                                                double errorRatio3 = absError3 / D;
                                                if (errorRatio3 > t_maxPythagoreanErrorRatio)
                                                {
                                                if (D < 2000)
                                                {
                                                if (errorRatio3 > t_maxPythagoreanErrorRatio * 1.05)
                                                Helper.test();
                                                t_maxPythagoreanErrorRatio = errorRatio3;
                                                }
                                                }
                                                }


                                                return D;
                                                }

                                                // As a fraction of the distance.
                                                private static double t_maxHaversineErrorRatio, t_maxPolarErrorRatio, t_maxPythagoreanErrorRatio;


                                                // Average of equatorial and polar radii (meters).
                                                public const double EarthAvgRadius = 6371000;
                                                public const double EarthAvgCircumference = EarthAvgRadius * 2 * PI;
                                                // CAUTION: This is an average of great circles; won't be the actual distance of any longitude or latitude degree.
                                                public const double EarthAvgMeterPerGreatCircleDegree = EarthAvgCircumference / 360;

                                                // Haversine formula (assumes Earth is sphere).
                                                // "deg" = degrees.
                                                // Perhaps based on Haversine Formula in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                                public static double HaversineApproxDistanceGeo(double lon1Xdeg, double lat1Ydeg, double lon2Xdeg, double lat2Ydeg)
                                                {
                                                double lon1 = degreesToRadians( lon1Xdeg );
                                                double lat1 = degreesToRadians( lat1Ydeg );
                                                double lon2 = degreesToRadians( lon2Xdeg );
                                                double lat2 = degreesToRadians( lat2Ydeg );

                                                double dlon = lon2 - lon1;
                                                double dlat = lat2 - lat1;
                                                double sinDLat2 = Sin( dlat / 2 );
                                                double sinDLon2 = Sin( dlon / 2 );
                                                double a = sinDLat2 * sinDLat2 + Cos( lat1 ) * Cos( lat2 ) * sinDLon2 * sinDLon2;
                                                double c = 2 * Atan2( Sqrt( a ), Sqrt( 1 - a ) );
                                                double d = EarthAvgRadius * c;
                                                return d;
                                                }

                                                // From https://stackoverflow.com/a/19772119/199364
                                                // Based on Polar Coordinate Flat Earth in https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
                                                public static double ApproxDistanceGeo_Polar( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                double approxUnitDistSq = ApproxUnitDistSq_Polar(lon1deg, lat1deg, lon2deg, lat2deg, D);
                                                double c = Sqrt( approxUnitDistSq );
                                                return EarthAvgRadius * c;
                                                }

                                                // Might be useful to avoid taking Sqrt, when comparing to some threshold.
                                                // Threshold would have to be adjusted to match: Power(threshold / EarthAvgRadius, 2)
                                                private static double ApproxUnitDistSq_Polar(double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                const double HalfPi = PI / 2; //1.5707963267949;

                                                double lon1 = degreesToRadians(lon1deg);
                                                double lat1 = degreesToRadians(lat1deg);
                                                double lon2 = degreesToRadians(lon2deg);
                                                double lat2 = degreesToRadians(lat2deg);

                                                double a = HalfPi - lat1;
                                                double b = HalfPi - lat2;
                                                double u = a * a + b * b;
                                                double dlon21 = lon2 - lon1;
                                                double cosDeltaLon = Cos( dlon21 );
                                                double v = -2 * a * b * cosDeltaLon;
                                                // TBD: Is "Abs" necessary? That is, is "u + v" ever negative?
                                                // (I think not; "v" looks like a secondary term. Though might be round-off issue near zero when a~=b.)
                                                double approxUnitDistSq = Abs(u + v);

                                                //if (approxUnitDistSq.nearlyEquals(0, 1E-16))
                                                // Helper.dubious();
                                                //else if (D > 0)
                                                //{
                                                // double dba = b - a;
                                                // double unitD = D / EarthAvgRadius;
                                                // double unitDSq = unitD * unitD;
                                                // if (approxUnitDistSq > 2 * unitDSq)
                                                // Helper.dubious();
                                                // else if (approxUnitDistSq * 2 < unitDSq)
                                                // Helper.dubious();
                                                //}

                                                return approxUnitDistSq;
                                                }

                                                // Pythagorean Theorem with Latitude Adjustment - from Ewan Todd - https://stackoverflow.com/a/1664836/199364
                                                // Refined by ToolmakerSteve - https://stackoverflow.com/a/53468745/199364
                                                public static double ApproxDistanceGeo_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg, double D = 0 )
                                                {
                                                double approxDegreesSq = ApproxDegreesSq_PythagoreanCosLatitude( lon1deg, lat1deg, lon2deg, lat2deg );
                                                // approximate degrees on the great circle between the points.
                                                double d_degrees = Sqrt( approxDegreesSq );
                                                return d_degrees * EarthAvgMeterPerGreatCircleDegree;
                                                }

                                                public static double ApproxDegreesSq_PythagoreanCosLatitude( double lon1deg, double lat1deg, double lon2deg, double lat2deg )
                                                {
                                                double avgLatDeg = average( lat1deg , lat2deg );
                                                double avgLat = degreesToRadians( avgLatDeg );

                                                double d_ew = (lon2deg - lon1deg) * Cos( avgLat );
                                                double d_ns = (lat2deg - lat1deg);
                                                double approxDegreesSq = d_ew * d_ew + d_ns * d_ns;
                                                return approxDegreesSq;
                                                }






                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 25 '18 at 19:51

























                                                answered Nov 25 '18 at 14:57









                                                ToolmakerSteveToolmakerSteve

                                                3,675135104




                                                3,675135104























                                                    0














                                                    I am done using SQL query



                                                    select *, (acos(sin(input_lat* 0.01745329)*sin(lattitude *0.01745329) + cos(input_lat *0.01745329)*cos(lattitude *0.01745329)*cos((input_long -longitude)*0.01745329))* 57.29577951 )* 69.16 As D  from table_name 





                                                    share|improve this answer






























                                                      0














                                                      I am done using SQL query



                                                      select *, (acos(sin(input_lat* 0.01745329)*sin(lattitude *0.01745329) + cos(input_lat *0.01745329)*cos(lattitude *0.01745329)*cos((input_long -longitude)*0.01745329))* 57.29577951 )* 69.16 As D  from table_name 





                                                      share|improve this answer




























                                                        0












                                                        0








                                                        0







                                                        I am done using SQL query



                                                        select *, (acos(sin(input_lat* 0.01745329)*sin(lattitude *0.01745329) + cos(input_lat *0.01745329)*cos(lattitude *0.01745329)*cos((input_long -longitude)*0.01745329))* 57.29577951 )* 69.16 As D  from table_name 





                                                        share|improve this answer















                                                        I am done using SQL query



                                                        select *, (acos(sin(input_lat* 0.01745329)*sin(lattitude *0.01745329) + cos(input_lat *0.01745329)*cos(lattitude *0.01745329)*cos((input_long -longitude)*0.01745329))* 57.29577951 )* 69.16 As D  from table_name 






                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Nov 25 '18 at 18:43









                                                        Richard

                                                        27.6k19110171




                                                        27.6k19110171










                                                        answered Sep 14 '17 at 11:10









                                                        Ganesh GiriGanesh Giri

                                                        30515




                                                        30515























                                                            0














                                                            Following is the module (coded in f90) containing three formulas discussed in the previous answers. You can either put this module at the top of your program
                                                            (before PROGRAM MAIN) or compile it separately and include the module directory during compilation. The following module contains three formulas. First two are great-circle distances based on the assumption that earth is spherical.



                                                            module spherical_dists

                                                            contains

                                                            subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Great-circle_distance
                                                            ! It takes lon, lats of two points on an assumed spherical earth and
                                                            ! calculates the distance between them along the great circle connecting the two points
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine haversine_formula(lon1,lat1,lon2,lat2,dist)
                                                            ! https://en.wikipedia.org/wiki/Haversine_formula
                                                            ! This is similar above but numerically better conditioned for small distances
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            !lon, lats of two points
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,dellat,a
                                                            ! degrees are converted to radians
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1 ! These dels simplify the haversine formula
                                                            dellat=latr2-latr1
                                                            ! The actual haversine formula
                                                            a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2
                                                            delangl=2*asin(sqrt(a)) !2*asin(sqrt(a))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Vincenty%27s_formulae
                                                            !It's a better approximation over previous two, since it considers earth to in oblate spheroid, which better approximates the shape of the earth
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,nom,denom
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.)
                                                            denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)
                                                            delangl=atan2(nom,denom)
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            end module





                                                            share|improve this answer





















                                                            • 1





                                                              This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • I edited my answer to add more details and format the code.

                                                              – srinivasu u
                                                              Nov 28 '18 at 6:24











                                                            • Awesome, thank you.

                                                              – Richard
                                                              Nov 28 '18 at 7:02
















                                                            0














                                                            Following is the module (coded in f90) containing three formulas discussed in the previous answers. You can either put this module at the top of your program
                                                            (before PROGRAM MAIN) or compile it separately and include the module directory during compilation. The following module contains three formulas. First two are great-circle distances based on the assumption that earth is spherical.



                                                            module spherical_dists

                                                            contains

                                                            subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Great-circle_distance
                                                            ! It takes lon, lats of two points on an assumed spherical earth and
                                                            ! calculates the distance between them along the great circle connecting the two points
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine haversine_formula(lon1,lat1,lon2,lat2,dist)
                                                            ! https://en.wikipedia.org/wiki/Haversine_formula
                                                            ! This is similar above but numerically better conditioned for small distances
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            !lon, lats of two points
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,dellat,a
                                                            ! degrees are converted to radians
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1 ! These dels simplify the haversine formula
                                                            dellat=latr2-latr1
                                                            ! The actual haversine formula
                                                            a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2
                                                            delangl=2*asin(sqrt(a)) !2*asin(sqrt(a))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Vincenty%27s_formulae
                                                            !It's a better approximation over previous two, since it considers earth to in oblate spheroid, which better approximates the shape of the earth
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,nom,denom
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.)
                                                            denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)
                                                            delangl=atan2(nom,denom)
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            end module





                                                            share|improve this answer





















                                                            • 1





                                                              This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • I edited my answer to add more details and format the code.

                                                              – srinivasu u
                                                              Nov 28 '18 at 6:24











                                                            • Awesome, thank you.

                                                              – Richard
                                                              Nov 28 '18 at 7:02














                                                            0












                                                            0








                                                            0







                                                            Following is the module (coded in f90) containing three formulas discussed in the previous answers. You can either put this module at the top of your program
                                                            (before PROGRAM MAIN) or compile it separately and include the module directory during compilation. The following module contains three formulas. First two are great-circle distances based on the assumption that earth is spherical.



                                                            module spherical_dists

                                                            contains

                                                            subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Great-circle_distance
                                                            ! It takes lon, lats of two points on an assumed spherical earth and
                                                            ! calculates the distance between them along the great circle connecting the two points
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine haversine_formula(lon1,lat1,lon2,lat2,dist)
                                                            ! https://en.wikipedia.org/wiki/Haversine_formula
                                                            ! This is similar above but numerically better conditioned for small distances
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            !lon, lats of two points
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,dellat,a
                                                            ! degrees are converted to radians
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1 ! These dels simplify the haversine formula
                                                            dellat=latr2-latr1
                                                            ! The actual haversine formula
                                                            a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2
                                                            delangl=2*asin(sqrt(a)) !2*asin(sqrt(a))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Vincenty%27s_formulae
                                                            !It's a better approximation over previous two, since it considers earth to in oblate spheroid, which better approximates the shape of the earth
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,nom,denom
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.)
                                                            denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)
                                                            delangl=atan2(nom,denom)
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            end module





                                                            share|improve this answer















                                                            Following is the module (coded in f90) containing three formulas discussed in the previous answers. You can either put this module at the top of your program
                                                            (before PROGRAM MAIN) or compile it separately and include the module directory during compilation. The following module contains three formulas. First two are great-circle distances based on the assumption that earth is spherical.



                                                            module spherical_dists

                                                            contains

                                                            subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Great-circle_distance
                                                            ! It takes lon, lats of two points on an assumed spherical earth and
                                                            ! calculates the distance between them along the great circle connecting the two points
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine haversine_formula(lon1,lat1,lon2,lat2,dist)
                                                            ! https://en.wikipedia.org/wiki/Haversine_formula
                                                            ! This is similar above but numerically better conditioned for small distances
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            !lon, lats of two points
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,dellat,a
                                                            ! degrees are converted to radians
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1 ! These dels simplify the haversine formula
                                                            dellat=latr2-latr1
                                                            ! The actual haversine formula
                                                            a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2
                                                            delangl=2*asin(sqrt(a)) !2*asin(sqrt(a))
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist)
                                                            !https://en.wikipedia.org/wiki/Vincenty%27s_formulae
                                                            !It's a better approximation over previous two, since it considers earth to in oblate spheroid, which better approximates the shape of the earth
                                                            implicit none
                                                            real,intent(in)::lon1,lon2,lat1,lat2
                                                            real,intent(out)::dist
                                                            real,parameter::pi=3.141592,mean_earth_radius=6371.0088
                                                            real::lonr1,lonr2,latr1,latr2
                                                            real::delangl,dellon,nom,denom
                                                            lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.)
                                                            latr1=lat1*(pi/180.);latr2=lat2*(pi/180.)
                                                            dellon=lonr2-lonr1
                                                            nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.)
                                                            denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)
                                                            delangl=atan2(nom,denom)
                                                            dist=delangl*mean_earth_radius
                                                            end subroutine

                                                            end module






                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited Nov 26 '18 at 8:12

























                                                            answered Jun 7 '17 at 9:26









                                                            srinivasu usrinivasu u

                                                            37849




                                                            37849








                                                            • 1





                                                              This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • I edited my answer to add more details and format the code.

                                                              – srinivasu u
                                                              Nov 28 '18 at 6:24











                                                            • Awesome, thank you.

                                                              – Richard
                                                              Nov 28 '18 at 7:02














                                                            • 1





                                                              This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • I edited my answer to add more details and format the code.

                                                              – srinivasu u
                                                              Nov 28 '18 at 6:24











                                                            • Awesome, thank you.

                                                              – Richard
                                                              Nov 28 '18 at 7:02








                                                            1




                                                            1





                                                            This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                            – Richard
                                                            Nov 25 '18 at 18:42





                                                            This code lacks formatting. More importantly, it lacks the comments necessary to explain what it does and what formula is being used.

                                                            – Richard
                                                            Nov 25 '18 at 18:42













                                                            I edited my answer to add more details and format the code.

                                                            – srinivasu u
                                                            Nov 28 '18 at 6:24





                                                            I edited my answer to add more details and format the code.

                                                            – srinivasu u
                                                            Nov 28 '18 at 6:24













                                                            Awesome, thank you.

                                                            – Richard
                                                            Nov 28 '18 at 7:02





                                                            Awesome, thank you.

                                                            – Richard
                                                            Nov 28 '18 at 7:02











                                                            0














                                                            On this page you can see the whole code and formulas how distances of locations are calculated in Android Location class



                                                            android/location/Location.java



                                                            EDIT: According the hint from @Richard I put the code of the linked function into my answer, to avoid invalidated link:



                                                            private static void computeDistanceAndBearing(double lat1, double lon1,
                                                            double lat2, double lon2, BearingDistanceCache results) {
                                                            // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
                                                            // using the "Inverse Formula" (section 4)
                                                            int MAXITERS = 20;
                                                            // Convert lat/long to radians
                                                            lat1 *= Math.PI / 180.0;
                                                            lat2 *= Math.PI / 180.0;
                                                            lon1 *= Math.PI / 180.0;
                                                            lon2 *= Math.PI / 180.0;
                                                            double a = 6378137.0; // WGS84 major axis
                                                            double b = 6356752.3142; // WGS84 semi-major axis
                                                            double f = (a - b) / a;
                                                            double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
                                                            double L = lon2 - lon1;
                                                            double A = 0.0;
                                                            double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
                                                            double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
                                                            double cosU1 = Math.cos(U1);
                                                            double cosU2 = Math.cos(U2);
                                                            double sinU1 = Math.sin(U1);
                                                            double sinU2 = Math.sin(U2);
                                                            double cosU1cosU2 = cosU1 * cosU2;
                                                            double sinU1sinU2 = sinU1 * sinU2;
                                                            double sigma = 0.0;
                                                            double deltaSigma = 0.0;
                                                            double cosSqAlpha = 0.0;
                                                            double cos2SM = 0.0;
                                                            double cosSigma = 0.0;
                                                            double sinSigma = 0.0;
                                                            double cosLambda = 0.0;
                                                            double sinLambda = 0.0;
                                                            double lambda = L; // initial guess
                                                            for (int iter = 0; iter < MAXITERS; iter++) {
                                                            double lambdaOrig = lambda;
                                                            cosLambda = Math.cos(lambda);
                                                            sinLambda = Math.sin(lambda);
                                                            double t1 = cosU2 * sinLambda;
                                                            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
                                                            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
                                                            sinSigma = Math.sqrt(sinSqSigma);
                                                            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
                                                            sigma = Math.atan2(sinSigma, cosSigma); // (16)
                                                            double sinAlpha = (sinSigma == 0) ? 0.0 :
                                                            cosU1cosU2 * sinLambda / sinSigma; // (17)
                                                            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
                                                            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                                                            cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
                                                            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
                                                            A = 1 + (uSquared / 16384.0) * // (3)
                                                            (4096.0 + uSquared *
                                                            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
                                                            double B = (uSquared / 1024.0) * // (4)
                                                            (256.0 + uSquared *
                                                            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
                                                            double C = (f / 16.0) *
                                                            cosSqAlpha *
                                                            (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
                                                            double cos2SMSq = cos2SM * cos2SM;
                                                            deltaSigma = B * sinSigma * // (6)
                                                            (cos2SM + (B / 4.0) *
                                                            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                                                            (B / 6.0) * cos2SM *
                                                            (-3.0 + 4.0 * sinSigma * sinSigma) *
                                                            (-3.0 + 4.0 * cos2SMSq)));
                                                            lambda = L +
                                                            (1.0 - C) * f * sinAlpha *
                                                            (sigma + C * sinSigma *
                                                            (cos2SM + C * cosSigma *
                                                            (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
                                                            double delta = (lambda - lambdaOrig) / lambda;
                                                            if (Math.abs(delta) < 1.0e-12) {
                                                            break;
                                                            }
                                                            }
                                                            float distance = (float) (b * A * (sigma - deltaSigma));
                                                            results.mDistance = distance;
                                                            float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                                                            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
                                                            initialBearing *= 180.0 / Math.PI;
                                                            results.mInitialBearing = initialBearing;
                                                            float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                                                            -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
                                                            finalBearing *= 180.0 / Math.PI;
                                                            results.mFinalBearing = finalBearing;
                                                            results.mLat1 = lat1;
                                                            results.mLat2 = lat2;
                                                            results.mLon1 = lon1;
                                                            results.mLon2 = lon2;
                                                            }





                                                            share|improve this answer


























                                                            • Link only answers can invalidate over time, and so are less useful.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • You are right @Richard I updated the link and added the linkt function code to my answer.

                                                              – Radon8472
                                                              Nov 28 '18 at 12:22











                                                            • Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                              – Richard
                                                              Nov 28 '18 at 17:28
















                                                            0














                                                            On this page you can see the whole code and formulas how distances of locations are calculated in Android Location class



                                                            android/location/Location.java



                                                            EDIT: According the hint from @Richard I put the code of the linked function into my answer, to avoid invalidated link:



                                                            private static void computeDistanceAndBearing(double lat1, double lon1,
                                                            double lat2, double lon2, BearingDistanceCache results) {
                                                            // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
                                                            // using the "Inverse Formula" (section 4)
                                                            int MAXITERS = 20;
                                                            // Convert lat/long to radians
                                                            lat1 *= Math.PI / 180.0;
                                                            lat2 *= Math.PI / 180.0;
                                                            lon1 *= Math.PI / 180.0;
                                                            lon2 *= Math.PI / 180.0;
                                                            double a = 6378137.0; // WGS84 major axis
                                                            double b = 6356752.3142; // WGS84 semi-major axis
                                                            double f = (a - b) / a;
                                                            double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
                                                            double L = lon2 - lon1;
                                                            double A = 0.0;
                                                            double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
                                                            double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
                                                            double cosU1 = Math.cos(U1);
                                                            double cosU2 = Math.cos(U2);
                                                            double sinU1 = Math.sin(U1);
                                                            double sinU2 = Math.sin(U2);
                                                            double cosU1cosU2 = cosU1 * cosU2;
                                                            double sinU1sinU2 = sinU1 * sinU2;
                                                            double sigma = 0.0;
                                                            double deltaSigma = 0.0;
                                                            double cosSqAlpha = 0.0;
                                                            double cos2SM = 0.0;
                                                            double cosSigma = 0.0;
                                                            double sinSigma = 0.0;
                                                            double cosLambda = 0.0;
                                                            double sinLambda = 0.0;
                                                            double lambda = L; // initial guess
                                                            for (int iter = 0; iter < MAXITERS; iter++) {
                                                            double lambdaOrig = lambda;
                                                            cosLambda = Math.cos(lambda);
                                                            sinLambda = Math.sin(lambda);
                                                            double t1 = cosU2 * sinLambda;
                                                            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
                                                            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
                                                            sinSigma = Math.sqrt(sinSqSigma);
                                                            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
                                                            sigma = Math.atan2(sinSigma, cosSigma); // (16)
                                                            double sinAlpha = (sinSigma == 0) ? 0.0 :
                                                            cosU1cosU2 * sinLambda / sinSigma; // (17)
                                                            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
                                                            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                                                            cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
                                                            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
                                                            A = 1 + (uSquared / 16384.0) * // (3)
                                                            (4096.0 + uSquared *
                                                            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
                                                            double B = (uSquared / 1024.0) * // (4)
                                                            (256.0 + uSquared *
                                                            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
                                                            double C = (f / 16.0) *
                                                            cosSqAlpha *
                                                            (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
                                                            double cos2SMSq = cos2SM * cos2SM;
                                                            deltaSigma = B * sinSigma * // (6)
                                                            (cos2SM + (B / 4.0) *
                                                            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                                                            (B / 6.0) * cos2SM *
                                                            (-3.0 + 4.0 * sinSigma * sinSigma) *
                                                            (-3.0 + 4.0 * cos2SMSq)));
                                                            lambda = L +
                                                            (1.0 - C) * f * sinAlpha *
                                                            (sigma + C * sinSigma *
                                                            (cos2SM + C * cosSigma *
                                                            (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
                                                            double delta = (lambda - lambdaOrig) / lambda;
                                                            if (Math.abs(delta) < 1.0e-12) {
                                                            break;
                                                            }
                                                            }
                                                            float distance = (float) (b * A * (sigma - deltaSigma));
                                                            results.mDistance = distance;
                                                            float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                                                            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
                                                            initialBearing *= 180.0 / Math.PI;
                                                            results.mInitialBearing = initialBearing;
                                                            float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                                                            -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
                                                            finalBearing *= 180.0 / Math.PI;
                                                            results.mFinalBearing = finalBearing;
                                                            results.mLat1 = lat1;
                                                            results.mLat2 = lat2;
                                                            results.mLon1 = lon1;
                                                            results.mLon2 = lon2;
                                                            }





                                                            share|improve this answer


























                                                            • Link only answers can invalidate over time, and so are less useful.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • You are right @Richard I updated the link and added the linkt function code to my answer.

                                                              – Radon8472
                                                              Nov 28 '18 at 12:22











                                                            • Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                              – Richard
                                                              Nov 28 '18 at 17:28














                                                            0












                                                            0








                                                            0







                                                            On this page you can see the whole code and formulas how distances of locations are calculated in Android Location class



                                                            android/location/Location.java



                                                            EDIT: According the hint from @Richard I put the code of the linked function into my answer, to avoid invalidated link:



                                                            private static void computeDistanceAndBearing(double lat1, double lon1,
                                                            double lat2, double lon2, BearingDistanceCache results) {
                                                            // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
                                                            // using the "Inverse Formula" (section 4)
                                                            int MAXITERS = 20;
                                                            // Convert lat/long to radians
                                                            lat1 *= Math.PI / 180.0;
                                                            lat2 *= Math.PI / 180.0;
                                                            lon1 *= Math.PI / 180.0;
                                                            lon2 *= Math.PI / 180.0;
                                                            double a = 6378137.0; // WGS84 major axis
                                                            double b = 6356752.3142; // WGS84 semi-major axis
                                                            double f = (a - b) / a;
                                                            double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
                                                            double L = lon2 - lon1;
                                                            double A = 0.0;
                                                            double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
                                                            double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
                                                            double cosU1 = Math.cos(U1);
                                                            double cosU2 = Math.cos(U2);
                                                            double sinU1 = Math.sin(U1);
                                                            double sinU2 = Math.sin(U2);
                                                            double cosU1cosU2 = cosU1 * cosU2;
                                                            double sinU1sinU2 = sinU1 * sinU2;
                                                            double sigma = 0.0;
                                                            double deltaSigma = 0.0;
                                                            double cosSqAlpha = 0.0;
                                                            double cos2SM = 0.0;
                                                            double cosSigma = 0.0;
                                                            double sinSigma = 0.0;
                                                            double cosLambda = 0.0;
                                                            double sinLambda = 0.0;
                                                            double lambda = L; // initial guess
                                                            for (int iter = 0; iter < MAXITERS; iter++) {
                                                            double lambdaOrig = lambda;
                                                            cosLambda = Math.cos(lambda);
                                                            sinLambda = Math.sin(lambda);
                                                            double t1 = cosU2 * sinLambda;
                                                            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
                                                            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
                                                            sinSigma = Math.sqrt(sinSqSigma);
                                                            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
                                                            sigma = Math.atan2(sinSigma, cosSigma); // (16)
                                                            double sinAlpha = (sinSigma == 0) ? 0.0 :
                                                            cosU1cosU2 * sinLambda / sinSigma; // (17)
                                                            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
                                                            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                                                            cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
                                                            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
                                                            A = 1 + (uSquared / 16384.0) * // (3)
                                                            (4096.0 + uSquared *
                                                            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
                                                            double B = (uSquared / 1024.0) * // (4)
                                                            (256.0 + uSquared *
                                                            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
                                                            double C = (f / 16.0) *
                                                            cosSqAlpha *
                                                            (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
                                                            double cos2SMSq = cos2SM * cos2SM;
                                                            deltaSigma = B * sinSigma * // (6)
                                                            (cos2SM + (B / 4.0) *
                                                            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                                                            (B / 6.0) * cos2SM *
                                                            (-3.0 + 4.0 * sinSigma * sinSigma) *
                                                            (-3.0 + 4.0 * cos2SMSq)));
                                                            lambda = L +
                                                            (1.0 - C) * f * sinAlpha *
                                                            (sigma + C * sinSigma *
                                                            (cos2SM + C * cosSigma *
                                                            (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
                                                            double delta = (lambda - lambdaOrig) / lambda;
                                                            if (Math.abs(delta) < 1.0e-12) {
                                                            break;
                                                            }
                                                            }
                                                            float distance = (float) (b * A * (sigma - deltaSigma));
                                                            results.mDistance = distance;
                                                            float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                                                            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
                                                            initialBearing *= 180.0 / Math.PI;
                                                            results.mInitialBearing = initialBearing;
                                                            float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                                                            -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
                                                            finalBearing *= 180.0 / Math.PI;
                                                            results.mFinalBearing = finalBearing;
                                                            results.mLat1 = lat1;
                                                            results.mLat2 = lat2;
                                                            results.mLon1 = lon1;
                                                            results.mLon2 = lon2;
                                                            }





                                                            share|improve this answer















                                                            On this page you can see the whole code and formulas how distances of locations are calculated in Android Location class



                                                            android/location/Location.java



                                                            EDIT: According the hint from @Richard I put the code of the linked function into my answer, to avoid invalidated link:



                                                            private static void computeDistanceAndBearing(double lat1, double lon1,
                                                            double lat2, double lon2, BearingDistanceCache results) {
                                                            // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
                                                            // using the "Inverse Formula" (section 4)
                                                            int MAXITERS = 20;
                                                            // Convert lat/long to radians
                                                            lat1 *= Math.PI / 180.0;
                                                            lat2 *= Math.PI / 180.0;
                                                            lon1 *= Math.PI / 180.0;
                                                            lon2 *= Math.PI / 180.0;
                                                            double a = 6378137.0; // WGS84 major axis
                                                            double b = 6356752.3142; // WGS84 semi-major axis
                                                            double f = (a - b) / a;
                                                            double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
                                                            double L = lon2 - lon1;
                                                            double A = 0.0;
                                                            double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
                                                            double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
                                                            double cosU1 = Math.cos(U1);
                                                            double cosU2 = Math.cos(U2);
                                                            double sinU1 = Math.sin(U1);
                                                            double sinU2 = Math.sin(U2);
                                                            double cosU1cosU2 = cosU1 * cosU2;
                                                            double sinU1sinU2 = sinU1 * sinU2;
                                                            double sigma = 0.0;
                                                            double deltaSigma = 0.0;
                                                            double cosSqAlpha = 0.0;
                                                            double cos2SM = 0.0;
                                                            double cosSigma = 0.0;
                                                            double sinSigma = 0.0;
                                                            double cosLambda = 0.0;
                                                            double sinLambda = 0.0;
                                                            double lambda = L; // initial guess
                                                            for (int iter = 0; iter < MAXITERS; iter++) {
                                                            double lambdaOrig = lambda;
                                                            cosLambda = Math.cos(lambda);
                                                            sinLambda = Math.sin(lambda);
                                                            double t1 = cosU2 * sinLambda;
                                                            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
                                                            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
                                                            sinSigma = Math.sqrt(sinSqSigma);
                                                            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
                                                            sigma = Math.atan2(sinSigma, cosSigma); // (16)
                                                            double sinAlpha = (sinSigma == 0) ? 0.0 :
                                                            cosU1cosU2 * sinLambda / sinSigma; // (17)
                                                            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
                                                            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                                                            cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
                                                            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
                                                            A = 1 + (uSquared / 16384.0) * // (3)
                                                            (4096.0 + uSquared *
                                                            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
                                                            double B = (uSquared / 1024.0) * // (4)
                                                            (256.0 + uSquared *
                                                            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
                                                            double C = (f / 16.0) *
                                                            cosSqAlpha *
                                                            (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
                                                            double cos2SMSq = cos2SM * cos2SM;
                                                            deltaSigma = B * sinSigma * // (6)
                                                            (cos2SM + (B / 4.0) *
                                                            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                                                            (B / 6.0) * cos2SM *
                                                            (-3.0 + 4.0 * sinSigma * sinSigma) *
                                                            (-3.0 + 4.0 * cos2SMSq)));
                                                            lambda = L +
                                                            (1.0 - C) * f * sinAlpha *
                                                            (sigma + C * sinSigma *
                                                            (cos2SM + C * cosSigma *
                                                            (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
                                                            double delta = (lambda - lambdaOrig) / lambda;
                                                            if (Math.abs(delta) < 1.0e-12) {
                                                            break;
                                                            }
                                                            }
                                                            float distance = (float) (b * A * (sigma - deltaSigma));
                                                            results.mDistance = distance;
                                                            float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                                                            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
                                                            initialBearing *= 180.0 / Math.PI;
                                                            results.mInitialBearing = initialBearing;
                                                            float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                                                            -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
                                                            finalBearing *= 180.0 / Math.PI;
                                                            results.mFinalBearing = finalBearing;
                                                            results.mLat1 = lat1;
                                                            results.mLat2 = lat2;
                                                            results.mLon1 = lon1;
                                                            results.mLon2 = lon2;
                                                            }






                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited Nov 28 '18 at 12:23

























                                                            answered Jul 3 '15 at 7:25









                                                            Radon8472Radon8472

                                                            1,4011524




                                                            1,4011524













                                                            • Link only answers can invalidate over time, and so are less useful.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • You are right @Richard I updated the link and added the linkt function code to my answer.

                                                              – Radon8472
                                                              Nov 28 '18 at 12:22











                                                            • Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                              – Richard
                                                              Nov 28 '18 at 17:28



















                                                            • Link only answers can invalidate over time, and so are less useful.

                                                              – Richard
                                                              Nov 25 '18 at 18:42











                                                            • You are right @Richard I updated the link and added the linkt function code to my answer.

                                                              – Radon8472
                                                              Nov 28 '18 at 12:22











                                                            • Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                              – Richard
                                                              Nov 28 '18 at 17:28

















                                                            Link only answers can invalidate over time, and so are less useful.

                                                            – Richard
                                                            Nov 25 '18 at 18:42





                                                            Link only answers can invalidate over time, and so are less useful.

                                                            – Richard
                                                            Nov 25 '18 at 18:42













                                                            You are right @Richard I updated the link and added the linkt function code to my answer.

                                                            – Radon8472
                                                            Nov 28 '18 at 12:22





                                                            You are right @Richard I updated the link and added the linkt function code to my answer.

                                                            – Radon8472
                                                            Nov 28 '18 at 12:22













                                                            Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                            – Richard
                                                            Nov 28 '18 at 17:28





                                                            Thanks! Putting a more complete citation to the document would be useful so folks can find it via other means.

                                                            – Richard
                                                            Nov 28 '18 at 17:28











                                                            -3














                                                            just use the distance formula Sqrt( (x2-x1)^2 + (y2-y1)^2 )






                                                            share|improve this answer





















                                                            • 1





                                                              Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                              – ToolmakerSteve
                                                              Nov 25 '18 at 12:55













                                                            • This is so very wrong.

                                                              – Richard
                                                              Nov 25 '18 at 18:43
















                                                            -3














                                                            just use the distance formula Sqrt( (x2-x1)^2 + (y2-y1)^2 )






                                                            share|improve this answer





















                                                            • 1





                                                              Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                              – ToolmakerSteve
                                                              Nov 25 '18 at 12:55













                                                            • This is so very wrong.

                                                              – Richard
                                                              Nov 25 '18 at 18:43














                                                            -3












                                                            -3








                                                            -3







                                                            just use the distance formula Sqrt( (x2-x1)^2 + (y2-y1)^2 )






                                                            share|improve this answer















                                                            just use the distance formula Sqrt( (x2-x1)^2 + (y2-y1)^2 )







                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited Jan 20 '15 at 8:15









                                                            Taher Khorshidi

                                                            4,20532448




                                                            4,20532448










                                                            answered Jan 8 '15 at 10:57









                                                            RNR123RNR123

                                                            286




                                                            286








                                                            • 1





                                                              Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                              – ToolmakerSteve
                                                              Nov 25 '18 at 12:55













                                                            • This is so very wrong.

                                                              – Richard
                                                              Nov 25 '18 at 18:43














                                                            • 1





                                                              Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                              – ToolmakerSteve
                                                              Nov 25 '18 at 12:55













                                                            • This is so very wrong.

                                                              – Richard
                                                              Nov 25 '18 at 18:43








                                                            1




                                                            1





                                                            Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                            – ToolmakerSteve
                                                            Nov 25 '18 at 12:55







                                                            Don't do this. It is only valid for small distances near the equator. Away from equator, its wrong even for small distances; at higher latitudes a change in longitude of 1 degree is only * cos(latitude) as large a distance as a change in latitude of 1 degree.

                                                            – ToolmakerSteve
                                                            Nov 25 '18 at 12:55















                                                            This is so very wrong.

                                                            – Richard
                                                            Nov 25 '18 at 18:43





                                                            This is so very wrong.

                                                            – Richard
                                                            Nov 25 '18 at 18:43





                                                            protected by Neil Lunn Jan 20 '15 at 8:11



                                                            Thank you for your interest in this question.
                                                            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                            Would you like to answer one of these unanswered questions instead?



                                                            Popular posts from this blog

                                                            Wiesbaden

                                                            Marschland

                                                            Dieringhausen