Get iPads direction (N, E, S, W) [duplicate] - ios

This question already has answers here:
iPhone - CLHeading to find direction
(2 answers)
Closed 6 years ago.
Is it possible to get the current iPads direction like North, East, South, or West for example by CLLocationManager?

This is for rotating pin in which direction its move
so might be it will helpful for you and by pin angle you will get ipad direction.
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
// Use the true heading if it is valid.
CLLocationDirection direction = newHeading.magneticHeading;
CGFloat radians = -direction / 180.0 * M_PI;
self.strAccuracy = [NSString stringWithFormat:#"%.1fmi",newHeading.headingAccuracy];
[lblAccuracy setText:self.strAccuracy];
//Rotate Bearing View
[self rotateBearingView:bearingView radians:radians];
//For Rotate Niddle
CGFloat angle = RadiansToDegrees(radians);
[self setLatLonForDistanceAndAngle];
[self rotateArrowView:arrowView degrees:(angle + fltAngle)];
}
-(void)rotateArrowView:(UIView *)view degrees:(CGFloat)degrees
{
CGAffineTransform transform = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
view.transform = transform;
}
-(void)setLatLonForDistanceAndAngle
{
dblLat1 = DegreesToRadians(appDelegate.dblLatitude);
dblLon1 = DegreesToRadians(appDelegate.dblLongitude);
dblLat2 = DegreesToRadians(objClsProductSearch.dblLatitude);
dblLon2 = DegreesToRadians(objClsProductSearch.dblLongitude);
fltLat = dblLat2 - dblLat1;
fltLon = dblLon2 - dblLon1;
}
-(float)getAngleFromLatLon
{
//Calculate angle between two points taken from http://www.movable-type.co.uk/scripts /latlong.html
double y = sin(fltLon) * cos(dblLat2);
double x = cos(dblLat1) * sin(dblLat2) - sin(dblLat1) * cos(dblLat2) * cos(dblLon2);
CGFloat angle = RadiansToDegrees(atan2(y, x));
return angle;
}

Related

Rotating UIView (Again)

