Skip to content

Instantly share code, notes, and snippets.

@valarpirai
Created September 22, 2016 05:10
Show Gist options
  • Save valarpirai/ea1b85cb5d74ded4d885c502abb0b2fc to your computer and use it in GitHub Desktop.
Save valarpirai/ea1b85cb5d74ded4d885c502abb0b2fc to your computer and use it in GitHub Desktop.
Objective-C for finding latitude and longitude range boundaries
//
// GeoLocationUtils.m
#import "GeoLocationUtils.h"
@implementation GeoLocationUtils
float TO_RADIAN = 0.0174532925,
TO_DEGREE = 57.2957795,
TO_MILE = 0.621371192,
TO_KM = 1.609344;
float MIN_LAT, MAX_LAT, MIN_LON, MAX_LON;
+ (double) degreeToRadian: (double) degree {
return degree * TO_RADIAN;
}
+ (double) radianToDegree: (double) radian {
return radian * TO_DEGREE;
}
+ (float) kmToMile: (float) km {
return km * TO_MILE;
}
+ (float) mileToKm: (float) mile {
return mile * TO_KM;
}
+ (void) initializeLocal {
MIN_LAT = [GeoLocationUtils degreeToRadian: -90.0];
MAX_LAT = [GeoLocationUtils degreeToRadian: 90.0];
MIN_LON = [GeoLocationUtils degreeToRadian: -180.0];
MAX_LON = [GeoLocationUtils degreeToRadian: 180.0];
}
// Semi-axes of WGS-84 geoidal reference
float WGS84_a = 6378137.0; // Major semiaxis [meter]
float WGS84_b = 6356752.3; // Minor semiaxis [meter]
// Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
+ (float) WGS84EarthRadius: (float)lat {
// http://en.wikipedia.org/wiki/Earth_radius
float An = WGS84_a * WGS84_a * cos(lat);
float Bn = WGS84_b * WGS84_b * sin(lat);
float Ad = WGS84_a * cos(lat);
float Bd = WGS84_b * sin(lat);
return sqrt( (An * An + Bn * Bn) / (Ad * Ad + Bd * Bd) );
}
+(BOOL) checkBounds: (float) radLat RadianLong: (float) radLon {
if (radLat < MIN_LAT || radLat > MAX_LAT || radLon < MIN_LON || radLon > MAX_LON) {
NSLog(@"radLat or radLon is out of bounds");
return NO;
}
return YES;
}
+ (NSArray *) calculateBoundryForLatitude: (float)latitude Longitude: (float)longitude DistanceinKm: (float)distance {
return [GeoLocationUtils calculateBoxBoundryForLatitude:[NSString stringWithFormat:@"%f", latitude] Longitude:[NSString stringWithFormat:@"%f",longitude] DistanceinKm: distance];
}
+ (NSArray *) calculateBoxBoundryForLatitude: (NSString *)latitude Longitude: (NSString *)longitude DistanceinKm: (float)distance {
NSLog(@"Latitude - %@, Longitude - %@", latitude, longitude);
[GeoLocationUtils initializeLocal];
NSString *radLat = [NSString stringWithFormat:@"%f", [GeoLocationUtils degreeToRadian:[latitude doubleValue]]];
NSString *radLon = [NSString stringWithFormat:@"%f", [GeoLocationUtils degreeToRadian:[longitude doubleValue]]];
// NSLog(@"Radian Latitude - %@, Longitude - %@", radLat, radLon);
// NSLog(@"Degree Latitude - %f, Longitude - %f", [GeoLocationUtils radianToDegree:[radLat floatValue]], [GeoLocationUtils radianToDegree: [radLon floatValue]]);
if([GeoLocationUtils checkBounds: [radLat floatValue] RadianLong: [radLon floatValue]] == NO) {
// Location Out of bounds
return [[NSArray alloc] init];
}
NSDictionary *location = [[NSDictionary alloc] initWithObjectsAndKeys:latitude, kLatitude, longitude, kLongitude, radLat, kRadianLat, radLon, kRadianLong, nil];
return [GeoLocationUtils boundingCoordinates:location distanceInKm:distance];
}
// Bounding box surrounding the point at given coordinates, assuming local approximation of Earth surface as a sphere of radius given by WGS84
+ (NSArray *) boundingCoordinates:(NSDictionary *)location distanceInKm:(float)distance {
if (distance < 0) {
// console.log("no location or distance");
return [[NSArray alloc] init];
}
// NSLog(@"==== > Passed - %@", location);
float lat = [[location objectForKey:kRadianLat] floatValue];
float lon = [[location objectForKey:kRadianLong] floatValue];
// NSLog(@"Passed Radian Latitude - %f, Longitude - %f", lat, lon);
float halfSide = 1000 * distance;
// Radius of Earth at given latitude
float radius = [GeoLocationUtils WGS84EarthRadius: lat];
// NSLog(@"Earth Radius in Meters - %f", radius);
// Radius of the parallel at given latitude
float pradius = radius * cos(lat);
float latMin = lat - halfSide/radius;
float latMax = lat + halfSide/radius;
float lonMin = lon - halfSide/pradius;
float lonMax = lon + halfSide/pradius;
NSString *minLatStr = [NSString stringWithFormat: @"%f", [GeoLocationUtils radianToDegree: latMin]];
NSString *maxLatStr = [NSString stringWithFormat: @"%f", [GeoLocationUtils radianToDegree: latMax]];
NSString *minLonStr = [NSString stringWithFormat: @"%f", [GeoLocationUtils radianToDegree: lonMin]];
NSString *maxLonStr = [NSString stringWithFormat: @"%f", [GeoLocationUtils radianToDegree: lonMax]];
NSArray *boundries = [[NSArray alloc] initWithObjects: minLatStr, minLonStr, maxLatStr, maxLonStr, nil];
NSLog(@"=====> Box Boundaries : %@", boundries);
return boundries;
}
+ (float) getDistanceInKmForMinLat: (NSString *)minlat MinLong: (NSString *)minlong MaxLat: (NSString *)maxlat MaxLong: (NSString *)maxlong {
float lat1 = [minlat floatValue];
float lon1 = [minlong floatValue];
float lat2 = [maxlat floatValue];
float lon2 = [maxlong floatValue];
float R = [GeoLocationUtils WGS84EarthRadius: lat1] / 1000; // Radius of the earth in km
float dLat = [GeoLocationUtils degreeToRadian:(lat2 - lat1)]; // deg2rad below
float dLon = [GeoLocationUtils degreeToRadian:(lon2-lon1)];
float radLat1 = [GeoLocationUtils degreeToRadian: lat1];
float radLat2 = [GeoLocationUtils degreeToRadian: lat2];
float a = sin(dLat/2) * sin(dLat/2) + cos(radLat1) * cos(radLat2) * sin(dLon/2) * sin(dLon/2);
float c = 2 * atan2(sqrt(a), sqrt(1-a));
float d = R * c; // Distance in km
return d;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment