更精确的CGL for UILongPressGestureRecognizer

时间:2013-12-13 08:46:59

标签: objective-c cocoa-touch uigesturerecognizer cgpoint

我正在使用UILongPressGestureRecognizer,它可以很好地工作,但是我获得的数据对于我的用例来说不够精确。我认为,我得到的CGPoints已经四舍五入。

我得到的示例点:100.5,103.0等。小数部分是.5或.0。有没有办法获得更精确的分数?我希望像'100.8745'这样的.xxxx之类的东西,但.xx会这样做。

编辑: 我需要这个的原因是因为我有一个圆形UIBezierPath,我想将拖动手势限制为只有那个圆形路径。该项目只能沿此圆圈的圆周拖动。为此,我使用它的半径在圆的边界上计算了720个点。现在这些点是.xxxx数字。如果我将它们四舍五入,那么在圆的中间部分周围的阻力就不那么平滑了。这是因为在中间部分,赤道,x坐标上的点非常接近。因此,当我舍入y坐标时,我失去了很多分数,因此“不那么平滑”的拖动动作。

以下是我计算点数的方法

for (CGFloat i = -154;i<154;i++) {

    CGPoint point = [self pointAroundCircumferenceFromCenter:center forX:i];
    [bezierPoints addObject:[NSValue valueWithCGPoint:point]];
    i = i - .5;
}

- (CGPoint)pointAroundCircumferenceFromCenter:(CGPoint)center forX:(CGFloat)x
{
CGFloat radius = 154;
CGPoint upperPoint = CGPointZero;
CGPoint lowerPoint = CGPointZero;

//theta used to be the x variable. was first calculating points using the angle
/* point.x = center.x + radius * cosf(theta);
point.y = center.y + radius * sinf(theta);*/

CGFloat y = (radius*radius) - (theta*theta);
upperPoint.x = x+156;
upperPoint.y = 230-sqrtf(y);
lowerPoint.x = x+156;
lowerPoint.y = sqrtf(y)+230;

NSLog(@"x = %f, y = %f",upperPoint.x, upperPoint.y);
[lowerPoints addObject:[NSValue valueWithCGPoint:lowerPoint]];
[upperPoints addObject:[NSValue valueWithCGPoint:upperPoint]];
return upperPoint;
}

我知道代码很奇怪我的意思是为什么我会将这些点添加到数组中并返回一个点。请和我一起露面,我只是想让它现在起作用。

以下是限制运动的方法

-(void)handleLongPress:(UILongPressGestureRecognizer *)recognizer{
    CGPoint finalpoint;
    CGPoint initialpoint;
    CGFloat y;
    CGFloat x;
    CGPoint tempPoint;
    if(recognizer.state == UIGestureRecognizerStateBegan){
        initialpoint = [recognizer locationInView:self.view];
        CGRect rect = CGRectMake(initialpoint.x, initialpoint.y, 40, 40);
        self.hourHand.frame = rect;
        self.hourHand.center = initialpoint;
        NSLog(@"Long Press Activated at %f,%f",initialpoint.x, initialpoint.y );
    }
    else if (recognizer.state == UIGestureRecognizerStateChanged){
        CGPoint currentPoint = [recognizer locationInView:self.view];
        x = currentPoint.x-initialpoint.x;
        y = currentPoint.y-initialpoint.y;
        tempPoint = CGPointMake( currentPoint.x,  currentPoint.y);
        NSLog(@"temp point ::%f, %f", tempPoint.x, tempPoint.y);
        tempPoint = [self givePointOnCircleForPoint:tempPoint];
        self.hourHand.center = tempPoint;
     }
    else if (recognizer.state == UIGestureRecognizerStateEnded){
    //   finalpoint = [recognizer locationInView:self.view];
        CGRect rect = CGRectMake(tempPoint.x, tempPoint.y, 20, 20);
        self.hourHand.frame = rect;
        self.hourHand.center = tempPoint;
        NSLog(@"Long Press DeActivated at %f,%f",tempPoint.x, tempPoint.y );
    }
}

-(CGPoint)givePointOnCircleForPoint:(CGPoint) point{
CGPoint resultingPoint;
for (NSValue *pointValue in allPoints){
    CGPoint pointFromArray = [pointValue CGPointValue];
    if (point.x == pointFromArray.x) {
       // if(point.y > 230.0){
            resultingPoint = pointFromArray;
            break;
       // }
    }
}

基本上,我采用“触摸点”的x坐标,并通过将其与我先前计算的点数组进行比较来返回y。

目前这段代码仅适用于半圈,因为每个x都有2个y值,因为它是一个圆圈,忽略这个因为我觉得这很容易处理。

在图片中,白色圆圈是原始圆圈,黑色圆圈是我从代码中得到的点的圆圈+格式化它以移除精度以适合我得到的输入。如果你环顾赤道(红色突出部分),你会看到下一个点之间的差距。这个差距是我的问题。

1 个答案:

答案 0 :(得分:2)

回答您的原始问题:在具有Retina显示屏的设备上,一个像素为0.5个点,因此0.5是您可以在此硬件上获得的最佳分辨率。 (在非Retina设备上,1个像素== 1个点。)

但在我看来,你根本不需要那个点数组。如果正确理解问题,可以使用以下代码 “限制”(或“投射”)任意点到圆周:

CGPoint center = ...; // Center of the circle
CGFloat radius = ...; // Radius of the circle
CGPoint point = ...;  // The touched point
CGPoint resultingPoint; // Resulting point on the circumference

// Distance from center to point:
CGFloat dist = hypot(point.x - center.x, point.y - center.y);
if (dist == 0) {
    // The touched point is the circle center.
    // Choose any point on the circumference:
    resultingPoint = CGPointMake(center.x + radius, center.y);
} else {
    // Project point to circle circumference:
    resultingPoint = CGPointMake(center.x + (point.x - center.x)*radius/dist,
                     center.y + (point.y - center.y)*radius/dist);
}