Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multitouch tracking issue

I am working with multitouch while writing, So basically what I am doing is, I am writing with hand support, because typically, its how user rights, I followed this link How to ignore certain UITouch Points in multitouch sequence

So, what I am doing is , I am tracking a touch Object in touchesBegan and using that only in touchesMoved.Everything works fine, but some times while writing, I get this line

enter image description here

In the above image, you can see the thick line which suddenly comes while writing with my hand touched on the screen

Here is the code

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touches began");   

    UITouch* topmostTouch = self.trackingTouch;
    for (UITouch *touch in touches)
    {
        bufIdx = 0;
        isFirstTouchPoint = YES;
        ctr = 0;

        pts[0] = [touch locationInView:self];


        if(!topmostTouch || [topmostTouch locationInView:self].y > pts[0].y)
        {
            topmostTouch = touch;
            //touchStartPoint1 = pts[0];
        }
        else
        {
            pts[0] = pts[3];
        }
    }

   if (self.trackingTouch != nil && self.trackingTouch != topmostTouch) 
   {
     [self discardDrawing];        
   }

    self.trackingTouch = topmostTouch;
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{    
        // Find the touch that we track for drawing

            CGPoint p = [self.trackingTouch locationInView:self];
            ctr++;
            pts[ctr] = p;

            if (ctr == 4)
            {
                pts[3] = midPoint(pts[2], pts[4]);

                for ( int i = 0; i < 4; i++)
                {
                    pointsBuffer[bufIdx + i] = pts[i];
                }

                bufIdx += 4;

                dispatch_async(drawingQueue, ^{
                    //UIBezierPath *offsetPath = [UIBezierPath bezierPath]; // ................. (2)

                    self.currentPath = [[DrawingPath alloc] init];                   
                    [self.currentPath setPathColor:self.lineColor];


                    if (bufIdx == 0) return;

                    LineSegment ls[4];
                    for ( int i = 0; i < bufIdx; i += 4)
                    {
                        if (isFirstTouchPoint) // ................. (3)
                        {                           
                            ls[0] = (LineSegment){pointsBuffer[0], pointsBuffer[0]};
                            [self.currentPath.path moveToPoint:ls[0].firstPoint];                      
                            isFirstTouchPoint = NO;                   
                        }
                        else
                        {
                            ls[0] = lastSegmentOfPrev;

                        }


                        float frac1 = self.lineWidth/clamp(len_sq(pointsBuffer[i], pointsBuffer[i+1]), LOWER, UPPER); // ................. (4)
                        float frac2 = self.lineWidth/clamp(len_sq(pointsBuffer[i+1], pointsBuffer[i+2]), LOWER, UPPER);
                        float frac3 = self.lineWidth/clamp(len_sq(pointsBuffer[i+2], pointsBuffer[i+3]), LOWER, UPPER);



                        ls[1] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i], pointsBuffer[i+1]} ofRelativeLength:frac1]; // ................. (5)
                        ls[2] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+1], pointsBuffer[i+2]} ofRelativeLength:frac2];
                        ls[3] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+2], pointsBuffer[i+3]} ofRelativeLength:frac3];



                        [self.currentPath.path  moveToPoint:ls[0].firstPoint]; // ................. (6)
                        [self.currentPath.path  addCurveToPoint:ls[3].firstPoint controlPoint1:ls[1].firstPoint controlPoint2:ls[2].firstPoint];
                        [self.currentPath.path  addLineToPoint:ls[3].secondPoint];
                        [self.currentPath.path  addCurveToPoint:ls[0].secondPoint controlPoint1:ls[2].secondPoint controlPoint2:ls[1].secondPoint];
                        [self.currentPath.path  closePath];

                        lastSegmentOfPrev = ls[3]; // ................. (7)
                    }


                     dispatch_async(dispatch_get_main_queue(), ^{
                            bufIdx = 0;

                            [m_pathArray addObject:self.currentPath];
                            [self setNeedsDisplay];

                        });
                    });


                pts[0] = pts[3];
                pts[1] = pts[4]; 
                ctr = 1;
            }
        }        
}

So friends, please help me out.

like image 730
Ranjit Avatar asked May 13 '26 05:05

Ranjit


2 Answers

You will need to debug to confirm, but it appears to be related to your logic in touchesBegan:withEvent:. In this method, you check each time there is a new touch to determine if it is the 'highest', but when the highest touch does actually change you don't seem to abort / reset any existing drawing.

Your best approach is probably using logging to determine if / when the 'highest' touch is changing and what affect that has on the in-progress line.

Also, in touchesMoved:, you don't need the for (UITouch *touch in touches) loop as you already have a reference to self.trackingTouch so you can just use it directly.

like image 59
Wain Avatar answered May 15 '26 20:05

Wain


If I understood your problem correctly, you're having undesired strokes whenever the user uses multiple fingers on your canvas. Since you already have a self.trackingTouch, will it be reasonable to just ignore every other touch that is not self.trackingTouch?

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (self.trackingTouch)
    {
        // another touch is active so we ignore this one
        return;
    }
    // ...the rest of your code
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = self.trackingTouch;
    if (![touches containsObject:touch])
    {
        // updates to touches other than self.trackingTouch
        return;
    }

    // ...process only self.trackingTouch in the rest of your code
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = self.trackingTouch;
    if (![touches containsObject:touch])
    {
        // updates to touches other than self.trackingTouch
        return;
    }

    // ...process only self.trackingTouch in the rest of your code

   self.trackingTouch = nil;
}

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    // ...same as touchesEnded:withEvent:
}
like image 24
John Estropia Avatar answered May 15 '26 19:05

John Estropia