getDistanceFrom Vs distanceFromLocation - iphone

I'm having a problem with getDistanceFrom and distanceFromLocation. getDistanceFrom is deprecated iOS 4.1 and distanceFromLocation is not available in 3.1.3, how do I get around this problem.
Has anyone else come across this problem ?
My code at the moment is:
CLLocationDistance kilometers;
if ([currentLocation respondsToSelector: #selector(distanceFromLocation:)])
{
kilometers = [currentLocation distanceFromLocation:previousLocation] / 1000;
}
else
{
//kilometers = [currentLocation getDistanceFrom:previousLocation] / 1000;
kilometers = [currentLocation performSelector: #selector(getDistanceFrom:) withObject: previousLocation] / 1000;
}
Depending on which iOS I compile with I'm getting 'invalid operands to binary' on the lines:
kilometers = [currentLocation distanceFromLocation:previousLocation] / 1000;
kilometers = [currentLocation performSelector: #selector(getDistanceFrom:) withObject: previousLocation] / 1000;
Regards,
Stephen

There's a blog post by Cédric Luthi which has a pretty good solution to this.
In short, you need to enter the following into your main.m and make sure to #import <objc/runtime.h> :
Method getDistanceFrom = class_getInstanceMethod([CLLocation class], #selector(getDistanceFrom:));
class_addMethod([CLLocation class], #selector(distanceFromLocation:), method_getImplementation(getDistanceFrom), method_getTypeEncoding(getDistanceFrom));
You can then use distanceFromLocation: on any OS.

I use my own method. It is MUCH faster and can be used on both iOS 3.x and iOS 4.x.
- (double)distanceFrom:(CLLocationCoordinate2D)locationA to:(CLLocationCoordinate2D)locationB
{
double R = 6368500.0; // in meters
double lat1 = locationA.latitude*M_PI/180.0;
double lon1 = locationA.longitude*M_PI/180.0;
double lat2 = locationB.latitude*M_PI/180.0;
double lon2 = locationB.longitude*M_PI/180.0;
return acos(sin(lat1) * sin(lat2) +
cos(lat1) * cos(lat2) *
cos(lon2 - lon1)) * R;
}

Related

UIAccelerometer distance calculation

I have used the following code to calculate the distance when the device moved from one place to another.Is it correct or not please look at my code.
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
NSDate *now = [NSDate date];
NSTimeInterval intervalDate = [now timeIntervalSinceDate:now_prev];
sx = acceleration.x * kFilteringFactor + sx * (1.0 - kFilteringFactor);
sy = acceleration.y * kFilteringFactor + sy * (1.0 - kFilteringFactor);
sz = acceleration.z * kFilteringFactor + sz * (1.0 - kFilteringFactor);
[xLabel setText:[NSString stringWithFormat:#"%.2f",sx]];
[yLabel setText:[NSString stringWithFormat:#"%.2f",sy]];
[zLabel setText:[NSString stringWithFormat:#"%.2f",sz]];
float aValue = sqrtf(sx*sx+sy*sy+sz*sz);
[gLabel setText:[NSString stringWithFormat:#"%.2f g",aValue]];
velX += (sx * intervalDate);
distX += (velX * intervalDate);
velY += (sy * intervalDate);
distY += (velY * intervalDate);
velZ += (sz * intervalDate);
distZ += (velZ * intervalDate);
float distance = sqrtf(distX*distX+distY*distY+distZ*distZ);
[distanceLabel setText:[NSString stringWithFormat:#"%.2f",distance*0.0006213f]];
now_prev = [now retain];
}
There are a lot of reasons why trying to get distance from accelerator data is going to be terribly inefficient.
In order to keep track of your initial location, you need to continuously integrate all acceleration values into a vector, and preferably at a very high sampling rate (big gaps in your calculations will lead to inaccuracies)
The method itself isn't terribly hard to figure out (or google for that matter) ;
This question explains how to do the maths and pseudocode for such an integration approach

Why does MKMetersBetweenMapPoints give me different results when I swap the parameters?

I'm actually trying to calculate the distance between the max and min point in the x and y coordinates for the MKMapPoints.
For that, I'm doing this (max distance in y axis):
MKMapPoint test1, test2;
double dist;
test1.x = 0.0;
test1.y = 0.0;
test2.x = 0.0;
test2.y = MKMapSizeWorld.height;
dist = MKMetersBetweenMapPoints(test2, test1);
NSLog(#"Distance %f",dist);
I get 18997878.291251 in the console. But when I change the distance calculation to:
dist = MKMetersBetweenMapPoints(test1, test2);
I get 18873651.664238, so I don't understand what's the difference. I don't even know if I'm doing the right thing to get the max values of distance in the x and y axes.
Any help will be appreciated.
I guess it's an algorithm problem. Some kind of approximation that stops when a certain precision is achieved. That's why no commutation there. You can try sample code to get distance between two points on map without using MKMapPoints:
- (float) distanceToLPU {
useDelegate
CLLocationCoordinate2D pointACoordinate = appDelegate.usrLoc;
CLLocation *pointALocation = [[CLLocation alloc] initWithLatitude:pointACoordinate.latitude longitude:pointACoordinate.longitude];
CLLocationCoordinate2D pointBCoordinate;
pointBCoordinate.latitude = [self.latitude doubleValue];
pointBCoordinate.longitude = [self.longitude doubleValue];
CLLocation *pointBLocation = [[CLLocation alloc] initWithLatitude:pointBCoordinate.latitude longitude:pointBCoordinate.longitude];
float distanceMeters = [pointALocation distanceFromLocation:pointBLocation];
[pointALocation release];
[pointBLocation release];
NSString *dist = [NSString stringWithFormat:#" (%.0f м)", distanceMeters];
NSLog(#"Distance to this LPU:%#", dist);
return distanceMeters;
}

How to calculate the distance between two places using Haversine Formula in iPhone?

I want to calculate the distance between two places using Haversine formula. Actually i am having the latitude and longitude values of two places. Now i want to calculate the distance between that places using Haversine formula.
For Eg:
First Place:
"lat" : 12.97159870,
"lng" : -77.59456270
Second Place:
"lat" : 9.915996999999999,
"lng" : -78.1218470
},
Now i want to calculate the distance using Haversine Formula.
Please help me out.
Thanks!
You can use CLLocation class (CoreLocation.framework) method's distanceFromLocation:(CLLocation*)loc;
CLLocation *locA = [[CLLocation alloc] initWithLatitude:lat1 longitude:long1];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:lat2 longitude:long2];
CLLocationDistance distance = [locA distanceFromLocation:locB];
[locA release]; [locB release];
iOS provides standard means to calculate the distance between 2 geographic locations - you need to use CLLocation class for that:
#import <CoreLocation/CoreLocation.h>
CLLocation *loc1 = [[[CLLocation alloc] initWithLatitude:12.97159870 longitude:-77.59456270] autorelease];
CLLocation *loc2 = [[[CLLocation alloc] initWithLatitude: 9.915996 longitude:-78.1218470] autorelease];
double distance = [loc1 distanceFromLocation: loc2];
You'll also need to add CoreLocation.framework to link with your project.
// Copy library to your project https://github.com/heycarsten/haversine-objc. Then you get distance between two location by using
Haversine *hvs = [[Haversine alloc]initWithLat1:Lati1 lon1:Longi1 lat2:Lati2 lon2:Longi2];
// Getting Distance using Math Formula..
double dLat1InRad = DEGREES_TO_RADIANS(Lati1);
double dLong1InRad = DEGREES_TO_RADIANS(Longi1);
double dLat2InRad = DEGREES_TO_RADIANS(Lati2);
double dLong2InRad = DEGREES_TO_RADIANS(Longi2);
double dLongitude = dLong2InRad - dLong1InRad;
double dLatitude = dLat2InRad - dLat1InRad;
double a = pow(sin(dLatitude/2.0), 2)+ cos(dLat1InRad) * cos(dLat2InRad) * pow(sin(dLongitude / 2.0), 2);
double c = 2.0 * asin(sqrt(a));
const double kEarthRadiusKms = 6376.5;
double dDistance = kEarthRadiusKms * c;

Gauge animation on iphone

I'm trying to implement a gauge animation using (+ and - buttons) on iphone, but i have no idea where to start? Any help is really welcome. See the image below (this is what I'm trying to do). Thanks for your help.
Here is some open source code (with an example) that implements the gauge view. You of course would still need to do the buttons yourself, and possible add a different visual style.
http://www.cocoacontrols.com/platforms/ios/controls/meterview
You need to rotate the needle based on the angle... Here is the logic
You can refer my answer here... Rotating a UIImageView around a point over 10 seconds?
fireInterval = 10;
//Adjust starting and ending angle
mStartingAngle = 45;
mEndingAngle = 180;
//Implementation
-(void) startTimer
{
mPreviousTime = [NSDate timeIntervalSinceReferenceDate];
}
In the loop
-(void) updateFunction
{
NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];
//NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
//Mapping values between mStartAngle and mEndAngle
mCurrentAngle = (((timeNow - mPreviousTime) * (mEndingAngle - mStartingAngle)) / (previousTime+fireInterval - mPreviousTime)) + mStartingAngle;
if( mPreviousTime + fireInterval <= timeNow )
{
NSLog(#"10 seconds completed");
mPreviousTime = timeNow;
}
}
And rotate the needle based on mCurrentAngle....

Custom mapping functionality within iPhone App using CoreLocation

I'm developing some custom mapping functionality in my App and have hit a stumbling block.
This map is for a known area (i.e. I know the exact latitude / longitude of top left and bottom right corners) and I have a graphic image of the area, to scale, which I use as the background (I don't want to use an MKMapView for this).
I'm using CoreLocation to provide me with my latitude / longitude and am trying to translate these 'real' coords into a spot on the custom map.
One thing to note is that my custom map (which is displayed in a UIScrollView) is rotated from north by a certain angle (i.e. the top of the custom map does not equate to north), therefore, I need to translate/rotate all coords returned via CoreLocation.
I am using the following code to try and do this:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocation *pTL = [self rotateLocation:self.topLeftCorner
aboutLocation:newLocation];
CLLocation *pBR = [self rotateLocation:self.bottomRightCorner
aboutLocation:newLocation];
double mapCoordX = ((pTL.coordinate.longitude - newLocation.coordinate.longitude) / (pTL.coordinate.longitude - pBR.coordinate.longitude)) * imageWidth;
double mapCoordY = ((pTL.coordinate.latitude - newLocation.coordinate.latitude) / (pTL.coordinate.latitude - pBR.coordinate.latitude)) * imageHeight;
if ((mapCoordX >= -self.beaconImage.frame.size.width && mapCoordX <= imageWidth + self.beaconImage.frame.size.width) && (mapCoordY >= -self.beaconImage.frame.size.height && mapCoordY <= imageHeight + self.beaconImage.frame.size.height)) {
self.beaconImage.center = CGPointMake(mapCoordX, mapCoordY);
self.beaconImage.hidden = NO;
} else {
UIAlertView *av = [[UIAlertView alloc]
initWithTitle:nil
message:#"You're not within the boundaries of the map"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
[av release];
self.beaconImage.hidden = YES;
}
}
- (CLLocation *)rotateLocation:(CLLocation *)rotationLocation aboutLocation:(CLLocation *)baseLocation {
double mapLatitudeOffset = topLeftCorner.coordinate.latitude + bottomRightCorner.coordinate.latitude;
double mapLongitudeOffset = topLeftCorner.coordinate.longitude - bottomRightCorner.coordinate.longitude;
double mapOffsetAngle = 0;
if (mapLongitudeOffset == 0 && mapLatitudeOffset == 0) {
mapOffsetAngle = 0;
} else if (mapLongitudeOffset >= 0) {
mapOffsetAngle = atan2(mapLongitudeOffset, mapLatitudeOffset);
} else {
mapOffsetAngle = -atan2(mapLongitudeOffset, mapLatitudeOffset) + M_PI;
}
double latitudeOffset = (rotationLocation.coordinate.latitude + (baseLocation.coordinate.latitude * -1));
double longitudeOffset = (rotationLocation.coordinate.longitude + (baseLocation.coordinate.longitude * -1));
double radius = sqrt(pow(latitudeOffset, 2) + pow(longitudeOffset, 2));
double theta = 0;
if (longitudeOffset == 0 && latitudeOffset == 0) {
theta = 0;
} else if (longitudeOffset >= 0) {
theta = atan2(longitudeOffset, latitudeOffset);
} else {
theta = -atan2(longitudeOffset, latitudeOffset) + M_PI;
}
double angularOffset = theta + mapOffsetAngle;
double latitudeRotate = radius * sin(angularOffset);
double longitudeRotate = radius * cos(angularOffset);
return [[[CLLocation alloc] initWithLatitude:baseLocation.coordinate.latitude + latitudeRotate longitude:baseLocation.coordinate.longitude + longitudeRotate] autorelease];
}
Unfortunately, the calculated values aren't correct, and so the beacon image I use to indicate my current position is showing in the wrong area of the map.
It seems like a straightforward problem, so what am I doing wrong?