I need to get the penultimate result from a for loop - ios

I have an array of waypoints stored which have latitude and longitude values. I have created a for loop to loop through the array and compare my current CLLocation positions latitude and longitude to find which of the waypoints i am closest to. I also need to get the second closest waypoint and store this ac s a CLLocation object as well but cannot get it working.
The logic would be something like this
am I closest
yes
move closest location to second closest
set as second closest
loop again to get the closest point
My code:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
//set latestlocation as the last object from the locations array
CLLocation *currentLocation = [locations lastObject];
//declare a closestpoint object
CLLocation *closestWayPointToCurrentLocation;
//declare a second closest point object
CLLocation *secondClosestWayPointToCurrentLocation;
//set the distance to a high number
float distance = 10000000;
float secondClosestWaypointDistance = 10000000;
//load in plist
NSString *plistName = [self.mapsInfo objectForKey:#"plistName"];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Chester" ofType:#"plist"];
NSString *path = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
//store in array called waypoints
NSArray *waypoints= [NSArray arrayWithContentsOfFile:path];
//declare a variable for locationNum (the waypoints)
int locationNum = 0;
for (NSDictionary *point in waypoints) {
CLLocation *waypointLocation = [[CLLocation alloc]initWithLatitude:[(NSNumber *)[point objectForKey:#"Lat"]floatValue] longitude:[(NSNumber *)[point objectForKey:#"Long"]floatValue]];
float waypointDistanceFromCurrentLocation = [currentLocation distanceFromLocation:waypointLocation];
//secondClosestWayPointToCurrentLocation = waypointLocation;
if(waypointDistanceFromCurrentLocation < distance) {
//todo: move the current closestWayPointToCurrentLocation into second postion
//update the second closest waypoint distance variable also with distance
distance = waypointDistanceFromCurrentLocation;
closestWayPointToCurrentLocation = waypointLocation;
if(closestWayPointToCurrentLocation == waypointLocation) {
}
}
else
{
//check against the second position
//if closer than second position, replace it with new waypoint with code similar to above
}

If you are sure the point you is always the penultimate then you can retrive it like this
int totalNumberOfWaypoints = [waypoints count];
//Get penultimate waypoints
NSDictionary *penultimateWaypoint = [waypoints objectAtIndex:(totalNumberOfWaypoints - 2)];

Why dont you just make a sorted array of points, sorted by distance in ascending order?
NSMutableArray *waypoints= [NSArray arrayWithContentsOfFile:path];
for (NSDictionary *point in waypoints) {
[waypoints sortUsingComparator: (NSComparisonResult) ^ (id obj1, id obj2) {
CLLocation *waypointLocation1 = [[CLLocation alloc]initWithLatitude:[(NSNumber *)[obj1 objectForKey:#"Lat"]floatValue] longitude:[(NSNumber *)[obj1 objectForKey:#"Long"]floatValue]];
CLLocation *waypointLocation2 = [[CLLocation alloc]initWithLatitude:[(NSNumber *)[obj2 objectForKey:#"Lat"]floatValue] longitude:[(NSNumber *)[obj2 objectForKey:#"Long"]floatValue]];
float distance1 = [currentLocation distanceFromLocation:waypointLocation1];
float distance2 = [currentLocation distanceFromLocation:waypointLocation2];
if (distance1 < distance2) {
return NSOrderedAscending;
}
else if (distance1 > distance2) {
return NSOrderedDescending
}
else
return NSOrderedSame;
}];
This way you can always have the closest point at [waypoints objectAtIndex:0] and second closest point at [waypoints objectAtIndex:1] and so on.
less work, better result IMHO

Related

iOS: How to get the distance of multiple location from one location

i am working on a project in which i have to show the distance of multiple locations from user's locations. locations are based on latitude and longitude.
i am using the following code to get the distance between two locations is shows nearly same distance
CLLocation *locA = [[CLLocation alloc] initWithLatitude:28.6379 longitude: 77.2432];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:28.6562 longitude:77.2410];
CLLocationDistance distance = [locA distanceFromLocation:locB];
NSLog(#"Distance is %f",distance);
float i = distance/1000;
NSLog(#"distance between two places is %f KM", i);
but now i am struct to get the distance of multiple locations from my location: locaA.
for example i take NSarray for latitude and longitude as
NSArray * latArray = [[NSArray alloc]initWithObjects:#"28.6129",#"28.6020",#"28.5244", nil];
NSArray * longArray = [[NSArray alloc]initWithObjects:#"77.2295",#"77.2478",#"77.1855", nil];
Please help me to resolve it
Take locaA as user's location
You can use below method to find distance
#define DEG2RAD(degrees) (degrees * 0.01745327)
double currentLatitudeRad = DEG2RAD(currentLatitude);
double currentLongitudeRad = DEG2RAD(currentLongitude);
double destinationLatitudeRad = DEG2RAD(destinationLatitude);
double destinationLongitudeRad = DEG2RAD(destinationLongitude);
double distance = acos(sin(currentLatitudeRad) * sin(destinationLatitudeRad) + cos(currentLatitudeRad) * cos(destinationLatitudeRad) * cos(currentLongitudeRad - destinationLongitudeRad)) * 6880.1295896;
Here, currentLatitude and currentLongitude is user's location. destinationLatitude and destinationLongitude is each object from your array "latArray" and "longArray" which you can iterate via for loop. distance is the distance between user's location and locations in array. Obtained distance will be in kilometres.
CLLocation *currentLocation = ... // This is a reference to your current location as a CLLocation
NSArray *arrayOfOtherCLLocationObjects = ... // This is an array that contains all of the other points you want to calculate the distance to as CLLocations
NSMutableArray *distancesFromCurrentLocation = [[NSMutableArray alloc] initWithCapacity:arrayOfOtherCLLocationObjects.count]; // We will add all of the calculated distances to this array
for (CLLocation *location in arrayOfOtherCLLocationObjects) // Iterate through each location object
{
CLLocationDistance distance = [location distanceFromLocation:currentLocation]; // Calculate distance
[distancesFromCurrentLocation addObject:#(distance)]; // Append distance to array. You need to wrap the distance object as an NSNumber so you can append it to the array.
}
// At this point, you have the distance for each location point in the array distancesFromCurrentLocation
Swift version:
let currentLocation: CLLocation = //current location
let otherLocations: [CLLocation] = //the locations you want to know their distance to currentLocation
let distances = otherLocations.map { $0.distanceFromLocation(currentLocation) }

How to add objects in a NSMutableDictionary

I have an app that uses MKMapView. In my app, I have declared an array that will hold the response from the API. The data from the API are the jobs to be pinned in the map (clustered annotations). The array that holds the jobs from the API will/needs to be filtered by the jobs pins that are visible in the map. I am able to filter the coordinates (visible or not visible in the map) but I am having troubles on storing the data (coordinates that are visible) in a new array.
Here's what I have so far:
In regionDidChangeAnimated in my mapview
[ar objectAtIndex:0];
NSMutableDictionary *visibleJobs;
for(NSDictionary *loc in ar)
{
CLLocationDegrees Lat = [[[loc objectForKey:#"sub_slots"] objectForKey:#"latitude"] doubleValue];
CLLocationDegrees longTitude = [[[loc objectForKey:#"sub_slots"] objectForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D point = CLLocationCoordinate2DMake(Lat, longTitude);
MKMapPoint mkPoint = MKMapPointForCoordinate(point);
BOOL contains = MKMapRectContainsPoint(mapView.visibleMapRect, mkPoint);
if(contains)
{
NSLog(#"Contains:1");
}
else
{
NSLog(#"Contains:0");
}
}
Any help will be very much appreciated.
Thanks!
why don't you use NSMutableArray
try this
NSMutableArray *visibleJobs = [[NSMutableArray alloc]init];
for(NSDictionary *loc in ar)
{
CLLocationDegrees Lat = [[[loc objectForKey:#"sub_slots"] objectForKey:#"latitude"] doubleValue];
CLLocationDegrees longTitude = [[[loc objectForKey:#"sub_slots"] objectForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D point = CLLocationCoordinate2DMake(Lat, longTitude);
MKMapPoint mkPoint = MKMapPointForCoordinate(point);
BOOL contains = MKMapRectContainsPoint(mapView.visibleMapRect, mkPoint);
if(contains)
{
NSLog(#"Contains:1");
[visibleJobs addObject:loc];
}
else
{
NSLog(#"Contains:0");
}
}
Now visible jobs array contains dictionary of all pin data which in currently visible on map

Find closest longitude and latitude in array from user location

I have an array full of longitudes and latitudes. I have two double variables with my users location. I'd like to test the distance between my user's locations against my array to see which location is the closest. How do I do this?
This will get the distance between 2 location but stuggeling to understand
how I'd test it against an array of locations.
CLLocation *startLocation = [[CLLocation alloc] initWithLatitude:userlatitude longitude:userlongitude];
CLLocation *endLocation = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];
CLLocationDistance distance = [startLocation distanceFromLocation:endLocation];
You just need to iterate through the array checking the distances.
NSArray *locations = //your array of CLLocation objects
CLLocation *currentLocation = //current device Location
CLLocation *closestLocation;
CLLocationDistance smallestDistance = DOUBLE_MAX;
for (CLLocation *location in locations) {
CLLocationDistance distance = [currentLocation distanceFromLocation:location];
if (distance < smallestDistance) {
smallestDistance = distance;
closestLocation = location;
}
}
At the end of the loop you will have the smallest distance and the closest location.
#Fogmeister
I think this is a mistake which must be set right about DBL_MAX and an assignment.
First : Use DBL_MAX instead of DOUBLE_MAX.
DBL_MAX is a #define variable in math.h.
It's the value of maximum representable finite floating-point (double) number.
Second : In your condition, your assignment is wrong :
if (distance < smallestDistance) {
distance = smallestDistance;
closestLocation = location;
}
You must do :
if (distance < smallestDistance) {
smallestDistance = distance;
closestLocation = location;
}
The difference is that will be assign distance value into smallestDistance, and not the opposite.
The final result :
NSArray *locations = //your array of CLLocation objects
CLLocation *currentLocation = //current device Location
CLLocation *closestLocation;
CLLocationDistance smallestDistance = DBL_MAX; // set the max value
for (CLLocation *location in locations) {
CLLocationDistance distance = [currentLocation distanceFromLocation:location];
if (distance < smallestDistance) {
smallestDistance = distance;
closestLocation = location;
}
}
NSLog(#"smallestDistance = %f", smallestDistance);
Can you confirm that is correct ?

find locations (from mutablearray) close to users location ios

)
i have an mutable array of restaurantObjects serialized form json data, if current object is named restaurantDetail i can acces corrdinates like this
float x = [[restaurantDetail.coordinates objectAtIndex:0] floatValue];
float y = [[restaurantDetail.coordinates objectAtIndex:1] floatValue];
so i would like to extract restaurants which are close to users location and store them to array
and if user changes location array should get updated too
i would really apprichiate help because i am completely lost here
i have tried this form Muthub Ram
- (void) checkIfInRegion{
Restaurant * currentRestaurant;
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
for(int i=0;i<[restaurantsArray count];i++){
currentRestaurant = [restaurantsArray objectAtIndex:i];
//NSLog(#"%#",currentRestaurant.coordinates);
CLLocation * currentRestLoc = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake([[currentRestaurant.coordinates objectAtIndex:0] floatValue], [[currentRestaurant.coordinates objectAtIndex:1] floatValue])
altitude:0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
NSLog(#"%#",currentRestLoc);
if([locationManager.location distanceFromLocation:currentRestLoc] <100)
{
//if less than 100meters
//then add object in this array
[near_by_user addObject:[restaurantsArray objectAtIndex:i]];
}
}
NSLog(#"%#",locationManager.location);
NSLog(#"restaurants near%#",near_by_user);
[locationManager stopUpdatingLocation];
}
i get all coordinates form location but i dont get any objects in near_by_user array ( it remains empty)
http://pastebin.com/fc8q69Le here is log, last set of coordinates is my location same as one of restaurants
for(i=0;i<[array_res count];i++){
if([clloc distanceFromLocation:[array_res objectatindex:i]<100])
{
//if less than 100meters
//then add object in this array
[near_by_user addobject:[array_res objectatindex:i];
}
}
please add this code.if you have any clarification update here

Using Block sortedArrayUsingComparator:^(id a, id b)

In my project, I try to compare a known location to an inputted location by using block sortedArrayUsingComparator:^(id a, id b). I have a dictionary array called locationArray containing a lat long and a station number that corresponds to that lat long point. I try to compare each locationArray station to the inputted station. I do this by taking the absolute value of the difference between the two which gives me a distance. Then I try to sort locationArray based on the distance from the inputted station from closest to furthest away.
//locationArray
#define kStation #"station"
#define kLatitude #"latitude"
#define kLongitude #"longitude"
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"499CSV" ofType:#"csv"];
NSString *csvString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *locations = [csvString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSMutableArray *CSVArray = [NSMutableArray array];
NSCharacterSet *whiteSPNewLine = [NSCharacterSet whitespaceAndNewlineCharacterSet];
for (NSString * location in locations)
{
NSArray *components = [location componentsSeparatedByString:#","];
double latitude = [[components[0] stringByTrimmingCharactersInSet:whiteSPNewLine] doubleValue];
double longitude = [[components[1] stringByTrimmingCharactersInSet:whiteSPNewLine] doubleValue];
NSString *station = [components[2] stringByTrimmingCharactersInSet:whiteSPNewLine];
NSDictionary *dict = #{kLatitude: #(latitude),
kLongitude: #(longitude),
kStation: station};
[CSVArray addObject:dict];
}
NSLog(#"The contents of CSVArray = %#",[CSVArray description]);
{
latitude = "41.674364";
longitude = "-81.23700700000001";
station = 40150;
},
{
latitude = "41.67517";
longitude = "-81.235038";
station = 40763;
},
{
latitude = "41.673106";
longitude = "-81.24017499999999";
station = 39175;
}, ...
My block code that directly follows locationArray.
NSArray *orderedPlaces = [CSVArray sortedArrayUsingComparator:^(id a, id b) {
NSDictionary *dictA;
NSDictionary *dictB;
NSString *locA;
NSString *locB;
int distanceA;
int distanceB;
dictA = (NSDictionary *)a;
dictB = (NSDictionary *)b;
NSLog(#"dictA = %#", dictA);
NSLog(#"dictB = %#", dictB);
locA = [dictA objectForKey:kStation];
locB = [dictB objectForKey:kStation];
NSLog(#"locA = %#", locA);
NSLog(#"locB = %#", locB);
distanceA = abs(stationNumber-[locA intValue]);
distanceB = abs(stationNumber-[locB intValue]);
NSLog(#"distanceA = %d", distanceA);
NSLog(#"distanceB = %d", distanceB);
if (distanceA < distanceB) {
return NSOrderedAscending;
} else if (distanceA > distanceB) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
NSLog(#"The contents of array = %#",[orderedPlaces description]);
The block runs but it's not sorting locationsArray as intended. orderedPlaces returns an unsorted locationsArray. By running NSLOG on the block components, I see that it successfully recognizes locationsArray and creates the distance object. I must be missing something because I use the same code in a different part of my project where I compare locationsArray to the lat long of the user's location and it works well. Please help me identify the issue keeping it from working as intended.
*If you need any more information or clarification, just ask.
I don't understand your sort block. You're calculating distance A as abs(stationNumber-[locA intValue]).
What is stationNumber? Is that some fixed integer index? How can the difference between a fixed station number and the station numbers in your array have anything to do with distances?
It seems to me that your distance values should be
(target.lat - this_station.lat)^2 + (target.long - this_station.long)^2
That will give you the square of the pythagorean distance between your target point and one of the stations you are comparing. Then in your comparison you select the item who's distance squared is less.
You can skip the square root, because you're just comparing them. That will make your distance calculations much faster.
Try this:
NSArray *orderedPlaces = [CSVArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
^(id a, id b) means ^void (id a, id b) and your return value is ignored.

Resources