views:

55

answers:

1

Hi! I'm working on the iPad app, In which I have to rotate a arrow in a circle by touch. But I'm facing problems in it. The problem is in the angle calculation to which the image must be rotate.

You can check it here . I have to rotate the big red arrow image around the circle. Can anybody help me, How to get the angle of the touched point. Currently I'm using the following code, I found it at somewhere in the net. But it didn't rotate the arrow to the touched place.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *oneTouch = [touches anyObject];
    CGPoint currentPoint = [oneTouch locationInView:imgCompass];    

    double current_angle = [self wheelAngleFromPoint:currentPoint]; 
    imgNeedle.transform = CGAffineTransformMakeRotation( current_angle );
}

- (double) wheelAngleFromPoint:(CGPoint)location
{
    double retAngle;

    // subtract center of wheel 

    location.x -= (self.imgNeedle.bounds.size.width ) / 2.0;
    location.y = (self.imgNeedle.bounds.size.height )  / 2.0 - location.y;


    // normalize vector
    double vector_length = sqrt(location.x*location.x + location.y*location.y);

    location.x = location.x/vector_length;
    location.y = location.y/vector_length;

    retAngle = acos(location.y);

    float offset = 0.28;
    //if (location.x)
    //  offset = 0.28;
    retAngle += offset;


    if (location.x<0)
    {
        retAngle = -retAngle;
    }

    return retAngle;
}

Can anyone help me in correct angle calculation.

Thanks

A: 

Here's the problem:

location.x -= (self.imgNeedle.bounds.size.width ) / 2.0;
location.y = (self.imgNeedle.bounds.size.height )  / 2.0 - location.y;

The values in location.x and location.y after the calculation should represent a vector from the centre of the imgNeedle (or wheel?) to the touch point. try this instead:

location.x = location.x - self.imgNeedle.center.x;
location.y = self.imgNeedle.center.y - location.y;

Note that since you are setting the imgNeedle.transform property, the frame will be invalid, but the center will be ok :) - the imgNeedle will rotate about the center of the image.

Notice that I explicitly stated location.x - self.imgNeedle.center.x to help you understand what's going on - you need to calculate the difference between the two points (a vector between them). You should understand that in mathematics, (0, 0) being the origin, the x-axis is positive to the right and the y-axis is positive upwards. However, on your device's screen, the co-ordinate system you are using (view co-ordinates) (0, 0) is at the top left with the x-axis going positive to the right but the y-axis going positive downwards (this isn't always true, because you can map your screen co-ordinates a number of ways). That is why the location.y subtraction is the other way around from the location.x subtraction - to account for the screen being "flipped" vertically (in terms of mathematically calculating the angle). It's also good to know that in mathematics, a positive rotation represents a rotation in the anti-clockwise direction, and a flip on one axis can hide this and make it appear that a positive angle means a clockwise rotation (like a double negative making a positive), so when you're playing with rotations and vectors, you should take all of this into account. However, for your purposes, it's quite simple, so instead of trying to wrap your head around all the maths you may just prefer to play with the code using trial and error, you might need to flip one of the directions (change the order of subtraction) or even change the direction of rotation (do 2*M_PI - retAngle for example).

jhabbott