Calculating new longitude, latitude from old + n meters
Asked Answered
B

13

156

I want to create 2 new longitude and 2 new latitudes based on a coordinate and a distance in meters, I want to create a nice bounding box around a certain point. It is for a part of a city and max ±1500 meters. I therefore don't think the curvature of earth has to be taken into account.

So I have 50.0452345 (x) and 4.3242234 (y) and I want to know x + 500 meters, x - 500 meters, y - 500 meters, y + 500 meters

I found many algorithms but almost all seem to deal with the distance between points.

Berndt answered 19/9, 2011 at 20:35 Comment(1)
gis.stackexchange.com/questions/25877/…Paction
A
183

The number of kilometers per degree of longitude is approximately

(pi/180) * r_earth * cos(theta*pi/180)

where theta is the latitude in degrees and r_earth is approximately 6378 km.

The number of kilometers per degree of latitude is approximately the same at all locations, approx

(pi/180) * r_earth = 111 km / degree 

So you can do:

new_latitude  = latitude  + (dy / r_earth) * (180 / pi);
new_longitude = longitude + (dx / r_earth) * (180 / pi) / cos(latitude * pi/180);

As long as dx and dy are small compared to the radius of the earth and you don't get too close to the poles.

Airlift answered 20/9, 2011 at 0:25 Comment(10)
to convert from degree to radians you multiply with py and divide by 180. But you write cos(latitude*180/pi)Custard
@josch: Good catch. Try to correct the answer the answer next time instead of simply proposing a correction. Many people simply copy and paste code from StackOverflow thinking it is correct and ready to use.Sauveur
Why is latitude used in the expression for new_longitude?Ongoing
@Ongoing I suppose it's for taking into account the distance from the EquatorTriparted
ok, what will be the direction? I mean if I want to add 50 meters, where it will be added? Right, left, up or down?Eliciaelicit
shouldn't r_earth be 6371 km approximately? google.it/…*Laudation
The earth is not perfectly spherical, so using a single value for "radius" is an approximation. Wikipedia says "distances from points on the surface to the center range from 6,353 km to 6,384 km". It also says "Several different ways of modeling the Earth as a sphere each yield a mean radius of 6,371 km" which indicates your value. Really, if this correction is significant in your application, you should be using a better algorithm anyway.Airlift
For anyone who isn't sure the r_earth variable should be in meters and should be equal to approximately 6371000.0Balkanize
to calculate the new_longitude instead of latitude the new latitude should be used:new_longitude = longitude + (dx / r_earth) * (180 / pi) / cos(NEW_LATITUDE * pi/180);Genniegennifer
What is needed for the radius is a mean value for the radius at sea level + the lat/long's elevation.Zygapophysis
O
47

The accepted answer is perfectly right and works. I made some tweaks and turned into this:

double meters = 50;

// number of km per degree = ~111km (111.32 in google maps, but range varies
// between 110.567km at the equator and 111.699km at the poles)
//
// 111.32km = 111320.0m (".0" is used to make sure the result of division is
// double even if the "meters" variable can't be explicitly declared as double)
double coef = meters / 111320.0;

double new_lat = my_lat + coef;

// pi / 180 ~= 0.01745
double new_long = my_long + coef / Math.cos(my_lat * 0.01745);

Hope this helps too.

