Created
September 22, 2016 05:10
-
-
Save valarpirai/ea1b85cb5d74ded4d885c502abb0b2fc to your computer and use it in GitHub Desktop.
Objective-C for finding latitude and longitude range boundaries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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