Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Track touch points in Multitouch

I am working on a drawing project, I want to support multitouch, I have gone through documentation online, which suggest to track the touch points, I did it , But I am not getting the desired behaviour. I am not getting straight lines.

Below is my code

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    red = 0.0/255.0;
    green = 0.0/255.0;
    blue = 0.0/255.0;
    brush = 10.0;
    opacity = 1.0;

     self.view.multipleTouchEnabled = YES;

     touchPaths = [NSMutableDictionary dictionary];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {


    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];
        lastPoint = [touch locationInView:self.view];

        [touchPaths setObject:[NSValue valueWithCGPoint:lastPoint] forKey:key];
    }

}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];

        lastPoint = [[touchPaths objectForKey:key] CGPointValue];


        CGPoint currentPoint1 = [touch locationInView:self.view];

        UIGraphicsBeginImageContext(self.view.frame.size);
        [self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint1.x, currentPoint1.y);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

        CGContextStrokePath(UIGraphicsGetCurrentContext());
        self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
        [self.tempDrawImage setAlpha:opacity];
        UIGraphicsEndImageContext();

        lastPoint = currentPoint1;

    }
}

But when I draw using this code, I get this. enter image description here

So friends, please help me out, what I am doing wrong.

Regards Ranjit

like image 221
Ranjit Avatar asked Dec 24 '13 13:12

Ranjit


2 Answers

You are not populating the touchPaths properly. Try setting it after each drawing instead, something like this:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];

        CGPoint lastPoint = [[touchPaths objectForKey:key] CGPointValue];


        CGPoint currentPoint1 = [touch locationInView:self.view];

        UIGraphicsBeginImageContext(self.view.frame.size);
        [self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint1.x, currentPoint1.y);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

        CGContextStrokePath(UIGraphicsGetCurrentContext());
        self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
        [self.tempDrawImage setAlpha:opacity];
        UIGraphicsEndImageContext();
        // I changed your code here
        [touchPaths setObject:[NSValue valueWithCGPoint:currentPoint1] forKey:key];

    }
}

You are currently setting lastPoint here but you do not seem to use it (and it would only work with one touch). There is no need to have lastPoint as a field either.

like image 190
Krumelur Avatar answered Sep 30 '22 17:09

Krumelur


I always try to use gesture-recognizers when possible. Here I use the UIPanGestureRecognizer:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)]];
}

- (void)didPan:(UIPanGestureRecognizer*)panGesture {
    for (NSUInteger touchIndex = 0; touchIndex < panGesture.numberOfTouches; touchIndex++) {
        // touchIndex is basically the "source" (the finger) from which the point comes from
        CGPoint p = [panGesture locationOfTouch:touchIndex inView:self.view];
        [self drawAtPoint:p withIndex:touchIndex];
    }
}


- (void)drawAtPoint:(CGPoint)point withIndex:(NSUInteger)index{
    UIView *smallPoint = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, 3, 3)];
    [smallPoint setBackgroundColor:[self colorForIndex:index]];
    [self.view addSubview:smallPoint];
}

- (UIColor*)colorForIndex:(NSUInteger)index {
    switch (index) {
        case 0: return [UIColor redColor];
        case 1: return [UIColor orangeColor];
        case 2: return [UIColor yellowColor];
        case 3: return [UIColor blueColor];
        case 4: return [UIColor greenColor];
    }
    return [UIColor clearColor];
}

I don't draw a bezier path, but if you drop it in an empty ViewController and run it, you will see that when multi-touching the screen, each finger draws a different colour.

So if you take into consideration the touchIndex, basically you can keep track of different paths for different fingers.

Let's say you use two fingers to draw: you will have panGesture.numberOfTouches == 2, and touchIndex 0 will represent the first finger, and touchIndex 1 will represent the second finger. You can accumulate the points in different arrays and add the points to their corresponding path.

like image 45
Ilea Cristian Avatar answered Sep 30 '22 18:09

Ilea Cristian