"Get 100 meters out from" Haversin Formula

1.5k Views Asked by At

I'm interested in working with coordinates, and I was wondering, how is it possible to get the distance between two points (coordinates) in meters. After a long search I found the Haversine Formula, and the Objective-C implementation of it here.

It's the following (I modified it a little bit for myself):

- (CGFloat)directMetersFromCoordinate:(CLLocation *)from toCoordinate:(CLLocation *)to {

static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;

double latitudeArc  = (from.coordinate.latitude - to.coordinate.latitude) * DEG_TO_RAD;
double longitudeArc = (from.coordinate.longitude - to.coordinate.longitude) * DEG_TO_RAD;
double latitudeH = sin(latitudeArc * 0.5);
latitudeH *= latitudeH;
double lontitudeH = sin(longitudeArc * 0.5);
lontitudeH *= lontitudeH;
double tmp = cos(from.coordinate.latitude*DEG_TO_RAD) * cos(to.coordinate.latitude*DEG_TO_RAD);
return EARTH_RADIUS_IN_METERS * 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH)); }

My question is: How is it possible to get 100 meters distance (for latitude and for longitude) for the current location? This formula is too complicated for me, I don't understand it, so I can't "code it back" to get the result what I want.

I need only the actual location (Paris, Tokyo, London, New York, whatever), and a (float) number for latitude and a (float) number for longitude, which (float) number represents 100 meters distance from the actual location.

If you open this page, here you can "calculate out" the 100 meters distance between two points ("actual" and the one 100 meters away).

For example:

Point1: 47.0, 19.0 Point2: 47.0, 19.0013190 ---That's 0.1000 km (100 m) distance.

Point1: 47.0, 19.0 Point2: 47.0008995, 19.0 ---is also 0.1000 km (100 m) distance.

Here you can see, that at that coordinate (latitude 47.0 and longitude 19.0) 100 meters distance is 0.0008995 (latitude) and 0.0013190 (longitude).

And I want to get these data with the help of the Haversine Formula, just don't know, how.

Could you help me to figure it out?

Thanks!

UPDATE: Thank you for the answers, right now I don't have time to try them out, but as I understood, I didn't explain exactly what I want. Maybe this is a better example, how I want to use these "100 meters":

So, right now I'm at the coordinate "lat x" and "lon y". There is another point (let's say a hotel) at another given coordinate, "lat a" and "lon b". My question is: how can I calculate out, if this hotel is (less than) 100 meters from me? So it doesn't matter, if it's only 5 meters or 99 meters, both of them are less (or equal) than 100 meters far from me.

With the code what I provided, I can calculate this out, that's what that formula is for.

But let's say, I have a million of other coordinates (hotel locations) that I want to work with. And I need only a list of them, what are (less than) 100 meters away from me. So yes, that's a circle around me with a radius of 100 meters, and I need the results within that.