Ostosis answered 7/11, 2016 at 18:7 Comment(14)
0.0000089? Try to avoid magic numbers, nobody will understand this.Ultimately
It is a short version of earth diameter and pi numbers in the code. not magic.Ostosis
It is still magic if nobody knows how to reproduce this number. Why don't you put the full calculation into your code?Ultimately
1 degree in google map is equal to 111.32 Kilometer. 1Degree = 111.32KM. 1KM in Degree = 1 / 111.32 = 0.008983. 1M in Degree = 0.000008983.Lientery
You should have made a comment in your answer, putting it in the comments is not helpful.Jesus
@MuhammadAzeem your formula is not accurate. How many meters are represented within a degree changes depending on coordinate location and also depending on if it's a latitudinal degree or a longitudinal degree.Kelda
Other than putting the 0.0000089 in to a variable and naming it I think that is better than have a complete formula, as it will execute quicker than math logic for each calculation they doing. And if people want to know the maths then they would be googling that, not how to convert gps values.Antihistamine
@Muhammad Azeem I have the same problem using this formula i can get one new lat and one new long in one direction, how to get the another direction ?Marcheshvan
@Marcheshvan have you find a solution?Shag
@Marcheshvan it just works also with negative meters meters = Math.round((Math.random() - 0.5) * meters)Wright
how can we get direction of new latitude if it is toward east, west, north , west ?Symbolic
It is hidden information in the + and - signs. You must figure it out :)Ostosis
Eliminate magic numbers like this: const <type> <descriptive_name> = <value>; Don't rely on comments, those are not propagated into the code and you will have at least two copies of the <value>, which can get out of sync.Zygapophysis
In this calc double new_long = my_long + coef / Math.cos(my_lat * 0.01745); shouldn't this part Math.cos(my_lat * 0.01745) be Math.cos(new_lat * 0.01745)? It seems like the new_long would be influenced by the new_lat not the original lat. I see a similar comment on the accepted answer but it only has 3 votes and the accepted answer hasn't been updated to incorporate the comment. So I'm left unsure. Thoughts?Schedule
C
41

For latitude do:

var earth = 6378.137,  //radius of the earth in kilometer
    pi = Math.PI,
    m = (1 / ((2 * pi / 360) * earth)) / 1000;  //1 meter in degree

var new_latitude = latitude + (your_meters * m);

For longitude do:

var earth = 6378.137,  //radius of the earth in kilometer
    pi = Math.PI,
    cos = Math.cos,
    m = (1 / ((2 * pi / 360) * earth)) / 1000;  //1 meter in degree

var new_longitude = longitude + (your_meters * m) / cos(latitude * (pi / 180));

The variable your_meters can contain a positive or a negative value.

Contagion answered 24/5, 2018 at 10:9 Comment(1)
Thanks a lot, fixed my problem. but I'd say it'd be much better if you could add some more explanatory information concerning the bits, especially the m and what is going on there.Auntie
C
15

I had to spend about two hours to work out the solution by @nibot , I simply needed a method to create a boundary box given its center point and width/height (or radius) in kilometers:

I don't fully understand the solution mathematically/ geographically. I tweaked the solution (by trial and error) to get the four coordinates. Distances in km, given the current position and distance we shift to the new position in the four coordinates:

North:

private static Position ToNorthPosition(Position center, double northDistance)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_latitude = center.Lat + (northDistance / r_earth) * (180 / pi);
    return new Position(new_latitude, center.Long);
}

East:

private static Position ToEastPosition(Position center, double eastDistance)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_longitude = center.Long + (eastDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
    return new Position(center.Lat, new_longitude);
}

South:

private static Position ToSouthPosition(Position center, double southDistance)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_latitude = center.Lat - (southDistance / r_earth) * (180 / pi);
    return new Position(new_latitude, center.Long);
}

West:

private static Position ToWestPosition(Position center, double westDistance)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_longitude = center.Long - (westDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
    return new Position(center.Lat, new_longitude);
}
Christner answered 4/2, 2020 at 15:0 Comment(0)
G
10

Have you checked out: How do I find the lat/long that is x km north of a given lat/long ?

These calculations are annoying at best, I've done many of them. The haversine formula will be your friend.

Some reference: http://www.movable-type.co.uk/scripts/latlong.html

Gravitative answered 19/9, 2011 at 20:39 Comment(3)
if you work for a quite small area, is it really bad to just do latitude-0.09 and longtitude-0.0148 to get approximately a square km area?Berndt
I'd say it's not really bad. The square km at that level will not be distorted by the curvature of the Earth - as long as the Lat/Lng's you're dealing with is decimal.Gravitative
@BenjaminUdinktenCate That will work in Amsterdam, but will be inaccurate in other parts of the world. Doing "longitude-0.0148" will only get you about 0.16 km at the equator.Airlift
W
5

Posting this method for sake of completeness.

Use this method "as it is" to:

  • Move any (lat,long) point by given meters in either axis.

Python method to move any point by defined meters.

