UITouches 屏幕绘图 检测圆形

该博客介绍了一种在iPhone应用中检测用户是否画出圆形的方法。通过两个测试:判断起点和终点距离以及计算移动弧度,来确认手势是否接近圆形。算法会生成一个无框矩形并计算几何平均值以确定圆心。虽然不是完美的检测系统,但适用于很多应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

检测分两步进行,首先是一个收敛测试,圆的起点和终点一定要非常接近,近到几乎相连。不过这也需要有适当的余地,因为在不提供直接的视觉反馈的情况下,

用户可能画不圆或画过头。这里适用的像素距离是60个像素,大约是视图大小的1/3。

第二个测试检查中心点周围的移动,它合计移动的弧度,在这个正圆中应该等于360度,容许45度范围内的移动。

通过这两个测试之后,算法生成一个无框矩形,并根据原手势上的各点的几何平均值确定矩形中心。该结果被赋给圆形实例变量。

它不是一个完美的检测系统,不过这足以为许多iPhone应用程序提供相当好的圆形检查

代码:


#define POINT(X)    [[self.points objectAtIndex:X] CGPointValue]

//检测圆形

- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event
{
    if (!self.points) return;
    if (self.points.count < 3) return;

    // Test 1: The start and end points must be between 60 pixels of each other
    CGRect tcircle;
    if (distance(POINT(0), POINT(self.points.count - 1)) < 60.0f)
        tcircle = [self centeredRectangle];

    // Test 2: Count the distance traveled in degrees. Must fall within 45 degrees of 2 PI
    CGPoint center = CGPointMake(CGRectGetMidX(tcircle), CGRectGetMidY(tcircle));
    float distance = ABS(acos(dotproduct(centerPoint(POINT(0), center), centerPoint(POINT(1), center))));
    for (int i = 1; i < (self.points.count - 1); i++)
        distance += ABS(acos(dotproduct(centerPoint(POINT(i), center), centerPoint(POINT(i+1), center))));
    if ((ABS(distance - 2 * M_PI) < (M_PI / 4.0f))) circle = tcircle;
    
    [self setNeedsDisplay];
}


// Return distance between two points
float distance (CGPoint p1, CGPoint p2)
{
    float dx = p2.x - p1.x;
    float dy = p2.y - p1.y;
    
    return sqrt(dx*dx + dy*dy);
}

// Calculate and return least bounding rectangle
- (CGRect) centeredRectangle
{
    float x = 0.0f;
    float y = 0.0f;
    for (NSValue *pt in self.points)
    {
        x += [pt CGPointValue].x;
        y += [pt CGPointValue].y;
    }
    
    // Calculate weighted center
    x /= self.points.count;
    y /= self.points.count;
    
    float minx = 9999.0f;
    float maxx = -9999.0f;
    float miny = 9999.0f;
    float maxy = -9999.0f;
    
    for (NSValue *pt in self.points)
    {
        minx = MIN(minx, [pt CGPointValue].x);
        miny = MIN(miny, [pt CGPointValue].y);
        maxx = MAX(maxx, [pt CGPointValue].x);
        maxy = MAX(maxy, [pt CGPointValue].y);
    }
    
    return CGRectMake(minx, miny, (maxx - minx), (maxy - miny));
}

CGPoint centerPoint(CGPoint pt, CGPoint origin)
{
    return CGPointMake(pt.x - origin.x, pt.y - origin.y);
}

float dotproduct (CGPoint v1, CGPoint v2)
{
    float dot = (v1.x * v2.x) + (v1.y * v2.y);
    float a = ABS(sqrt(v1.x * v1.x + v1.y * v1.y));
    float b = ABS(sqrt(v2.x * v2.x + v2.y * v2.y));
    dot /= (a * b);
    
    return dot;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值