I'm encountering some problems with rotating a uiview again. This time, im trying to rotate a uiview 1/12 the speed of another uiview I'm rotating at normal speed. However, when I try to accomplish this task, the uiview I'm trying to move slower moves like this:
1st Update
https://www.youtube.com/watch?v=wj3nRJo5CMM&feature=youtu.be
2nd Update
https://www.youtube.com/watch?v=YLRkUzXSDtQ&feature=youtu.be
Here's my code:
- (void)rotateHand:(UIPanGestureRecognizer *)panGesture {
if ([(UIPanGestureRecognizer*)panGesture state] == UIGestureRecognizerStateBegan) {
CGPoint touchPoint = [panGesture locationInView:[self view]];
float dx = touchPoint.x - minHandContainer.center.x;
float dy = touchPoint.y - minHandContainer.center.y;
arcTanMin = atan2(dy,dx);
arcTanHour = atan2(hourHand.center.x - minHandContainer.center.x, hourHand.center.y - minHandContainer.center.y);
if (arcTanMin < 0) {
arcTanMin = 2 * M_PI + arcTanMin;
}
if (arcTanHour < 0) {
arcTanHour = 2 * M_PI + arcTanMin;
}
NSLog(#"arcTanMin %f", arcTanMin);
startTransformMin = minHandContainer.transform;
startTransformHour = hourHandContainer.transform;
}
if ([(UIPanGestureRecognizer*)panGesture state] == UIGestureRecognizerStateChanged) {
CGPoint pt = [panGesture locationInView:[self view]];
float dx = pt.x - minHandContainer.center.x;
float dy = pt.y - minHandContainer.center.y;
float ang = atan2(dy,dx);
if (ang < 0) {
ang = 2 * M_PI + ang;
}
float angleDifferenceM = arcTanMin - ang;
float angleDifferenceH = arcTanHour + angleDifferenceM * (1.0/12.0);
NSLog(#"angleDiffM %f", angleDifferenceM);
NSLog(#"angleDiffH %f", angleDifferenceH);
minHandContainer.transform = CGAffineTransformRotate(startTransformMin, -angleDifferenceM);
hourHandContainer.transform = CGAffineTransformRotate(startTransformHour, -angleDifferenceH);
}
}
It appears that you're using arcTanMin as the starting reference angle for both the minute hand and hour hand. So when you make the jump across the x-axis, both angleDifferenceM and angleDifferenceH are making the jump (which is why at the moment of the jump the angle of the hour hand to the y-axis is the same as the angle of the minute hand to the x-axis), but angleDifferenceH doesn't need to make the jump. Change this:
float angleDifferenceH = angleDifferenceM * (1.0/12.0);
to
float angleDifferenceH = arcTanHour + angleDifferenceM * (1.0/12.0);
with an appropriate starting value for arcTanHour.

How to I rotate a UIView a fix +/- angle?

I want to use a UISlider to rotate +/- angles from 0 to 180 degrees (pi).
My problem is that the rectangle rotates either before 0 or beyond 180.
What I need is to essentially map to relative UISlider button position with the angle.
Here's the code, with the UIView.layer's anchor at one end (as in a dial):
- (IBAction)sliderAction:(UISlider *)sender {
static float datum = 0;
if (sender.value > 0 && sender.value < 10) {
float myValue = 0;
if (datum < sender.value) {
myValue = +0.1;
} else {
myValue = -0.1;
}
_gageStickView.transform = CGAffineTransformRotate(_gageStickView.transform, myValue);
datum = sender.value;
}
This rotates it, but I don't have adequate control over it.
Question: How can I map the the UISlider's position with the angle of the UIView?
That is, left-slider at 0 deg., mid-sider at 90deg and right-slider at 180 degs; and in-between.
Like #Larme says, you need to convert degrees to radians.
- (IBAction)sliderValueChanged:(UISlider *)sender {
CGFloat degrees = (sender.value / sender.maximumValue) * 180;
CGFloat radians = degrees * M_PI / 180;
self.label.transform = CGAffineTransformMakeRotation(radians);
}
This code isn't hardwired to a value of 10, but just get's the 'percentage', based on the maximum value of the slider.

Arrow to point particular location in iPad

I have to point the arrow to particular location based on the current location. For that I am using didUpdateHeading delegate method for getting the true heading value.
In iPhone( Portrait mode) the arrow image is showing perfectly. But in iPad its not showing correctly. It is in Landscape mode.
The code I am using to find the bearing distance is,
- (void)UpdateCompass:(NSNotification *)notification
{
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:m_nLatitude longitude:m_nLongitude];
CLLocation* target = [[CLLocation alloc] initWithLatitude:questionLatitude longitude:questionLangitude ];
_latestBearing = [self getHeadingForDirectionFromCoordinate:newLocation.coordinate toCoordinate:target.coordinate];
CGFloat degrees = _latestBearing - m_CLHeading.magneticHeading;
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation([self degreesToRadians:degrees]);
m_arrowImage.transform = cgaRotate;
}
- (double)degreesToRadians:(double)degrees
{
return degrees * M_PI / 180.0;
}
- (double)radiansToDegrees:(double)radians
{
return radians * 180.0/M_PI;
}
- (double)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
double lat1 = [self degreesToRadians:fromLoc.latitude];
double lon1 = [self degreesToRadians:fromLoc.longitude];
double lat2 = [self degreesToRadians:toLoc.latitude];
double lon2 = [self degreesToRadians:toLoc.longitude];
double dLon = lon2 - lon1;
double y = sin(dLon) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
double radiansBearing = atan2(y, x);
if(radiansBearing < 0.0)
radiansBearing += 2*M_PI;
return [self radiansToDegrees:radiansBearing];
}
How can I make this work for iPad?
Check whether device is ipad or iphone and write your code accordingly
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// The device is an iPad running iPhone 3.2 or later.
}
else
{
// The device is an iPhone or iPod touch.
}

iOS using accelerometer to move an object within a circle

I am trying use the accelerometer to move an image within a circle. I am having issue that when the image hits the edge of the circle, it just moves the other side of the circle. My code is below:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
//NSLog(#"x : %g", acceleration.x);
//NSLog(#"y : %g", acceleration.y);
//NSLog(#"z : %g", acceleration.z);
delta.x = acceleration.x * 10;
delta.y = acceleration.y * 10;
joypadCap.center = CGPointMake(joypadCap.center.x + delta.x, joypadCap.center.y - delta.y);
distance = sqrtf(((joypadCap.center.x - 160) * (joypadCap.center.x - 160)) +
((joypadCap.center.y -206) * (joypadCap.center.y - 206)));
//NSLog(#"Distance : %f", distance);
touchAngle = atan2(joypadCap.center.y, joypadCap.center.x);
NSLog(#"Angle : %f", touchAngle);
if (distance > 50) {
joypadCap.center = CGPointMake(160 - cosf(touchAngle) * 50, 206 - sinf(touchAngle) * 50);
}
I was having the same issue when attempting to implement a circular spirit level using CMDeviceMotion. I found it was an issue with the coordinates passed to atan2(y,x). This function requires cartesian coordinates, with (0,0) in the centre of the view. However, the screen coordinates have (0,0) in the top left corner. I created methods to convert a point between the two coordinate systems, and now it's working well.
I put up a sample project here on github, but here's the most important part:
float distance = sqrtf(((point.x - halfOfWidth) * (point.x - halfOfWidth)) +
((point.y - halfOfWidth) * (point.y - halfOfWidth)));
if (distance > maxDistance)
{
// Convert point from screen coordinate system to cartesian coordinate system,
// with (0,0) located in the centre of the view
CGPoint pointInCartesianCoordSystem = [self convertScreenPointToCartesianCoordSystem:point
inFrame:self.view.frame];
// Calculate angle of point in radians from centre of the view
CGFloat angle = atan2(pointInCartesianCoordSystem.y, pointInCartesianCoordSystem.x);
// Get new point on the edge of the circle
point = CGPointMake(cos(angle) * maxDistance, sinf(angle) * maxDistance);
// Convert back to screen coordinate system
point = [self convertCartesianPointToScreenCoordSystem:point inFrame:self.view.frame];
}
And:
- (CGPoint)convertScreenPointToCartesianCoordSystem:(CGPoint)point
inFrame:(CGRect)frame
{
float x = point.x - (frame.size.width / 2.0f);
float y = (point.y - (frame.size.height / 2.0f)) * -1.0f;
return CGPointMake(x, y);
}
- (CGPoint)convertCartesianPointToScreenCoordSystem:(CGPoint)point
inFrame:(CGRect)frame
{
float x = point.x + (frame.size.width / 2.0f);
float y = (point.y * -1.0f) + (frame.size.height / 2.0f);
return CGPointMake(x, y);
}

How to keep rollingY consistent when user flips over iDevice while in landscape mode?

In my app, I'm the game is set for landscape mode allowing the user to be able to flip the device with the game auto-rotating to match the angle. When the user tilts the device to its right, the hero will travel to the right, and when tilted to the left, the hero goes left.
I have that part figured out, but the problem comes in when the user flips the iDevice over (because of the headphone jack or placement of the speaker), the app is auto-rotated, but the rollingY is setting the hero's position.x to be inverted. Tilting left makes hero go right, and tilting right makes hero go left. After looking at the NSLogs of the accelY value when flipping around the iDevice, it doesn't seem possible to be able to reverse the position.x when rotated?
I guess this is more of a math question.
Here is my code:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
#define kFilteringFactor 0.75
static UIAccelerationValue rollingX = 0, rollingY = 0, rollingZ = 0;
rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
float accelX = rollingX;
float accelY = rollingY;
float accelZ = rollingZ;
NSLog(#"accelX: %f, accelY: %f, accelZ: %f", accelX, accelY, accelZ);
CGSize winSize = [CCDirector sharedDirector].winSize;
#define kRestAccelX 0.6
#define kShipxMaxPointsPerSec (winSize.height * 1.0)
#define kMaxDiffX 0.2
#define kRestAccelY 0.0
#define kShipyMaxPointsPerSec (winSize.width * 0.5)
#define kMaxDiffY 0.2
float accelDiffX = kRestAccelX - ABS(accelX);
float accelFractionX = accelDiffX / kMaxDiffX;
float pointsPerSecX = kShipxMaxPointsPerSec * accelFractionX;
float accelDiffY = -accelY;
float accelFractionY = accelDiffY / kMaxDiffY;
float pointsPerSecY = kShipyMaxPointsPerSec * accelFractionY;
_shipPointsPerSecX = pointsPerSecY;
_shipPointsPerSecY = pointsPerSecX;
CCLOG(#"accelX: %f, pointsPerSecX: %f", accelX, pointsPerSecX);
CCLOG(#"accelY: %f, pointsPerSecY: %f", accelY, pointsPerSecY);
}
-(void)updateShipPos:(ccTime)dt
{
CGSize winSize = [CCDirector sharedDirector].winSize;
float maxX = winSize.width - _ship.contentSize.width;
float minX = _ship.contentSize.width / 2;
float maxY = winSize.height - _ship.contentSize.height / 2;
float minY = _ship.contentSize.height / 2;
float newX = _ship.position.x + (_shipPointsPerSecX * dt);
float newY = _ship.position.y + (_shipPointsPerSecY * dt);
newX = MIN(MAX(newX, minX), maxX);
newY = MIN(MAX(newY, minY), maxY);
_ship.position = ccp(newX, newY);
}
The idea is, I'm trying to make it so that pointsPerSecY is positive when tilting to the right and negative when tilted to the left. The problem is when the user flips the device, they are inverted since the device is flipped. Is there a way to make it so that it will stay positive when tilted to the right and negative to the left, no matter the orientation, when flipped while being in landscape?
How about to do something like this?
if ([[UIApplication sharedApplication] statusBarOrientaion]==UIInterfaceOrientationLandscapeLeft) {
pointsPerSecY *= -1;
}

Resources