It would take much more time and resource to take all the coordinates of these "million" hotels and calculate the distance one by one, that's why I thought it would be much easier to calculate out, how much 100 meters are in latitude and longitude (changes the value as we are on different locations, that' why I can't use simply the ones what I calculated out in the example above). So if I would know how much 100 meters are in latitude and longitude for example at London's coordinate (if I'm there), I could simply get the list of the hotels what are (less than) 100 meters far from me, by a simple dividing:

if 
((hotelLocation.coordinate.latitude <= (myLocation.coordinate.latitude + "100metersInLatitude")) || (hotelLocation.coordinate.latitude >= (myLocation.coordinate.latitude - "100metersInLatitude")))
&&
((hotelLocation.coordinate.longitude <= (myLocation.coordinate.longitude + "100metersInLongitude")) || (hotelLocation.coordinate.longitude >= (myLocation.coordinate.longitude - "100metersInLongitude")))
{
   NSLog(@"Be Happy :-) !");
}

I just need these "100metersInLatitude" and "100metersInLongitude", calculated always from "myLocation".

Whoa, I hope, somebody will understand what I just wrote down, because it's not easy for me, neither... :-)))

3

There are 3 best solutions below

0
On

Assuming you have a point with latitude and longitude, and you want to find another point that is a distance d on a bearing b, when the distance is small (you said "100 meters" which is very small on the surface of the earth) then you can do a simple approximation - treating the earth's surface locally as "flat". Here is a simple C program that implements this (using the numbers you had above). I updated it to include the "accurate" formulation as well - it's just a few more calculations, but it is accurate at all distances (and not just the short ones). The equation I used came from the link you referenced - subheading "Destination point given distance and bearing from start point"

updated - I moved the accurate calculation into a separate function, and added a loop to compute the new point for all integer bearings from 0 to 359, printing out every 30th. This give you the "circle" I talked about in my initial comment.

#include <stdio.h>
#include <math.h>

double radians(double x) {
  return acos(0.0) * x / 90.0;
}

void calcNewPosition(double lat, double lon, double bearing, double d, double *newLat, double *newLon) {
  double lat1, lon1, br, pi;
  double Re = 6371000;
// convert everything to radians first:
  lat1 = radians(lat);
  lon1 = radians(lon);
  br = radians(bearing);

  pi = 2 * acos(0.0);

  double lat2, lon2;
  lat2 = asin( sin(lat1) * cos(d/Re) +
              cos( lat1 ) * sin( d / Re ) * cos(br ) );
  lon2 = lon1 + atan2(sin(br) * sin( d / Re ) * cos( lat1 ), \
    cos( d / Re ) - sin(lat1 ) * sin( lat2 ) );
  *newLat = 180. * lat2 / pi;
  *newLon = 180. * lon2 / pi;
}


int main(void) {
  double lon = 47., lat=19.;
  double newLongitude, newLatitude;
  double dx, dy, dLong, dLat;
  double Re = 6371000, d = 100, bearing = 0.0;
  double pi;
  double lat1, lon1, br;

  // convert everything to radians first:
  lat1 = radians(lat);
  lon1 = radians(lon);
  br = radians(bearing);

  pi = 2 * acos(0.0);

  // approximate calculation - using equirectangular approximation
  // and noting that distance between meridians (lines of longitude)
  // get closer at higher latitudes, with cos(latitude).
  dx = d * sin(br);                                // distance in E-W direction
  dy = d * cos(br);                                // distance in N-S direction
  dLat = 360 * dy / (2.0 * pi * Re);               // convert N-S to degrees latitude
  dLong = 360 * dx / (2.0 * pi * Re * cos(lat1));  // convert E-W to degrees longitude

  newLatitude = lat + dLat;
  newLongitude = lon + dLong;
  printf("simple forumula: the new position is %.8lf lon, %.8lf lat\n", newLongitude, newLatitude);

  // more accurate formula: based on http://www.movable-type.co.uk/scripts/latlong.html

  double lat2, lon2;
  calcNewPosition(lat, lon, bearing, d, &lat2, &lon2);
  printf("more accurate:   the new position is %.8lf lon, %.8lf lat\n", lon2, lat2);

  // now loop over all bearings and compute the "circle of points":
  int iBearing;
  double lonArray[360], latArray[360];
  for(iBearing = 0; iBearing < 360; iBearing++) {
    calcNewPosition(lat, lon, (double)iBearing, d, &latArray[iBearing], &lonArray[iBearing]);
    if (iBearing % 30 == 0) printf("bearing %03d: new lat = %.8lf, new lon = %.8lf\n", iBearing, latArray[iBearing], lonArray[iBearing]);
  }

return 0;
}

The output of this is

simple forumula: the new position is 47.00000000 lon, 19.00089932 lat
more accurate:   the new position is 47.00000000 lon, 19.00089932 lat
bearing 000: new lat = 19.00089932, new lon = 47.00000000
bearing 030: new lat = 19.00077883, new lon = 47.00047557
bearing 060: new lat = 19.00044966, new lon = 47.00082371
bearing 090: new lat = 19.00000000, new lon = 47.00095114
bearing 120: new lat = 18.99955034, new lon = 47.00082371
bearing 150: new lat = 18.99922116, new lon = 47.00047557
bearing 180: new lat = 18.99910068, new lon = 47.00000000
bearing 210: new lat = 18.99922116, new lon = 46.99952443
bearing 240: new lat = 18.99955034, new lon = 46.99917629
bearing 270: new lat = 19.00000000, new lon = 46.99904886
bearing 300: new lat = 19.00044966, new lon = 46.99917629
bearing 330: new lat = 19.00077883, new lon = 46.99952443

As you can see, it is accurate to within a fraction of a meter (your code gave 19.0008995 - it is actually possible that your result was "wrong" in the last digit as these two methods agree to 8 significant digits even though they use different equations).

0
On

The question isn't really answerable if the OP wants a location a distance (100 meters) from the current location without a desired bearing being provided, there being an infinite number of points in a circle around the point.

So, this answer may or may not be what the OP wants, it is a way with CLLocation to calculate the distance between two points.

Create two CLLocation point and use the method Have you looked at theCLLocationmethod- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location`.

CLLocation *location1 = [[CLLocation alloc] initWithLatitude:)latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:)latitude2 longitude:longitude2];
double distance = [location1 distanceFromLocation:location2];
0
On

The radius of the earth at equator = 6,371 km. The equator is divided into 360 degrees of longitude, so each degree at the equator represents approximately 111.32 km. Moving away from the equator towards a pole this distance decreases to zero at the pole.To calculate the distance at different latitudes multiply it by the cosine of the latitude

3 decimal places,0.001 degrees aproximates to 111.32 meters at equator
96.41meters at 30 degrees N/S
78.71 meters at 45 degrees N/S
55.66 meters at 60 degrees N/S
28.82 meters at 75 degrees N/S

For for small distances (100 meters) Pythagoras’ theorem can be used on an equirectangular projection to calculate distance. This is less complicated than Haversine or Spherical Law of Cosines.

var R = 6371; // km
lat/lng in radians

In pseudo code as I don't know Objective-C

var x = (lng2-lng1) * cos((lat1+lat2)/2);
var y = (lat2-lat1);
var d = sqrt(x*x + y*y) * R;