2012-01-07 3 views
4

私は私の見解の変遷を作り、常に奇妙な何か起こるんだ、私はこのコードを使用して角度を計算する意味します。私はそれが正しい方向に回転していることを意味しますが、角度は常に+/- 0.05ラジアンほど不正確です。再度をタップすると、ビューは適切な位置に回転します。どんな忠告?カンマの後に5桁まで正確な角度を取得することが重要です。CGAffineTranformRotate ATAN2 inaccuration

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 

私はあなたに言っておくことを忘れています、条件、ポイント間の違いは、より不正確です。実装

私は変換ボットのものと同様の制御を作ってるんだ - :

EDIT ':withEvent touchesEnded'

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

これはの一部であるコードです。私のアプリとconvertbotの "ホイール"は似ていますが、私のカスタム図面を使用しています。

So Circleは回転するUIViewです。サークルにはサブビューがあります - CircleThumbs。親指は円の単一のセグメントを表します。ポイントは適切に計算されますが、理由は説明しません。なぜなら、必要がないからです。

+0

上記の情報を印刷するポストコードをお願いしますか?最初と2番目のタップは何ですか? – 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

関連する問題