Algorithm for offsetting a latitude/longitude by some amount of meters

  • I'm looking for an algorithm which when given a latitude and longitude pair and a vector translation in meters in Cartesian coordinates (x,y) would give me a new coordinate. Sort of like a reverse Haversine. I could also work with a distance and a heading transformation, but this would probably be slower and not as accurate. Ideally, the algorithm should be fast as I'm working on an embedded system. Accuracy is not critical, within 10 meters would be good.

    So you'd be fine modeling the earth as a sphere?

    Yeah, that would be fine as I'm expecting <1km offsets.

  • whuber

    whuber Correct answer

    10 years ago

    If your displacements aren't too great (less than a few kilometers) and you're not right at the poles, use the quick and dirty estimate that 111,111 meters (111.111 km) in the y direction is 1 degree (of latitude) and 111,111 * cos(latitude) meters in the x direction is 1 degree (of longitude).

    I suppose this could work; what would the range be - within 10 degrees of the poles?

    @Thomas: Actually, you can be very close to the poles. I checked against a UTM calculation using equal x- and y-displacements of 1400 m (so the total displacement is 2 km). The results are good to 8.6 meters or better. The worst latitude (for this direction and amount of displacement) is 81 degrees: the approximation actually gets more accurate as you move north and its error stays below 10 meters until you get beyond 89.6 degrees!

    Incidentally, these magic numbers of 111,111 are easy to remember by knowing some history: the French originally *defined* the meter so that 10^7 meters would be the distance along the Paris meridian from the equator to the north pole. Thus, 10^7 / 90 = 111,111.1 meters equals one degree of latitude to within the capabilities of French surveyors two centuries ago.

    Thanks! Within 0.4 degrees is much better than I could have hoped for.

    So with the formula if I wanted to move +100m in the y direction from say 10.0 N, 10.0 E, would I just add 100 / 111111? If moving in the x direction +100m, would it be 100÷(111,111×(cos 10))? Just making sure I've got this right.

    @Thomas Yes, that's right. Note how the second formula *expands* the apparent x-displacement (by virtue of dividing by a number less than 1) as it should, because a degree of longitude gets smaller as you move towards the poles from the equator. The only potential hitch is to make sure you and your software platform agree on what "cos" means: it had better interpret cos(10) as the cosine of 10 *degrees*, not 10 radians! (If not, 10 degrees = 10 * pi / 180 radians illustrates the simple conversion.) At this point, the code offered by @haakon_d should make complete sense to you.

    Good point - must remember to convert to radians!

    Somebody attempted to edit this answer to replace "meters" by "km." They probably were reading the comma "," in the European sense of a decimal point. I follow the American convention (which I believe is the convention of international publications, too) of using a comma to separate long digit strings into groups of three and a decimal point "." instead of the comma. (This usage is clearly shown in previous comments.) To avoid any ambiguity I have edited the answer to show clearly what the comma and point mean.

    Somebody else attempted to edit this answer to replace the cosine of the latitude by the cosine of the longitude. That's definitely wrong; I rolled back the edit.

    @whuber -- that's an interesting story for sure but I'm not sure that numbers get much _"easier to remember"_ than 111111... (but maybe things were different "back in 2010". :-) +

    @whuber A million years later, but just figured I would point out that the 'safe' option which everybody tends to understand is using spaces to indicate the thousand separator. 111 111 meters or 111 111,111 meters or 111 111.111 meters will be understood by virtually everyone without difficulty.

    Note: In Java, cos() takes radians by default. You can use Math.toRadians to convert.

License under CC-BY-SA with attribution

Content dated before 6/26/2020 9:53 AM