views:

836

answers:

2

I'm developing an application for iPhone, and I want to detect when the user is moving his finger along a certain path.

Specifically, I want to detect when the user moves their finger along a specific circular path.

This would probably be easily adapted from detecting mouse motion along a path.

A: 

Since I'm not familiar with the iPhone SDK itself, I'm not sure if there are built in facilities for capturing non-standard gestures. However, here is one of the manual ways you can do it.

This tutorial is for Flash, but it operates on the same gesture principles. Each direction represents a number. Tracing a circle with the pointing device will generate a sequence of numbers representing the directions travelled either over time or over distance, its up to you. Compare that sequence of numbers to a pre-defined sequence representing a circle. If they match, fire an event.

There are plenty of tutorials that explain how to make gestures like this "fuzzy" so that less precise point motion is required.

Soviut
+1  A: 

Seems like a specific case can be fairly simple to implement. Divide the input area into four quadrants and track the position through each quadrant. The sequence of quandrants determines if they have completed or traveled in a circle.

Pseudo-code to describe the idea:

static touchKeeper; //touch, quadrant
static touchIndex=0;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
   touchKeeper[touchIndex].touch =  touch;
   touchKepper[touchIndex].quadrant = DetectQuadrant(touch));
   if (touchIndex > 3 && (touchKeeper[3].quadrant == touchKeeper[2].quadrant+1 == touchKeeper[1].quadrant+2 == touchKeeper[0].quadrant+3)) {
     [self doCircleAction];
     touchIndex=0;
   } 
     else touchIndex++;
 }

The idea is that you only need to roughly identify a particular touch to a region. So the quadrant routine would something like this:

int DetectQuadrant(UITouch *touch) {
 CGPoint point;
 point = [touch locationInView:self];
 if (endPoint.x > X1 && endPoint.x < X2 && endPoint.Y > Y1 && endPoint.Y < Y2)
  return QUAD1;
 } else etc

I use quadrants as an example - clearly you could draw a square and think 'circle!'. The accuracy is improved by making more regions in the Detect method. The main idea is to think in terms of sequences of regions in order to achieve the desired behavior without excessive complication (like bezier curve detection or similar nonsense). This pseudo code is certainly brutish and I'm sure there's a nice way to finesse the implementation. I've been thinking about 'circular motion detection' for a project I'm working on and this was the rough idea I came up with.

Enjoy!

John Fricker
Credit where credit is due. This idea is based on an IBM paper on character and handwriting detection where researches determined that only a few unique points were necessary to identify characters. So instead of tracing 'E' the OCR would look for the fewest unique position points.
John Fricker