CGAffineTranformRotate atan2 inactivation

I make the transition of my view and something strange always happens, I mean, I calculate the angle using this code: angle = atan2f(currentTouchPoint.y - center.y, currentTouchPoint.x - center.x) - atan2f(previousTouchPoint.y - center.y, previousTouchPoint.x - center.x);

And the view rotates, but not right. I mean, it rotates in the right direction, but the angle is always inaccurate with respect to +/- 0.05 radians. And when I click again, the view rotates to the correct position . Any adekings? It is very important for me to get an angle with an accuracy of 5 decimal places.

 Some NSLog to show you the problem: First rotation first tap and second tap 2012-01-07 01:01:26.283 Wheel[9080:707] Angle: 0.598412 2012-01-07 01:01:29.281 Wheel[9080:707] Angle: -0.070008 Second rotation first tap and second tap 2012-01-07 01:01:31.103 Wheel[9080:707] Angle: -0.679809 2012-01-07 01:01:32.450 Wheel[9080:707] Angle: 0.092595 Third rotation first tap and second tap 2012-01-07 01:01:35.745 Wheel[9080:707] Angle: 0.607844 2012-01-07 01:01:36.945 Wheel[9080:707] Angle: -0.064927 Fourth rotation first tap and second tap 2012-01-07 01:01:41.073 Wheel[9080:707] Angle: -0.635756 2012-01-07 01:01:41.920 Wheel[9080:707] Angle: 0.052361 

And I forgot to tell you that the state, the difference between the points is farther than the deeper occurs.

EDIT:

 Circle *view = (Circle *) [self view]; for (CircleThumb *thumb in view.subviews) { CGPoint point = [thumb convertPoint:thumb.centerPoint toView:nil]; CircleThumb *shadow = [[view.overlayView subviews] lastObject]; CGPoint centralPoint = [shadow convertPoint:shadow.centerPoint toView:nil]; CGRect shadowRect = [shadow.superview convertRect:shadow.frame toView:nil]; if (CGRectContainsPoint(shadowRect, point) == YES) { CGPoint pointInShadowRect = [thumb convertPoint:thumb.centerPoint toView:shadow]; if (CGPathContainsPoint(shadow.arc.CGPath, NULL, pointInShadowRect, NULL)) { CGAffineTransform current = view.transform; CGPoint center = view.window.center; CGPoint currentTouchPoint =centralPoint; CGPoint previousTouchPoint = point; long double angle = atan2f(currentTouchPoint.y - center.y, currentTouchPoint.x - center.x) - atan2f(previousTouchPoint.y - center.y, previousTouchPoint.x - center.x); [UIView animateWithDuration:0.3f animations:^{ [view setTransform:CGAffineTransformRotate(current, angle)]; }]; [view.delegate circle:view didMoveToSegment:thumb.tag thumb:thumb]; NSLog(@"Angle: %Lf ", angle); break; } } } 

This is the code that is part of '- touchesEnded: withEvent:' implementation

I am making the control the same as in the Convert bot. The wheels from my application and from the converter are similar, but mine uses a custom drawing.

So the circle is the UIView that we rotate. The circle has a subspecies - CircleThumbs. thumb represents one segment of a circle. The points are calculated correctly, but I will not explain why, because there is no need.

+4
source share
1 answer

The calculation of atan is never completely correct. And you let iOS calculate cos and sin again out of the corner (cgaffinetransformRotate does this). Thus, you put trigonometric inaccuracies. And since you only calculate the difference from the previous angle, I believe that you are also incompatible with inaccuracies in multi-touch events.

If you need to rotate something, then there is no reason to use trigonometry or angles. You can fully realize this with linear algebra. Something like that:

 vx = touch.x - center.x; vy = touch.y - center.y; float length = sqrt(vx*vx + vy* vy); if (length < 5 ) break; vx /= length; vy /= length; // the rotation matrix is // vx -vy // vy vx rot.x = previous.x * vx + previous.y * vy; rot.y = previous.x * vy - previous.y * vx; CGAffineTransform rotate = CGAffineTransformMake( rot.x, rot.y, -rot.y, rot.x, 0,0); ... [view SetTransform:CGAffineTransformConcat ( current, rotate )]; ... previous.x = vx; previous.y = vy; 

This pseudo-code calculates the normalized vector for the current point (the same as for the previous point was also saved). Then we define a matrix that rotates the previous vector into a new vector. This matrix is ​​combined with the existing transformation.

It would be better if the rotation was not always calculated from the previous state, but rather from the initial state. The trick is to calculate the "previous" just for landing.

+7
source

Source: https://habr.com/ru/post/1389754/


All Articles