views:

516

answers:

2

Hi All,

Can any trig or GPS experts help me out here? I'm trying to create a geo-spacial bounding box (rectangle) calculation returning the maximum latitude and longitude using the following method that I've retrieved. I am calling the method once for each of the for bearings: north, south, east and west. With these four values I intend to query my Core Data store for all objects within the box.

  -(CLLocation*) offsetLocation:(CLLocation*)startLocation:(double)offsetMeters:(double)bearing {


    double EARTH_MEAN_RADIUS_METERS = 6372796.99;
    double newLatitude = asin( sin(startLocation.coordinate.latitude) * cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) + cos(startLocation.coordinate.latitude) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(bearing) );
    double newLongitude = startLocation.coordinate.longitude + atan2( sin(bearing) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(startLocation.coordinate.latitude), cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) - sin(startLocation.coordinate.latitude) * sin(newLatitude));


    CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:newLatitude longitude:newLongitude];
    [tempLocation autorelease];
    return tempLocation;
}

The problem is the calculation for the newLatitude offset is definitely incorrect. Given the following:

startLocation: latitude 37.331688999999997, longitude -122.030731 offsetMeters : 1000 bearing : 0 (north)

newLatitude returns -0.36726592610659514 (incorrect).

Any suggestions? I've coded around this particular formula until now and this one has me stumped. I've also tried translating a different formula from PHP to no avail. I figure the above is exactly what I need if it can be tweaked.

Thanks, b.dot

A: 

I haven't looked at your code, but you could also use the MapKit function MKCoordinateRegionMakeWithDistance() to have the framework calculate a bounding box for you.

CLLocationCoordinate2D center = { 37.3, -122.0 };
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, 2000.0, 2000.0);
CLLocationCoordinate2D northWestCorner, southEastCorner;
northWestCorner.latitude  = center.latitude  - (region.span.latitudeDelta  / 2.0);
northWestCorner.longitude = center.longitude + (region.span.longitudeDelta / 2.0);
southEastCorner.latitude  = center.latitude  + (region.span.latitudeDelta  / 2.0);
southEastCorner.longitude = center.longitude - (region.span.longitudeDelta / 2.0);
Ole Begemann
Wow. I'm not using MapKit, so I hadn't thought of looking there. Thanks. I'm going to try both methods.
b.dot
MKCoordinateRegionMakeWithDistance makes a nice box very easily, however I'm not sure how to retrieve the bounds (maximum latitude or longitude) of the newly created region. All of the properties seemed to be related to the MapView itself.
b.dot
It's just a little math, isn't it? I added some code to my answer. Note that this code doesn't work if the bounding box crosses the date line or the poles. But then, you'd need to split it into multiple boxes anyway to query the data store.
Ole Begemann
Ole, Thanks!.It works perfectly. This was my first experience with MapKit and it never occurred to me that you could do this with simple math. I spent two days trying to understand the Haversine and Vincenty formulas until my brain was mush. Now, that is "a little math". :)
b.dot
A: 

CLLocationCoordinate2D stores coordinates in degrees, but the trig functions you're using require radian units. If you convert to radians (multiply by M_PI/180, or 0.017453293f), it will probably work.

Brian Chapados
Thanks Brian. I'll keep that in mind.
b.dot