Reputation: 34629
I'm creating an iPhone app with Weather lookup for particular locations and I have the following problem that i'm not sure the best way to tackle.
I have the latitude and longitude of a location and want to find the closest lat/long match from a list of 5000+ locations
The 5000+ locations come from a JSON feed from Met Office Datapoint API and are in the form of a NSArray of NSDictionaries, the NSDictionary includes id, lat, long and name.
I want to match my location to the nearest location from the list from the Met Office and grab the id key value.
Many Thanks in advance
Upvotes: 2
Views: 2065
Reputation: 77641
I'm assuming you're using CLLocation objects in this...
- (CLLocation*)closestLocationToLocation:(CLLocation*)currLocation
{
CLLocationDistance minDistance;
CLLocation *closestLocation = nil;
for (CLLocation *location in arrayOfLocations) {
CLLocationDistance distance = [location distanceFromLocation:currLocation];
if (distance <= minDistance
|| closestLocation == nil) {
minDistance = distance;
closestLocation = location;
}
}
//closestLocation is now the location from your array which is closest to the current location or nil if there are no locations in your array.
return closestLocation;
}
There may be a quicker way of doing this but this will get it done.
EDITED to use CLLocation functions
Upvotes: 3
Reputation: 1437
I'd suggest something like this:
NSMutableArray *tempArray = [NSMutableArray new];
for (NSMutableDictionary *location in yourArrayOfLocations){
CLLocation coord;
coord.latitude = [location objectForKey:@"latitude"];
coord.longitude = [location objectForKey:@"longitude"];
[location setValue:[usersLocation distanceFromLocation:coord] forKey:@"distance"];
[tempArray addObject:location];
}
// Now sort the array
NSArray *sortedArray = [tempArray sortedArrayUsingComparator:^(id o1, id o2) {
NSDictionary *location1 = (NSDictionary *)o1;
NSDictionary *location2 = (NSDictionary *)o2;
return [[location1 objectForKey:@"distance"] compare:[location2 objectForKey:@"distance"]];
}];
[tempArray release];
Now you have an array ordered by distance. You can use the object at index 0, as it is the closest to the user's position.
Good Luck!
Upvotes: -1
Reputation: 14068
I did a similar thing once (finding all lat/lon Objects surrounding a point with a max. radius) and used the formula given here: http://www.movable-type.co.uk/scripts/latlong.html However, that was quite time consuming. So I sort of "boxed" the objects fist. Based on the calculation above (reverted of course) I calculated the latitude and longitude of those coordinates north, west, south and east that had exactly the maximum distance. With hose max and min values (for lat and lon) I queried all objects in question. And only for those I calculated the exact distance and included them in the list of results or excluded them.
However, so far that does not exactly match your problem. But I tried to fasten the calculations even further. For that I said to myself, that I do not need the exact distance from the searched object to mine but it is enogh to know wether it is closer than one of the boxes coordinates. And that part is the one that corresponds well to your question:
Your case could be much easier. Assuming that the locations in question (the shortest once) are close to the one location which you try to assign, all this complex math may not play a role. You do not need the exact distance. What you need is the cosest one. For that I would assume that the earth is flat and that the distances between longitudes (or latitude) are linear. That is not true of course but should be good enough to figure out, which of those is the closest. Going from there you could use pythagoras.
Distance = sqrt(sqr(difference-in-lat) + sqr(difference-in-lon));
For the mere purpose of comparing the distances and finding the shortest, you could even replace the time consuming square route with a much faster sqare operation.
Square-Of-Distance = sqr(difference-in-lat) + sqr(difference-in-lon).
And then compare the various Square-Of-Distance rather than the Distance. The result will be the same but much faster.
BTW, that was a PHP projects. That's why I cannot provide sample code but just explain the algorihm.
Upvotes: 0