178

If I have a latitude or longitude reading in standard NMEA format is there an easy way / formula to convert that reading to meters, which I can then implement in Java (J9)?

Edit: Ok seems what I want to do is not possible easily, however what I really want to do is:

Say I have a lat and long of a way point and a lat and long of a user is there an easy way to compare them to decide when to tell the user they are within a reasonably close distance of the way point? I realise reasonable is subject but is this easily do-able or still overly maths-y?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Adam Taylor
  • 7,534
  • 8
  • 44
  • 54
  • 2
    Do you mean to UTM? http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system – Adrian Archer Mar 12 '09 at 17:41
  • 1
    What do you mean by converting a lat/long to meters? meters from where? Are you looking for a way to compute the distance along the surface of the earth from one coordinate to another? – Baltimark Mar 12 '09 at 17:43
  • These seems like a copy of this question http://stackoverflow.com/questions/176137/java-convert-lat-lon-to-utm – Adrian Archer Mar 12 '09 at 17:45
  • Ok I think I maybe asked the wrong question.. I've updated it. – Adam Taylor Mar 12 '09 at 17:56
  • 2
    I stumbled upon this question wanting to do SQL queries on latitude and longitude and found [this great article](http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates) with some Java code at the bottom. It might interest you as well. – Kristof Van Landschoot Mar 01 '12 at 11:20
  • You may find this document helpful: [http://www.johndcook.com/lat_long_details.html](http://www.johndcook.com/lat_long_details.html) – John D. Cook Mar 12 '09 at 17:41
  • possible duplicate of [Simple calculations for working with lat/lon + km distance?](http://stackoverflow.com/questions/1253499/simple-calculations-for-working-with-lat-lon-km-distance) – jb. Aug 22 '13 at 08:29
  • 1
    possible duplicate of [How do I calculate distance between two latitude-longitude points?](http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points) – Teepeemm Apr 23 '15 at 19:20
  • 1
    Most of the answers here are using simple spherical trigonometry, so the results are rather crude compared to the WGS84 ellipsoid distances used in the GPS system. Some of the answers refer to Vincenty's formula for ellipsoids, but that algorithm was designed for use on 1960s' era desk calculators and it has stability & accuracy issues; we have better hardware and software now. Please see [GeographicLib](https://geographiclib.sourceforge.io/) for a high quality library with implementations in various languages. (I'm not sure what GDAL uses for its WGS84 work, I _think_ it still uses Vincenty). – PM 2Ring Aug 03 '18 at 13:36

19 Answers19

234

Here is a javascript function:

function measure(lat1, lon1, lat2, lon2){  // generally used geo measurement function
    var R = 6378.137; // Radius of earth in KM
    var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
    var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d * 1000; // meters
}

Explanation: https://en.wikipedia.org/wiki/Haversine_formula

The haversine formula determines the great-circle distance between two points on a sphere given their longitudes and latitudes.

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
b-h-
  • 2,651
  • 1
  • 18
  • 9
  • 3
    For those looking for a library to convert between wgs and utm: https://github.com/urbanetic/utm-converter – Aram Kocharyan Dec 20 '14 at 15:05
  • 5
    Would be really grateful if somebody could add in some explanatory comments on the above code. Thanks in advance! – Ravindranath Akila Sep 28 '16 at 03:47
  • Found [this](https://www.html5rocks.com/en/tutorials/geolocation/trip_meter/#toc-step6) which this comment seem to be an adoption of. The link also says its based on [this article](http://www.movable-type.co.uk/scripts/latlong.html) on distance calculation. So any unanswered questions should be found in the original link. :) – Joachim Mar 25 '17 at 18:19
  • 1
    How do I add elevation into this calculation? – dangalg Aug 02 '20 at 12:40
  • 1
    @dangalg, assuming lower distances where the floor is plane, you have also altitudes `alt1` and `alt2`, and `dm` is the distance in meters (the result of `measure` function above). You can use the hypothenuse function of JS `Math.hypot(x, y)`, where `x` is `dm` and `y` is `max(alt1, alt2) - min(alt1, alt2)`. – Marco Aurélio da Silva Sep 15 '20 at 12:23
113

Given you're looking for a simple formula, this is probably the simplest way to do it, assuming that the Earth is a sphere with a circumference of 40075 km.

Length in km of 1° of latitude = always 111.32 km

Length in km of 1° of longitude = 40075 km * cos( latitude ) / 360

Ben
  • 1,548
  • 1
  • 11
  • 12
  • 2
    How does the longitude equation work? with a latitude of 90 degrees you'd expect it to show near 111km; but instead it shows 0; similarly, values close to it are also near 0. – Reece Jun 14 '17 at 14:36
  • 15
    Latitude is 0° at the equator and 90° at the pole (and not the opposite). For equator the formula gives 40075 km * cos(0°) / 360 = 111 km. For pole the formula gives 40075 * cos(90°) / 360 = 0 km. – Ben Jun 15 '17 at 12:34
  • 1
    I think this approach is simple especially as the question didn't ask for the exact distance between two points, but rather if they are "reasonably close enough".With these formulas we easily check if the user is within a square centered on the waypoint. It's much simpler to check for a square than for a circle. – Ben Apr 14 '20 at 14:44
  • 1
    this is far faster than using haversine if u're making an approx, works great thanks – Richard Jul 18 '22 at 22:36
  • Nope. If on the left side of the equation you have Km, you will have Km also on the right side, not meters – SeF Jul 20 '22 at 16:02
  • It's now corrected, the result is in km. – Ben Jul 21 '22 at 14:04
38

For approximating short distances between two coordinates I used formulas from http://en.wikipedia.org/wiki/Lat-lon:

m_per_deg_lat = 111132.954 - 559.822 * cos( 2 * latMid ) + 1.175 * cos( 4 * latMid);
m_per_deg_lon = 111132.954 * cos ( latMid );

.

In the code below I've left the raw numbers to show their relation to the formula from wikipedia.

double latMid, m_per_deg_lat, m_per_deg_lon, deltaLat, deltaLon,dist_m;

latMid = (Lat1+Lat2 )/2.0;  // or just use Lat1 for slightly less accurate estimate


m_per_deg_lat = 111132.954 - 559.822 * cos( 2.0 * latMid ) + 1.175 * cos( 4.0 * latMid);
m_per_deg_lon = (3.14159265359/180 ) * 6367449 * cos ( latMid );

deltaLat = fabs(Lat1 - Lat2);
deltaLon = fabs(Lon1 - Lon2);

dist_m = sqrt (  pow( deltaLat * m_per_deg_lat,2) + pow( deltaLon * m_per_deg_lon , 2) );

The wikipedia entry states that the distance calcs are within 0.6m for 100km longitudinally and 1cm for 100km latitudinally but I have not verified this as anywhere near that accuracy is fine for my use.

JJones
  • 802
  • 7
  • 7
  • 3
    Note that in 2017 the Wikipedia page has another (seems refined) formula. – Gorka Llona Feb 25 '17 at 22:29
  • 3
    Yes, the formula in Wikipedia is slightly different, but it seem that the [other Wikipedia](https://en.wikipedia.org/wiki/Geographic_coordinate_system#Expressing_latitude_and_longitude_as_linear_units) formula is based on the similar results from this [great SO answer](https://gis.stackexchange.com/a/75535/46435), where someone actually went through the calculations. – not2qubit Jan 26 '18 at 09:00
  • 1
    Keep in mind that in this equation "latMid" is in radians while "m_per_deg_lat" is for degrees. So if you want to compute this for a latitude of 30N (say), in the equation `latMid = pi*30/180`. – Eli Holmes Nov 16 '20 at 18:43
  • I think you have a typo for this: m_per_deg_lon because inputs might need to be lon and not lat. – EngrStudent Nov 20 '20 at 17:15
  • 1
    @EngrStudent No, he is right, the transformation factor for longitude depends on the latitude, since the distance between meridians gets smaller until they meet at the poles, so the m_per_long_degree gets smaller too – André Mar 19 '22 at 20:12
9

Here is the R version of b-h-'s function, just in case:

measure <- function(lon1,lat1,lon2,lat2) {
    R <- 6378.137                                # radius of earth in Km
    dLat <- (lat2-lat1)*pi/180
    dLon <- (lon2-lon1)*pi/180
    a <- sin((dLat/2))^2 + cos(lat1*pi/180)*cos(lat2*pi/180)*(sin(dLon/2))^2
    c <- 2 * atan2(sqrt(a), sqrt(1-a))
    d <- R * c
    return (d * 1000)                            # distance in meters
}
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Rodrigo
  • 4,706
  • 6
  • 51
  • 94
8

The earth is an annoyingly irregular surface, so there is no simple formula to do this exactly. You have to live with an approximate model of the earth, and project your coordinates onto it. The model I typically see used for this is WGS 84. This is what GPS devices usually use to solve the exact same problem.

NOAA has some software you can download to help with this on their website.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
7

There are many tools that will make this easy. See monjardin's answer for more details about what's involved.

However, doing this isn't necessarily difficult. It sounds like you're using Java, so I would recommend looking into something like GDAL. It provides java wrappers for their routines, and they have all the tools required to convert from Lat/Lon (geographic coordinates) to UTM (projected coordinate system) or some other reasonable map projection.

UTM is nice, because it's meters, so easy to work with. However, you will need to get the appropriate UTM zone for it to do a good job. There are some simple codes available via googling to find an appropriate zone for a lat/long pair.

Community
  • 1
  • 1
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
3

There are quite a few ways to calculate this. All of them use aproximations of spherical trigonometry where the radius is the one of the earth.

try http://www.movable-type.co.uk/scripts/latlong.html for a bit of methods and code in different languages.

rcaval
  • 762
  • 5
  • 12
2

One nautical mile (1852 meters) is defined as one arcminute of longitude at the equator. However, you need to define a map projection (see also UTM) in which you are working for the conversion to really make sense.

Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
  • 1
    No, the nautical mile is defined by international standard (*v* http://en.wikipedia.org/wiki/Nautical_mile) to be 1852m. Its relationship to the measurement of an arc on the surface of a spheroid such as the Earth is now both historical and approximate. – High Performance Mark Aug 28 '13 at 14:51
1

To convert latitude and longitude in x and y representation you need to decide what type of map projection to use. As for me, Elliptical Mercator seems very well. Here you can find an implementation (in Java too).

Megamozg
  • 975
  • 9
  • 15
1
    'below is from
'http://www.zipcodeworld.com/samples/distance.vbnet.html
Public Function distance(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim theta As Double = lon1 - lon2
    Dim dist As Double = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + _
                            Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * _
                            Math.Cos(deg2rad(theta))
    dist = Math.Acos(dist)
    dist = rad2deg(dist)
    dist = dist * 60 * 1.1515
    If unit = "K" Then
        dist = dist * 1.609344
    ElseIf unit = "N" Then
        dist = dist * 0.8684
    End If
    Return dist
End Function
Public Function Haversine(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim R As Double = 6371 'earth radius in km
    Dim dLat As Double
    Dim dLon As Double
    Dim a As Double
    Dim c As Double
    Dim d As Double
    dLat = deg2rad(lat2 - lat1)
    dLon = deg2rad((lon2 - lon1))
    a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(deg2rad(lat1)) * _
            Math.Cos(deg2rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
    c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))
    d = R * c
    Select Case unit.ToString.ToUpper
        Case "M"c
            d = d * 0.62137119
        Case "N"c
            d = d * 0.5399568
    End Select
    Return d
End Function
Private Function deg2rad(ByVal deg As Double) As Double
    Return (deg * Math.PI / 180.0)
End Function
Private Function rad2deg(ByVal rad As Double) As Double
    Return rad / Math.PI * 180.0
End Function
dbasnett
  • 11,334
  • 2
  • 25
  • 33
1

Here is a MySQL function:

SET @radius_of_earth = 6378.137; -- In kilometers

DROP FUNCTION IF EXISTS Measure;
DELIMITER //
CREATE FUNCTION Measure (lat1 REAL, lon1 REAL, lat2 REAL, lon2 REAL) RETURNS REAL
BEGIN
-- Multiply by 1000 to convert millimeters to meters
RETURN 2 * @radius_of_earth * 1000 * ASIN(SQRT(
    POW(SIN((lat2 - lat1) / 2 * PI() / 180), 2) +
    COS(lat1 * PI() / 180) *
    COS(lat2 * PI() / 180) *
    POW(SIN((lon2 - lon1) / 2 * PI() / 180), 2)
));
END; //
DELIMITER ;
Blaze
  • 813
  • 2
  • 8
  • 13
1

Original poster asked "If I have a latitude or longitude reading in standard NMEA format is there an easy way / formula to convert that reading to meters"

I haven't used Java in a while so I did the solution here in "PARI". Just plug your point's latitude and longitudes into the equations below to get the exact arc lengths and scales in meters per (second of Longitude) and meters per (second of Latitude). I wrote these equations for the free-open-source-mac-pc math program "PARI". You can just paste the following into it and the I will show how to apply them to two made up points:

\\=======Arc lengths along Latitude and Longitude and the respective scales:
\p300
default(format,"g.42")
dms(u)=[truncate(u),truncate((u-truncate(u))*60),((u-truncate(u))*60-truncate((u-truncate(u))*60))*60];
SpinEarthRadiansPerSec=7.292115e-5;\
GMearth=3986005e8;\
J2earth=108263e-8;\
re=6378137;\
ecc=solve(ecc=.0001,.9999,eccp=ecc/sqrt(1-ecc^2);qecc=(1+3/eccp^2)*atan(eccp)-3/eccp;ecc^2-(3*J2earth+4/15*SpinEarthRadiansPerSec^2*re^3/GMearth*ecc^3/qecc));\
e2=ecc^2;\
b2=1-e2;\
b=sqrt(b2);\
fl=1-b;\
rfl=1/fl;\
U0=GMearth/ecc/re*atan(eccp)+1/3*SpinEarthRadiansPerSec^2*re^2;\
HeightAboveEllipsoid=0;\
reh=re+HeightAboveEllipsoid;\
longscale(lat)=reh*Pi/648000/sqrt(1+b2*(tan(lat))^2);
latscale(lat)=reh*b*Pi/648000/(1-e2*(sin(lat))^2)^(3/2);
longarc(lat,long1,long2)=longscale(lat)*648000/Pi*(long2-long1);
latarc(lat1,lat2)=(intnum(th=lat1,lat2,sqrt(1-e2*(sin(th))^2))+e2/2*sin(2*lat1)/sqrt(1-e2*(sin(lat1))^2)-e2/2*sin(2*lat2)/sqrt(1-e2*(sin(lat2))^2))*reh;
\\=======

To apply that to your type of problem I will make up that one of your data points was at

[Latitude, Longitude]=[+30, 30]

and the other at

[Latitude, Longitude]=[+30:00:16.237796,30:00:18.655502].

To convert those points to meters in two coordinates:

I can setup a system of coordinates in meters with the first point being at the origin: [0,0] meters. Then I can define the coordinate x-axis as due East-West, and the y-axis as due North-South.

Then the second point's coordinates are:

? [longarc(30*Pi/180,30*Pi/180,((18.655502/60+0)/60+30)*Pi/180),latarc(30*Pi/180,((16.237796/60+0)/60+30)*Pi/180)]
%9 = [499.999998389040060103621525561027349597207, 499.999990137812119668486524932382720606325]

Warning on precision: Note however: Since the surface of the Earth is curved, 2-dimensional coordinates obtained on it can't follow the same rules as cartesian coordinates such as the Pythagorean Theorem perfectly. Also lines pointing due North-South converge in the Northern Hemisphere. At the North Pole it becomes obvious that North-South lines won't serve well for lines parallel to the y-axis on a map.

At 30 degrees Latitude with 500 meter lengths, the x-coordinate changes by 1.0228 inches if the scale is set from [0,+500] instead of [0,0]:

? [longarc(((18.655502/60+0)/60+30)*Pi/180,30*Pi/180,((18.655502/60+0)/60+30)*Pi/180),latarc(30*Pi/180,((16.237796/60+0)/60+30)*Pi/180)]
%10 = [499.974018595036400823218815901067566617826, 499.999990137812119668486524932382720606325]
? (%10[1]-%9[1])*1000/25.4
%12 = -1.02282653557713702372872677007019603860352
? 

The error there of 500meters/1inch is only about 1/20000, good enough for most diagrams, but one might want to reduce the 1 inch error. For a completely general way to convert lat,long to orthogonal x,y coordinates for any point on the globe, I would chose to abandon aligning coordinate lines with East-West and North-South, except still keeping the center y-axis pointing due North. For example you could rotate the globe around the poles (around the 3-D Z-axis)
so the center point in your map is at longitude zero. Then tilt the globe (around the 3-D y-axis) to bring your center point to lat,long = [0,0]. On the globe points at lat,long = [0,0] are farthest from the poles and have a lat,long grid around them that is most orthogonal so you can use these new "North-South", "East-West" lines as coordinate x,y lines without incurring the stretching that would have occurred doing that before rotating the center point away from the pole. Showing an explicit example of that would take a lot more space.

1

Why limiting to one degree?

The formula is based on the proportion:

distance[m] : distance[deg] = max circumference[m] : 360[deg]

Lets say you are given an angle for a latitude and one for longitude both in degrees: (longitude[deg], latitude[deg])

For the latitude, the max circumference is always the one passing for the poles. In a spherical model, with radius R (in meters) the max circumference is 2 * pi * R and the proportions resolves to:

latitude[m] = ( 2 * pi * R[m] * latitude[deg] ) / 360[deg]

(note that deg and deg simplifies, and what remains is meters on both sides).

For the longitude the max circumference is proportional to the cosine of the latitude (as you can imagine running in circle the north pole is shorter than running in circle around the equator), so it is 2 * pi * R * cos(latitude[rad]). Therefore

longitude distance[m] = ( 2 * pi * R[m] * cos(latitude[rad]) * longitude[deg] ) / 360[deg]

Note that you will have to convert the latitude from deg to rad before computing the cos.


Omitting details for who is just looking for the formula:

lat_in_m = 111132.954 * lat_in_degree / 360
lon_in_m = 111132.954 * cos(lat_in_radians) * lon_in_deg ) / 360
SeF
  • 3,864
  • 2
  • 28
  • 41
0

If its sufficiently close you can get away with treating them as coordinates on a flat plane. This works on say, street or city level if perfect accuracy isnt required and all you need is a rough guess on the distance involved to compare with an arbitrary limit.

  • 3
    No, that does not work! The x distance in m is different for different values of latitude. At the equator you might get away with it, but the closer you get to the poles the extremer your ellipsoids will get. – RickyA Nov 29 '12 at 11:27
  • 3
    While your comment is reasonable, it doesn't answer the user's question about converting the lat/lng degree difference to meters. – JivanAmara Sep 19 '13 at 04:37
0

Here is a version in Swift:

func toDegreeAt(point: CLLocationCoordinate2D) -> CLLocationDegrees {
    let latitude = point.latitude  
    let earthRadiusInMetersAtSeaLevel = 6378137.0
    let earthRadiusInMetersAtPole = 6356752.314
    
    let r1 = earthRadiusInMetersAtSeaLevel
    let r2 = earthRadiusInMetersAtPole
    let beta = latitude

    let earthRadiuseAtGivenLatitude = (
      ( pow(pow(r1, 2) * cos(beta), 2) + pow(pow(r2, 2) * sin(beta), 2) ) /
      ( pow(r1 * cos(beta), 2) + pow(r2 * sin(beta), 2) )
    )
    .squareRoot()
      
    let metersInOneDegree = (2 * Double.pi * earthRadiuseAtGivenLatitude * 1.0) / 360.0
    let value: CLLocationDegrees = self / metersInOneDegree
    return value
  }
hbk
  • 10,908
  • 11
  • 91
  • 124
0

To directly convert the distance between two latitudes/longitudes to the x y meters between them, you could use the Earth Radius equations from Wikipedia. In C, these are:

N = a/sqrt(1-e2)*(sin(Lat1)*sin(Lat1))));
latlen = ((1-e2)/(a*a))*N*N*N*(Lat1-Lat2)*PI/180;
lonlen = (N*cos(Lat1))*(Lon1-Lon2)*PI/180;

Where a is the radius of the Earth at the equator and e2 is the Earth's eccentricity squared. The equations get the radii between the two points and PI/180 gets the circumferences of those radii.

-1

Based on average distance for degress in the Earth.

1° = 111km;

Converting this for radians and dividing for meters, take's a magic number for the RAD, in meters: 0.000008998719243599958;

then:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
Jaykon
  • 127
  • 1
  • 2
  • 3
    finally, a straightforward answer :) – Ben Hutchison Nov 14 '13 at 06:24
  • what if latitude is -179 and the other is 179, the x distance should be 2 degrees instead of 358 – OMGPOP Mar 15 '14 at 13:19
  • 7
    Do not use this answer (for some reason, it's upvoted). There is not a single scaling between longitude and distance; the Earth is not flat. – CPBL Apr 11 '15 at 23:36
  • 1
    I believe it is 111.1 – Abel Callejo Jan 07 '16 at 07:31
  • 7
    Note that one degree of longitude is 111 km at the equator, but less for other latitudes. There's a simple approximative formula to find the length in km of 1° of longitude in function of latitude : 1° of longitude = 40000 km * cos (latitude) / 360 (and of course it gives 111 km for latitude = 90°). Also remark that 1° of longitude is almost always a different distance than 1° of latitude. – Ben Sep 16 '16 at 21:13
-1

If you want a simple solution then use the Haversine formula as outlined by the other comments. If you have an accuracy sensitive application keep in mind the Haversine formula does not guarantee an accuracy better then 0.5% as it is assuming the earth is a sphere. To consider that Earth is a oblate spheroid consider using Vincenty's formulae. Additionally, I'm not sure what radius we should use with the Haversine formula: {Equator: 6,378.137 km, Polar: 6,356.752 km, Volumetric: 6,371.0088 km}.

  • 1
    `it is assuming the earth is a circle` ^^ Some strange people do this nowadays ... but what you mean is probably rather `it is assuming the earth is a sphere` ;) – derHugo Mar 02 '20 at 11:24
-2

You need to convert the coordinates to radians to do the spherical geometry. Once converted, then you can calculate a distance between the two points. The distance then can be converted to any measure you want.