def translate_latlong(lat,long,lat_translation_meters,long_translation_meters):
    ''' method to move any lat,long point by provided meters in lat and long direction.
    params :
        lat,long: lattitude and longitude in degrees as decimal values, e.g. 37.43609517497065, -122.17226450150885
        lat_translation_meters: movement of point in meters in lattitude direction.
                                positive value: up move, negative value: down move
        long_translation_meters: movement of point in meters in longitude direction.
                                positive value: left move, negative value: right move
        '''
    earth_radius = 6378.137

    #Calculate top, which is lat_translation_meters above
    m_lat = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000;  
    lat_new = lat + (lat_translation_meters * m_lat)

    #Calculate right, which is long_translation_meters right
    m_long = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000;  # 1 meter in degree
    long_new = long + (long_translation_meters * m_long) / math.cos(lat * (math.pi / 180));
    
    return lat_new,long_new
Wordage answered 25/10, 2021 at 19:42 Comment(0)
I
2

Working Python code to offset coordinates by 10 metres.

def add_blur(lat, long):
meters = 10
blur_factor = meters * 0.000006279
new_lat = lat + blur_factor
new_long = long + blur_factor / math.cos(lat * 0.018)
return new_lat, new_long
Infante answered 10/9, 2021 at 15:5 Comment(1)
the magic number 0.00006279 you used can result in a huge offset. replace it with the value of this : earth_radius_in_km = 6378.137 coeff = (1 / ((2 * math.pi / 360) * earth_radius_in_km)) / 1000 blur_factor = meters * coeff # depending on the north, south use - or + on meters by applying this change, the offset for my shrunk from 36 meters to around 10 centimeters!Auntie
D
1

if you don't have to be very exact then: each 10000 meters is about 0.1 for latitude and longitude. for example I want to load locations 3000 meters around point_A from my database:

double newMeter =  3000 * 0.1 / 10000;
double lat1 = point_A.latitude - newMeter;
double lat2 = point_A.latitude + newMeter;
double lon1 = point_A.longitude - newMeter;
double lon1 = point_A.longitude + newMeter;
Cursor c = mDb.rawQuery("select * from TABLE1  where lat >= " + lat1 + " and lat <= " + lat2 + " and lon >= " + lon1 + " and lon <= " + lon2 + " order by id", null);
Disfrock answered 27/6, 2020 at 13:48 Comment(0)
R
1
public double MeterToDegree(double meters, double latitude)
{
    return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}
Reign answered 28/10, 2020 at 9:52 Comment(0)
L
0
var meters = 50;
var coef = meters * 0.0000089;
var new_lat = map.getCenter().lat.apply() + coef;
var new_long = map.getCenter().lng.apply() + coef / Math.cos(new_lat * 0.018);
map.setCenter({lat:new_lat, lng:new_long});
Lorenalorene answered 19/12, 2019 at 21:32 Comment(2)
Please add some explanation to your answer.Leisured
if you want move map object about 50 meter near the center of current map, then you can use this code with +,- numbers as replacement for +50Lorenalorene
S
0

See from Official Google Maps Documentation (link below) as they solve on easy/simple maps the problems with distance by countries :)

I recommended this solution to easy/simply solve issue with boundaries that you can know which area you're solving the problem with boundaries (not recommended globally)

Note:

Latitude lines run west-east and mark the position south-north of a point. Lines of latitude are called parallels and in total there are 180 degrees of latitude. The distance between each degree of latitude is about 69 miles (110 kilometers).

The distance between longitudes narrows the further away from the equator. The distance between longitudes at the equator is the same as latitude, roughly 69 miles (110 kilometers) . At 45 degrees north or south, the distance between is about 49 miles (79 kilometers). The distance between longitudes reaches zero at the poles as the lines of meridian converge at that point.

Original source 1 Original source 2 enter image description here

Official Google Maps Documentation: Code Example: Autocomplete Restricted to Multiple Countries

