CGAffineTranformRotate atan2不准确 [英] CGAffineTranformRotate atan2 inaccuration

查看:74
本文介绍了CGAffineTranformRotate atan2不准确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在转换视图,并且总是发生一些奇怪的事情,我的意思是我使用以下代码计算角度: angle = atan2f(currentTouchPoint.y-center.y,currentTouchPoint.x-center。 x)-atan2f(previousTouchPoint.y-center.y,previousTouchPoint.x-center.x);

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

视图旋转但不旋转正确地。我的意思是它沿正确的方向旋转,但角度始终不准确,约为+/- 0.05弧度。当我再次点击时,视图会旋转到适当的位置。有没有住所?对我来说,重要的是要使逗号后的角度精确到5个位置。

And the view rotates but not properly. I mean it rotates in proper direction but the angle is always inaccurate about +/- 0.05 radians. And when I tap again, view rotates into proper position. Any adivices? It's important to me to get angle accurate to 5 places after comma.

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 forget to tell you, condition, the difference between points is farther the inaccuration is bigger.

编辑:

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:的实现

This is code which is part of '- touchesEnded: withEvent:' implementation

我正在执行类似于Convert bot中的控件的控制。我的应用程序和convertbot中的​​轮子看起来很相似,但是我使用的是自定义绘图。

I'm making control similar to the one in Convert bot. the "wheels" from my app and from convertbot look similar but mine uses custom drawing.

所以Circle是我们旋转的UIView。 Circle有子视图-CircleThumbs。拇指代表圆的单个线段。积分计算正确,但由于不需要,我不会解释原因。

So Circle is a UIView which we rotate. Circle has got subviews - CircleThumbs. thumb represents single segment of the circle. Points are calculated properly but I won't explain why, because there's no need.

推荐答案

atan计算永远不会完全正确。然后让iOS再次从角度计算cos和sin(cgaffinetransformRotate会这样做)。因此,您堆积了三角误差。而且,由于您仅计算了前一个角度的差,因此我想您还会在多个触摸事件上积累不准确的信息。

An atan calculation is never entirely correct. And you let iOS calculate cos and sin out of the angle again (cgaffinetransformRotate does that). So you're stacking up trigonometric inaccuracies. And since you calculate only the difference wi the previous angle, I imagine that you are also stacking up inaccuracies over the multiple touch events.

如果要旋转某些东西,则没有理由使用三角函数或角度。您可以使用线性代数完全实现这一点。

If it is to rotate something, then there is no reason to use trigonometry or angles. You can implement this completely using linear algebra. Something like this:

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;

此伪代码计算当前点的归一化向量(也存储了前一个点的向量) 。然后,我们定义一个矩阵,将先前的向量旋转为新的向量。该矩阵与现有转换连接在一起。

This pseudo code calculates a normalized vector for current point (the one for the previous point was also stored). Then we define a matrix that rotates the previous vector into the new vector. That matrix is concatenated with the existing transformation.

最好不总是根据前一个状态来计算轮换,而是根据初始状态来计算轮换。诀窍是只为触地得分计算上一个。

It would be better if the rotation wasn't always calculated from the previous state, but rather from an initial state. The trick is to calculate 'previous' only for the touchdown.

这篇关于CGAffineTranformRotate atan2不准确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