Homewrecker
Homewrecker

Reputation: 1106

Add exact distance to GPS coordinates

I want to be able to add an exact distance to some GPS coordinates. I have a longitude and a latitude and I want to add a distance, let's say 30 meters.

I found below formula but when I test it, it does not seem to be that accurate because the resulting long and lat are 37m away from the beginning coords.

public static Coordinates addDistanceToCoordinates(String lat, String lon, double distance) {
    Double latitude = Double.valueOf(lat);
    Double longitude = Double.valueOf(lon);

    double lat0 = cos(Math.PI / 180.0 * latitude);

    double x = longitude + (180/Math.PI)*(distance/6378137)/cos(lat0);
    double y = latitude + (180/Math.PI)*(distance/6378137);

    return Coordinates.builder().lon(x).lat(y).build();
}

Upvotes: 3

Views: 4241

Answers (2)

payloc91
payloc91

Reputation: 3809

If you have a center (x,y) and you move on the x axis by 30 meters and on the y axis by another 30 meters your distance from the center won't be 30.

It will be Math.sqrt( Math.pow(x, 2) + Math.pow(y, 2) );.

Specifically, there are an infinite number of points that are 30 meters distant from the center (or your initial coordinates).

If you want to move in only one direction, then you can simply add/subtract 30 meters in either of your axis.

As you already did:

double x = longitude + (180/Math.PI)*(distance/6378137)/cos(lat0);

or

double y = latitude + (180/Math.PI)*(distance/6378137);

but not both...


You are still better off by using angles in your calculations, which will turn handy when you move on both axis.

By knowing which direction you are headed to, for example 50° from the x axis,

double a = Math.toRadians(50);  // degrees

double x = longitude + (180/Math.PI) * (30 / 6378137)/cos(lat0) * Math.cos(a);
double y = latitude + (180/Math.PI) * (30 / 6378137) * Math.sin(a);

Coming back to your question, if you want to move on the x axis and the y axis by the same distance and end up exactly 30 meters away from the center, then your angle will be double a = Math.toRadians(45); (if you head North-East) *

In fact you will obtain for both (30 / 6378137) * Math.cos(a) and (30 / 6378137) * Math.sin(a) a result of x1 = y1 = 3.325924707417923e-06.

If you then apply Pythagoras

double finalDistance = Math.sqrt(Math.pow(x1, 2) + Math.pow(y1, 2)) * 6378137; 

you will find finalDistance to be 30 meters from your initial coordinates.


* The correct calculation would be Math.toRadians(45 * (2 * n - 1)); | where n = [1, 2, 3, 4]

Upvotes: 6

Ralf Kleberhoff
Ralf Kleberhoff

Reputation: 7290

Your code adds 30 meters north and 30 meters east, resulting in 42.4 meters northeast.

The calculation is assuming earth as a sphere instead of an ellipsoid, but that's mostly OK, can make a difference of max. 0.2 percent. It uses the biggest earth diameter (equator - equator) instead of some mean value, which will result in points too close to the starting point most of the time, but agian, taht can give an error of maybe 0.2 percent.

The calculation assumes the lat/lon grid to be rectangular, which is OK as long as the distances are short and you stay away from north or south pole.

So, all of this doesn't explain the 20 percent error you are reporting. The problem must be outside of the code you showed us.

The most suspicious remaining aspect is the string conversion. You'll need at least 5 decimal places for lat / lon degree values to get a 1 meter resolution.

Or maybe the tool that told you about the 37 meters isn't correct or somehow incompatible with the data...

Upvotes: 1

Related Questions