convert string to core location - ios

I have latitude and longitude values as string and want to convert it to corelocation. My main intension is to calculate the distance between the user's current location (returned by the device) and the location returned from the server.
calculate distance using lat and long.. This post helped me to find distance between two locations.
Which of the following will be the best way?
Should I convert string to core location and calculate distance
or
should i convert the device location to string and calculate distance.

Create and object like so:
CLLocation *locA = [[CLLocation alloc] initWithLatitude:lat1 longitude:long1];
lat1 / long2 are of type CLLocationDegrees which is a typedef of a double, representing the point in degrees.
Convert your lat / long to doubles and pass them in, like so:
CLLocation *locA = [[CLLocation alloc] initWithLatitude:[#"" doubleValue] longitude:[#"" doubleValue] ];
The above code was in the example you linked to, you could have very easily google'd the object and it would have brought you to the doc online.
EDIT:
As per Volker's suggestion, if you are getting numbers from a server, there is a possibility of localisation issues, where some local's use a decimal: 46.000 and others use a comma 46,000.
Something like this would be better:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
NSNumber *temp = [formatter numberFromString:#""];
[temp doubleValue];

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) }

subtracting latitudes with NSNumber type to find distance

I want to subtract two latitudes from each other to find the shortest distance, but I get this error, "Arithmetic on pointer to interface 'NSNumber', which is not a constant size in non-fragile ABI" If I change the - to a + I get a different error "Invalid operands to binary expression ('NSNumber *' and 'NSNumber *')" I've tried using doubles and many combinations of things, but it just doesn't work.
NSNumber *userLatitude = [NSNumber numberWithDouble:43.55];//sample
NSArray *listOfCities = [managedObjectContext executeFetchRequest:request error:&error];
for (CityList *item in listOfCities){
NSLog(#"latitude is %#",item.latitude);
NSNumber *distanceLat = userLatitude - item.latitude;
I will then insert them into a mutable array along with the longitudes and compare the distance. One possible solution using CLLocation would be
double distance = [usersCurrentLoc distanceFromLocation:otherLoc];
where usersCurrentLoc and otherLoc are both CLLocation variables.
I also want use the latitude and longitudes individually so I can do some custom plotting, and they are also stored separately, so I'd like to figure out the correct data types and most efficient solution.
item.latitude comes from core-data with the data model type of double and X-code auto generated the CityList class with a property of NSNumber * latitude;
If you want subtract two NSNumbers, then use this
NSNumber *distanceLat = [NSNumber numberWithFloat:([userLatitude floatValue] - [item.latitude floatValue])];
This:
NSNumber *distanceLat = userLatitude - item.latitude;
needs to be:
NSNumber *distanceLat = #([userLatitude doubleValue] - item.latitude);
If item.latitude is also an NSNumber then you need to call doubleValue on it too.
NSNumber is an object. You can't do math on the object. You need to use doubleValue to get its value and then you need to wrap the result in a new NSNumber instance.
BTW - why bother with NSNumber here? Why not do:
double userLatitude = 43.55;
double distanceLat = userLatitude - item.latitude;
CLLocationCoordinate2D newCoordinate = [newLocation coordinate];
CLLocationCoordinate2D oldCoordinate = [oldLocation coordinate];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
The above one can be used to find distance between two locations

How to implement %0.7f in annotation.coordinate?

I have two strings which hold values say for ex:35.5044752 97.3955550
Let me convert it :
double f1=[la doubleValue];
double f2=[lo doubleValue];
(value of f1 and f2 is dynamic say for example f1= "35.5044752" f2="97.3955550" )
if i want to print it in NSLog i will do as follows :
NSLog(#" %f %f ",f1,f2);
And it returns 35.504475 97.395555
hence i change it as
NSLog(#" %0.7f %0.7f ",f1,f2);
And gets the full values like 35.5044752 97.3955550
Now i need it to use in the Coordinate like below:
annotation.coordinate=CLLocationCoordinate2DMake(coord.longitude, coord.longitude);
My Question is how can i implement %0.7f here like which i made in NSlog ?
so that i should take input fully instead of reducing or altering the value.
make a try like this. Directly pass values to obj center
CLLocationCoordinate2D center;
...
else if ([elementName isEqualToString:#"Lat"]) {
center.latitude = [[attributeDict objectForKey:#"degrees"] doubleValue];
}
else if ([elementName isEqualToString:#"Lon"]) {
center.longitude = [[attributeDict objectForKey:#"degrees"] doubleValue];
}
...
OR
Archived the coordinate in foundLocation:
NSNumber *latitudeObject = [NSNumber numberWithDouble:coord.latitude];
NSNumber *longitudeObject = [NSNumber numberWithDouble:coord.longitude];
NSArray *coordinateArray = [NSArray arrayWithObjects:latitudeObject, longitudeObject, nil];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:coordinateArray]
forKey:WhereamiCoordinatePrefKey];
Unarchived the coordinate in viewDidLoad:
NSArray *coordinateArray = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults]
objectForKey:WhereamiCoordinatePrefKey]];
CLLocationCoordinate2D savedCoordinate = CLLocationCoordinate2DMake([[coordinateArray objectAtIndex:0] doubleValue],
[[coordinateArray objectAtIndex:1] doubleValue]);
MKCoordinateRegion savedRegion = MKCoordinateRegionMakeWithDistance(savedCoordinate, 250, 250);
[worldView setRegion:savedRegion animated:YES];
The %0.7f format specifier deals with how your value is displayed, not with how it is stored. A double is always double and has its inherent precision and nothing you can do, short of casting it to another data type, will change that.
As far as I know, the double data type offers the highest floating point precision of the standard data types. If you need greater precision than that, you're going to have to use something other than a double.
In other words, when you perform an operation on a double, it is always calculated to the full precision allowed by the double data type.
For more information on the subject, see the Wikipedia entry on floating point data types.

Google Maps iOS SDK: optimizing finding a random street view

This code finds a random location on Google Street Map according to the bounding box of a country´s latitude/longitude. But it is still even with the bounding box way to slow - it can take up to a minute for a steet view photo to be found. What can I do to make this faster?
The delegated method from GMSPanoramaView checks if there was a valid panorama photo at the random position. if not tells to find a search for a new one.
// Delegate method of GMSPanoramaView that get´s called when didMoveToPanorama: is called
- (void)panoramaView:(GMSPanoramaView *)view didMoveToPanorama:(GMSPanorama *)panorama
nearCoordinate:(CLLocationCoordinate2D)coordinate
{
if (!panorama)
{
[self shuffleLocation];
}
}
- (void)shuffleLocation
{
CLLocationCoordinate2D newLocation = [self randomLatitudeLongitude];
[self.panoView moveNearCoordinate:newLocation];
}
(CLLocationCoordinate2D) randomLatitudeLongitude
{
CountryBBVal auBB = [[GGData SharedInstance] boundingBoxForCountry:Australia];
double ranLongitude = [self randomDoubleBetween: auBB.NELng and: auBB.SWLng]; // Boundix Box
double ranLatitude = [self randomDoubleBetween: auBB.NELat and: auBB.SWLat];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:4];
[formatter setDecimalSeparator:#"."];
NSString *formattedNumberLng = [formatter stringFromNumber:#(ranLongitude)];
NSString *formattedNumberLat = [formatter stringFromNumber:#(ranLatitude)];
CLLocationCoordinate2D ranLatLng = CLLocationCoordinate2DMake([formattedNumberLat doubleValue], [formattedNumberLng doubleValue]);
//NSLog(#"ranLatLng: [%f] [%f]", ranLatLng.latitude, ranLatLng.longitude);
return ranLatLng;
}
What you have is a non-deterministic way of finding a photo so you cannot control how long it takes. What you have coded is optimal and there is no performance improvement in code. Only your algorithm to do so is not optimal and you need to think of a better strategy to get to a random photo.

DistanceFromLocation Error

CLLocation *useOne = [[CLLocation alloc] initWithLatitude:40.074744 longitude:116.240179];
CLLocation *useTwo = [[CLLocation alloc] initWithLatitude:40.079106 longitude:116.243469];
CLLocationDistance distance = [useOne distanceFromLocation:useTwo];
NSLog(#"%d",distance);
But I got the result is "distance=1921570242" metres. absolutely this result was incorrect.
So where am I wrong?
Your calculations are correct, but the way you print is wrong. CLLocationDistance is a double, so format specifier in NSLog should be %f (%d is used for integers):
NSLog(#"%f",distance);

Resources