2012-01-07 2 views
4

을 ATAN2, 나는이 코드를 사용하여 각도를 계산 의미 :하지만 제대로 angle = atan2f(currentTouchPoint.y - center.y, currentTouchPoint.x - center.x) - atan2f(previousTouchPoint.y - center.y, previousTouchPoint.x - center.x);CGAffineTranformRotate 내가 내보기의 전환을 항상 뭔가 이상한 일이있어 inaccuration

그리고 뷰가 회전합니다. 적절한 방향으로 회전하지만 각도는 항상 +/- 0.05 라디안에 대해 정확하지 않습니다. 그리고 다시 을 탭하면보기가 적절한 위치으로 회전합니다. 어떤 충고? 쉼표 뒤에 5 자리까지 정확한 각도를 얻는 것이 중요합니다.

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 

그리고 내가 말한 것을 잊지 마세요, 조건, 포인트의 차이는 부정확 한 것이 더 큽니다.

편집 : 이것은의 일부 코드

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

이다 '- touchesEnded : withEvent :'구현 내가 변환 봇에 유사한 컨트롤을 만들고있어

가. 내 애플 리케이션과 convertbot에서 비슷한 "휠"하지만 내 사용자 정의 드로잉을 사용합니다.

그래서 서클은 회전하는 UIView입니다. 서클에 하위보기가 있습니다. CircleThumbs. thumb은 원의 단일 세그먼트를 나타냅니다. 포인트는 적절히 계산되지만 필요가 없기 때문에 이유를 설명하지 않겠습니다.

+0

위의 정보를 인쇄하는 우편 번호를 게시 할 수 있습니까? 첫 번째와 두 번째 탭은 무엇입니까? – alekhine

답변

7

atan 계산이 완전히 올바르지 않습니다. 그리고 iOS가 cos과 sin을 다시 각도에서 계산하도록합니다 (cgaffinetransformRotate가이를 수행합니다). 따라서 삼각법 부정확성이 누적됩니다. 이전 각도와의 차이 만 계산 했으므로 여러 터치 이벤트에 대해 부정확 한 정보가 누적되어 있다고 생각합니다.

무언가를 돌리려면 삼각법이나 각도를 사용할 필요가 없습니다. 선형 대수학을 사용하여 이것을 완벽하게 구현할 수 있습니다. 이런 식으로 뭔가가 :

v.x = touch.x - center.x; v.y = touch.y - center.y; 
float length = sqrt(v.x*v.x + v.y* v.y); 
if (length < 5) break; 
v.x /= length; v.y /= length; 

// the rotation matrix is 
// v.x -v.y 
// v.y v.x 

rot.x = previous.x * v.x + previous.y * v.y; 
rot.y = previous.x * v.y - previous.y * v.x; 

CGAffineTransform rotate = CGAffineTransformMake(rot.x, rot.y, -rot.y, rot.x, 0,0); 
... 
[view SetTransform:CGAffineTransformConcat (current, rotate)]; 
... 

previous.x = v.x; 
previous.y = v.y; 

이 의사 코드는 현재 점에 대한 정규화 된 벡터 (또한 저장된 이전 점의 하나)을 계산합니다. 그런 다음 이전 벡터를 새 벡터로 회전시키는 행렬을 정의합니다. 이 행렬은 기존 변환과 연결됩니다.

회전이 항상 이전 상태에서 계산 된 것이 아니라 초기 상태에서 계산 된 것이 더 좋을 것입니다. 트릭은 터치 다운에 대해서만 '이전'을 계산하는 것입니다.

+0

내 질문을 편집했습니다. – wczekalski