96
votes

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.

9

9 Answers

138
votes

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.

34
votes

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)
// 1km in degree = 1 / 111.32km = 0.0089
// 1m in degree = 0.0089 / 1000 = 0.0000089
double coef = meters * 0.0000089;

double new_lat = my_lat + coef;

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

Hope this helps too.

22
votes

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.

9
votes

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

5
votes

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 understand the solution mathematically/ geographically. I tweaked the solution (by try and error) to get the four coordinates:

North:

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

East:

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

South:

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

West:

private static Position FromKmToWPosition(Position p, double km)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_longitude = p.Long - (km / r_earth) * (180 / pi) / Math.Cos(p.Lat * pi / 180);
    return new Position(p.Lat, new_longitude);
}
1
votes

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);
0
votes
public double MeterToDegree(double meters, double latitude)
{
    return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}
0
votes

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"],
  };
-1
votes
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});