See the part of their code how they solve problem with distance center + 10 kilometers by +/- 0.1 degree

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 50.064192, lng: -130.605469 },
      zoom: 3,
    }
  );
  const card = document.getElementById("pac-card") as HTMLElement;
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
  const center = { lat: 50.064192, lng: -130.605469 };

  // Create a bounding box with sides ~10km away from the center point
  const defaultBounds = {
    north: center.lat + 0.1,
    south: center.lat - 0.1,
    east: center.lng + 0.1,
    west: center.lng - 0.1,
  };

  const input = document.getElementById("pac-input") as HTMLInputElement;
  const options = {
    bounds: defaultBounds,
    componentRestrictions: { country: "us" },
    fields: ["address_components", "geometry", "icon", "name"],
    origin: center,
    strictBounds: false,
    types: ["establishment"],
  };
Suffruticose answered 3/4, 2021 at 12:1 Comment(0)
G
0

This is what I did in VBA that seems to be working for me. Calculation is in feet not meters though

Public Function CalcLong(OrigLong As Double, OrigLat As Double, DirLong As String, DirLat As String, DistLong As Double, DistLat As Double)
    Dim FT As Double
    Dim NewLong, NewLat As Double
    FT = 1 / ((2 * WorksheetFunction.Pi / 360) * 20902230.971129)
    
    If DirLong = "W" Then
        NewLat = CalcLat(OrigLong, OrigLat, DirLong, DirLat, DistLong, DistLat)
        NewLong = OrigLong - ((FT * DistLong) / Cos(NewLat * (WorksheetFunction.Pi / 180)))
        CalcLong = NewLong
    Else
        NewLong = OrigLong + ((FT * DistLong) / Math.Cos(CalcLat(OrigLong, OrigLat, DirLong, DirLat, DistLong, DistLat) * (WorksheetFunction.Pi / 180)))
        CalcLong = NewLong
    End If
    
End Function


Public Function CalcLat(OrigLong As Double, OrigLat As Double, DirLong As String, DirLat As String, DistLong As Double, DistLat As Double) As Double
    Dim FT As Double
    Dim NewLat As Double
    
    FT = 1 / ((2 * WorksheetFunction.Pi / 360) * 20902230.971129)
    
    If DirLat = "S" Then
        NewLat = (OrigLat - (FT * DistLat))
        CalcLat = NewLat
    Else
        NewLat = (OrigLat + (FT * DistLat))
        CalcLat = NewLat
    End If
    
End Function

Gd answered 22/8, 2021 at 19:7 Comment(0)
J
0

Original poster said: "So I have 50.0452345 (x) and 4.3242234 (y) and I want to know x + 500 meters..."

I will assume the units of the x and y values he gave there were in meters (and not degrees Longitude, Latitude). If so then he is stating measurements to 0.1 micrometer, so I will assume he needs similar accuracy for the translated output. I also will assume by "+500 meters" etc. he meant the direction to be due North-South and due East-West. He refers to a reference point: "2 new latitudes based on a coordinate"; but he did not give the Longitude and Latitude, so to explain the procedure concretely I will give the Latitudes and Longitudes for the corners of the 500 meter box he requested around the point [30 degrees Longitude,30 degrees Latitude].

The exact solution on the surface of the GRS80 Ellipsoid is given with the following set of functions (I wrote these for the free-open-source-mac-pc math program called "PARI" which allows any number of digits precision to be setup):

\\=======Arc lengths along Latitude and Longitude and the respective scales:
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;
\\=======

I then plugged the reference point [30,30] into those functions at the PARI command prompt and had PARI solve for the point +/- 500 meters away from it, giving the two new Longitudes and two new Latitudes that the original poster asked for. Here is the input and output showing that:

? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)+500))
cpu time = 1 ms, real time = 1 ms.
%1172 = [29, 59, 41.3444979398934670450280297216509190843055]
? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)-500))
cpu time = 1 ms, real time = 1 ms.
%1173 = [30, 0, 18.6555020601065329549719702783490809156945]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)+500))
cpu time = 1,357 ms, real time = 1,358 ms.
%1174 = [29, 59, 43.7621925447500548285775757329518579545513]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)-500))
cpu time = 1,365 ms, real time = 1,368 ms.
%1175 = [30, 0, 16.2377963202802863245716034907838199823349]
? 
Jamie answered 20/6, 2022 at 6:24 Comment(1)
Ideally, this program is supposed to run globally with any given set of parameters.Anitraaniweta

© 2022 - 2024 — McMap. All rights reserved.