UITouches 屏幕绘图线的计算

通过筛选用户输入创建更适用于应用程序的简单数据集。创建一个最小线段集来匹配自由形态的点。

原理:

一次分析一个由3个点组成的集合。对于每个集合,它将第一个和第三个点围绕第二个点的原点集中,然后计算第一个和第三个点的向量点积。

点积返回的值视两个矢量之间的角度的余弦。如果这些点在一条直线上。即他们之间的角度接近于180度(允许有小误差),则算法会舍弃中间的点。

180度的余弦是-1。该代码舍弃向量夹角余弦小于-0.75的所有点。增加容差能产生更好的结果。但同时可能会忽略用户有意的方向转变。

如果你的目标是检查三角形、正方形和其他简单的多边形。那么这个容差会很可靠。要生成“更漂亮”的线图,则需要适用一个更严格的容差来保留用户提供的细节。


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

//从自由形态的手势创建线段

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


- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event
{
    if (!self.points) return;
    if (self.points.count < 3) return;
    
    // Create the filtered array
    NSMutableArray *newpoints = [NSMutableArray array];
    [newpoints addObject:[self.points objectAtIndex:0]];
    CGPoint p1 = POINT(0);
    
    int i = 1;
    // Add only those points that are inflections
    for ( i;i < (self.points.count - 1); i++)
    {
        CGPoint p2 = POINT(i);
        CGPoint p3 = POINT(i+1);
        
        // Cast vectors around p2 origin
        CGPoint v1 = CGPointMake(p1.x - p2.x, p1.y - p2.y);
        CGPoint v2 = CGPointMake(p3.x - p2.x, p3.y - p2.y);
        float dot = dotproduct(v1, v2);

        // Colinear items need to be as close as possible to 180 degrees
        if (dot < -0.75f) continue;
        p1 = p2;
        [newpoints addObject:[self.points objectAtIndex:i]];
    }
    
    // Add final point
    if ([newpoints lastObject] != [self.points lastObject]) [newpoints addObject:[self.points lastObject]];
    
    // Report initial and final point counts
    NSLog(@"%@", [NSString stringWithFormat:@"%d points to %d points", self.points.count, newpoints.count]);
    
    // Update with the filtered points and draw
    self.points = newpoints;
    [self setNeedsDisplay];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值