Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geo Spacial Bounding Box Rectangle Calculation Error: Latitude Incorrect

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

like image 228
b.dot Avatar asked Mar 09 '10 13:03

b.dot


3 Answers

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);
like image 137
Ole Begemann Avatar answered Nov 14 '22 23:11

Ole Begemann


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.

like image 27
Brian Chapados Avatar answered Nov 14 '22 21:11

Brian Chapados


How are you guys setting up the NSPredicates?

I seem to run into performance issues with mine.

NSPredicate *northWestLat = [NSPredicate predicateWithFormat:@"ANY locations.lat > %lf", northWestCorner.latitude];
NSPredicate *southhWestLat = [NSPredicate predicateWithFormat:@"ANY locations.lat < %lf", southEastCorner.latitude];
NSPredicate *latitudePredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:northWestLat, southhWestLat, nil]];

NSPredicate *northWestLng = [NSPredicate predicateWithFormat:@"ANY locations.lng < %lf", northWestCorner.longitude];
NSPredicate *southEastLng = [NSPredicate predicateWithFormat:@"ANY locations.lng > %lf", southEastCorner.longitude];
NSPredicate *longitudePredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:northWestLng, southEastLng, nil]];

NSPredicate *coordPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:latitudePredicate, longitudePredicate, nil]];
like image 28
Jeremy Foo Avatar answered Nov 14 '22 21:11

Jeremy Foo