Commit 428e61a4 authored by Kees Bakker's avatar Kees Bakker

Reformat SDL_gesture.c (part 1, reindent using Emacs, c-basic-offset 4)

parent 61d3a02e
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define MAXPATHSIZE 1024 #define MAXPATHSIZE 1024
#define DOLLARNPOINTS 64 #define DOLLARNPOINTS 64
...@@ -44,35 +44,35 @@ ...@@ -44,35 +44,35 @@
#define ENABLE_DOLLAR #define ENABLE_DOLLAR
#define PHI 0.618033989 #define PHI 0.618033989
typedef struct { typedef struct {
float x,y; float x,y;
} SDL_FloatPoint; } SDL_FloatPoint;
typedef struct { typedef struct {
float length; float length;
int numPoints; int numPoints;
SDL_FloatPoint p[MAXPATHSIZE]; SDL_FloatPoint p[MAXPATHSIZE];
} SDL_DollarPath; } SDL_DollarPath;
typedef struct { typedef struct {
SDL_FloatPoint path[DOLLARNPOINTS]; SDL_FloatPoint path[DOLLARNPOINTS];
unsigned long hash; unsigned long hash;
} SDL_DollarTemplate; } SDL_DollarTemplate;
typedef struct { typedef struct {
SDL_GestureID id; SDL_GestureID id;
SDL_FloatPoint res; SDL_FloatPoint res;
SDL_FloatPoint centroid; SDL_FloatPoint centroid;
SDL_DollarPath dollarPath; SDL_DollarPath dollarPath;
Uint16 numDownFingers; Uint16 numDownFingers;
int numDollarTemplates; int numDollarTemplates;
SDL_DollarTemplate *dollarTemplate; SDL_DollarTemplate *dollarTemplate;
SDL_bool recording; SDL_bool recording;
} SDL_GestureTouch; } SDL_GestureTouch;
SDL_GestureTouch *SDL_gestureTouch; SDL_GestureTouch *SDL_gestureTouch;
...@@ -80,586 +80,603 @@ int SDL_numGestureTouches = 0; ...@@ -80,586 +80,603 @@ int SDL_numGestureTouches = 0;
SDL_bool recordAll; SDL_bool recordAll;
#if 0 #if 0
static void PrintPath(SDL_FloatPoint *path) { static void PrintPath(SDL_FloatPoint *path)
int i; {
printf("Path:"); int i;
for(i=0;i<DOLLARNPOINTS;i++) { printf("Path:");
printf(" (%f,%f)",path[i].x,path[i].y); for(i=0;i<DOLLARNPOINTS;i++) {
} printf(" (%f,%f)",path[i].x,path[i].y);
printf("\n"); }
printf("\n");
} }
#endif #endif
int SDL_RecordGesture(SDL_TouchID touchId) { int SDL_RecordGesture(SDL_TouchID touchId)
int i; {
if(touchId < 0) recordAll = SDL_TRUE; int i;
for(i = 0;i < SDL_numGestureTouches; i++) { if(touchId < 0) recordAll = SDL_TRUE;
if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) { for(i = 0;i < SDL_numGestureTouches; i++) {
SDL_gestureTouch[i].recording = SDL_TRUE; if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
if(touchId >= 0) SDL_gestureTouch[i].recording = SDL_TRUE;
return 1; if(touchId >= 0)
} return 1;
} }
return (touchId < 0); }
return (touchId < 0);
} }
unsigned long SDL_HashDollar(SDL_FloatPoint* points) { unsigned long SDL_HashDollar(SDL_FloatPoint* points)
unsigned long hash = 5381; {
int i; unsigned long hash = 5381;
for(i = 0;i < DOLLARNPOINTS; i++) { int i;
hash = ((hash<<5) + hash) + (unsigned long)points[i].x; for(i = 0;i < DOLLARNPOINTS; i++) {
hash = ((hash<<5) + hash) + (unsigned long)points[i].y; hash = ((hash<<5) + hash) + (unsigned long)points[i].x;
} hash = ((hash<<5) + hash) + (unsigned long)points[i].y;
return hash; }
return hash;
} }
static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src) { static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src)
if(src == NULL) return 0; {
if(src == NULL) return 0;
//No Longer storing the Hash, rehash on load
//if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
if(SDL_RWwrite(src,templ->path,
sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
return 0;
return 1; //No Longer storing the Hash, rehash on load
//if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
if(SDL_RWwrite(src,templ->path,
sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
return 0;
return 1;
} }
int SDL_SaveAllDollarTemplates(SDL_RWops *src) { int SDL_SaveAllDollarTemplates(SDL_RWops *src)
int i,j,rtrn = 0; {
for(i = 0; i < SDL_numGestureTouches; i++) { int i,j,rtrn = 0;
SDL_GestureTouch* touch = &SDL_gestureTouch[i]; for(i = 0; i < SDL_numGestureTouches; i++) {
for(j = 0;j < touch->numDollarTemplates; j++) { SDL_GestureTouch* touch = &SDL_gestureTouch[i];
rtrn += SaveTemplate(&touch->dollarTemplate[i],src); for(j = 0;j < touch->numDollarTemplates; j++) {
rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
}
} }
} return rtrn;
return rtrn;
} }
int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src) { int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src)
int i,j; {
for(i = 0; i < SDL_numGestureTouches; i++) { int i,j;
SDL_GestureTouch* touch = &SDL_gestureTouch[i]; for(i = 0; i < SDL_numGestureTouches; i++) {
for(j = 0;j < touch->numDollarTemplates; j++) { SDL_GestureTouch* touch = &SDL_gestureTouch[i];
if(touch->dollarTemplate[i].hash == gestureId) { for(j = 0;j < touch->numDollarTemplates; j++) {
return SaveTemplate(&touch->dollarTemplate[i],src); if(touch->dollarTemplate[i].hash == gestureId) {
} return SaveTemplate(&touch->dollarTemplate[i],src);
}
}
} }
} SDL_SetError("Unknown gestureId");
SDL_SetError("Unknown gestureId"); return -1;
return -1;
} }
//path is an already sampled set of points //path is an already sampled set of points
//Returns the index of the gesture on success, or -1 //Returns the index of the gesture on success, or -1
static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch,SDL_FloatPoint* path) { static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch,SDL_FloatPoint* path)
SDL_DollarTemplate* dollarTemplate; {
SDL_DollarTemplate *templ; SDL_DollarTemplate* dollarTemplate;
int i = 0; SDL_DollarTemplate *templ;
if(inTouch == NULL) { int i = 0;
if(SDL_numGestureTouches == 0) return -1; if(inTouch == NULL) {
for(i = 0;i < SDL_numGestureTouches; i++) { if(SDL_numGestureTouches == 0) return -1;
inTouch = &SDL_gestureTouch[i]; for(i = 0;i < SDL_numGestureTouches; i++) {
inTouch = &SDL_gestureTouch[i];
dollarTemplate =
(SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
(inTouch->numDollarTemplates + 1) *
sizeof(SDL_DollarTemplate));
if(!dollarTemplate) {
SDL_OutOfMemory();
return -1;
}
inTouch->dollarTemplate = dollarTemplate;
templ =
&inTouch->dollarTemplate[inTouch->numDollarTemplates];
SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
templ->hash = SDL_HashDollar(templ->path);
inTouch->numDollarTemplates++;
}
return inTouch->numDollarTemplates - 1;
} else {
SDL_DollarTemplate* dollarTemplate =
( SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
(inTouch->numDollarTemplates + 1) *
sizeof(SDL_DollarTemplate));
if(!dollarTemplate) {
SDL_OutOfMemory();
return -1;
}
dollarTemplate = inTouch->dollarTemplate = dollarTemplate;
(SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
(inTouch->numDollarTemplates + 1) * templ =
sizeof(SDL_DollarTemplate)); &inTouch->dollarTemplate[inTouch->numDollarTemplates];
if(!dollarTemplate) { SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
SDL_OutOfMemory(); templ->hash = SDL_HashDollar(templ->path);
return -1; inTouch->numDollarTemplates++;
} return inTouch->numDollarTemplates - 1;
inTouch->dollarTemplate = dollarTemplate;
templ =
&inTouch->dollarTemplate[inTouch->numDollarTemplates];
SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
templ->hash = SDL_HashDollar(templ->path);
inTouch->numDollarTemplates++;
}
return inTouch->numDollarTemplates - 1;
} else {
SDL_DollarTemplate* dollarTemplate =
( SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
(inTouch->numDollarTemplates + 1) *
sizeof(SDL_DollarTemplate));
if(!dollarTemplate) {
SDL_OutOfMemory();
return -1;
} }
return -1;
inTouch->dollarTemplate = dollarTemplate;
templ =
&inTouch->dollarTemplate[inTouch->numDollarTemplates];
SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
templ->hash = SDL_HashDollar(templ->path);
inTouch->numDollarTemplates++;
return inTouch->numDollarTemplates - 1;
}
return -1;
} }
int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) { int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
int i,loaded = 0; {
SDL_GestureTouch *touch = NULL; int i,loaded = 0;
if(src == NULL) return 0; SDL_GestureTouch *touch = NULL;
if(touchId >= 0) { if(src == NULL) return 0;
for(i = 0;i < SDL_numGestureTouches; i++) if(touchId >= 0) {
if(SDL_gestureTouch[i].id == touchId) for(i = 0;i < SDL_numGestureTouches; i++)
touch = &SDL_gestureTouch[i]; if(SDL_gestureTouch[i].id == touchId)
if(touch == NULL) return -1; touch = &SDL_gestureTouch[i];
} if(touch == NULL) return -1;
}
while(1) { while(1) {
SDL_DollarTemplate templ; SDL_DollarTemplate templ;
if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) <
DOLLARNPOINTS) break; DOLLARNPOINTS) break;
if(touchId >= 0) { if(touchId >= 0) {
//printf("Adding loaded gesture to 1 touch\n"); //printf("Adding loaded gesture to 1 touch\n");
if(SDL_AddDollarGesture(touch,templ.path)) loaded++; if(SDL_AddDollarGesture(touch,templ.path)) loaded++;
} }
else { else {
//printf("Adding to: %i touches\n",SDL_numGestureTouches); //printf("Adding to: %i touches\n",SDL_numGestureTouches);
for(i = 0;i < SDL_numGestureTouches; i++) { for(i = 0;i < SDL_numGestureTouches; i++) {
touch = &SDL_gestureTouch[i]; touch = &SDL_gestureTouch[i];
//printf("Adding loaded gesture to + touches\n"); //printf("Adding loaded gesture to + touches\n");
//TODO: What if this fails? //TODO: What if this fails?
SDL_AddDollarGesture(touch,templ.path); SDL_AddDollarGesture(touch,templ.path);
} }
loaded++; loaded++;
}
} }
}
return loaded; return loaded;
} }
float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang) { float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang)
// SDL_FloatPoint p[DOLLARNPOINTS]; {
float dist = 0; // SDL_FloatPoint p[DOLLARNPOINTS];
SDL_FloatPoint p; float dist = 0;
int i; SDL_FloatPoint p;
for(i = 0; i < DOLLARNPOINTS; i++) { int i;
p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang)); for(i = 0; i < DOLLARNPOINTS; i++) {
p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang)); p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+ p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
(p.y-templ[i].y)*(p.y-templ[i].y))); dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
} (p.y-templ[i].y)*(p.y-templ[i].y)));
return dist/DOLLARNPOINTS; }
return dist/DOLLARNPOINTS;
} }
float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ) { float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
//------------BEGIN DOLLAR BLACKBOX----------------// {
//-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-// //------------BEGIN DOLLAR BLACKBOX----------------//
//-"http://depts.washington.edu/aimgroup/proj/dollar/"-// //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
double ta = -M_PI/4; //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
double tb = M_PI/4; double ta = -M_PI/4;
double dt = M_PI/90; double tb = M_PI/4;
float x1 = (float)(PHI*ta + (1-PHI)*tb); double dt = M_PI/90;
float f1 = dollarDifference(points,templ,x1); float x1 = (float)(PHI*ta + (1-PHI)*tb);
float x2 = (float)((1-PHI)*ta + PHI*tb); float f1 = dollarDifference(points,templ,x1);
float f2 = dollarDifference(points,templ,x2); float x2 = (float)((1-PHI)*ta + PHI*tb);
while(SDL_fabs(ta-tb) > dt) { float f2 = dollarDifference(points,templ,x2);
if(f1 < f2) { while(SDL_fabs(ta-tb) > dt) {
tb = x2; if(f1 < f2) {
x2 = x1; tb = x2;
f2 = f1; x2 = x1;
x1 = (float)(PHI*ta + (1-PHI)*tb); f2 = f1;
f1 = dollarDifference(points,templ,x1); x1 = (float)(PHI*ta + (1-PHI)*tb);
} f1 = dollarDifference(points,templ,x1);
else { }
ta = x1; else {
x1 = x2; ta = x1;
f1 = f2; x1 = x2;
x2 = (float)((1-PHI)*ta + PHI*tb); f1 = f2;
f2 = dollarDifference(points,templ,x2); x2 = (float)((1-PHI)*ta + PHI*tb);
f2 = dollarDifference(points,templ,x2);
}
} }
} /*
/* if(f1 <= f2)
if(f1 <= f2) printf("Min angle (x1): %f\n",x1);
printf("Min angle (x1): %f\n",x1); else if(f1 > f2)
else if(f1 > f2) printf("Min angle (x2): %f\n",x2);
printf("Min angle (x2): %f\n",x2); */
*/ return SDL_min(f1,f2);
return SDL_min(f1,f2);
} }
//DollarPath contains raw points, plus (possibly) the calculated length //DollarPath contains raw points, plus (possibly) the calculated length
int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points) { int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
int i; {
float interval; int i;
float dist; float interval;
int numPoints = 0; float dist;
SDL_FloatPoint centroid; int numPoints = 0;
float xmin,xmax,ymin,ymax; SDL_FloatPoint centroid;
float ang; float xmin,xmax,ymin,ymax;
float w,h; float ang;
float length = path->length; float w,h;
float length = path->length;
//Calculate length if it hasn't already been done
if(length <= 0) { //Calculate length if it hasn't already been done
for(i=1;i<path->numPoints;i++) { if(length <= 0) {
float dx = path->p[i ].x - for(i=1;i<path->numPoints;i++) {
path->p[i-1].x; float dx = path->p[i ].x -
float dy = path->p[i ].y - path->p[i-1].x;
path->p[i-1].y; float dy = path->p[i ].y -
length += (float)(SDL_sqrt(dx*dx+dy*dy)); path->p[i-1].y;
length += (float)(SDL_sqrt(dx*dx+dy*dy));
}
} }
}
//Resample
//Resample interval = length/(DOLLARNPOINTS - 1);
interval = length/(DOLLARNPOINTS - 1); dist = interval;
dist = interval;
centroid.x = 0;centroid.y = 0;
centroid.x = 0;centroid.y = 0;
//printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
//printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y); for(i = 1;i < path->numPoints;i++) {
for(i = 1;i < path->numPoints;i++) { float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+ (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
(path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y))); //printf("d = %f dist = %f/%f\n",d,dist,interval);
//printf("d = %f dist = %f/%f\n",d,dist,interval); while(dist + d > interval) {
while(dist + d > interval) { points[numPoints].x = path->p[i-1].x +
points[numPoints].x = path->p[i-1].x + ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
((interval-dist)/d)*(path->p[i].x-path->p[i-1].x); points[numPoints].y = path->p[i-1].y +
points[numPoints].y = path->p[i-1].y + ((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
((interval-dist)/d)*(path->p[i].y-path->p[i-1].y); centroid.x += points[numPoints].x;
centroid.x += points[numPoints].x; centroid.y += points[numPoints].y;
centroid.y += points[numPoints].y; numPoints++;
numPoints++;
dist -= interval;
dist -= interval; }
dist += d;
} }
dist += d; if(numPoints < DOLLARNPOINTS-1) {
} SDL_SetError("ERROR: NumPoints = %i\n",numPoints);
if(numPoints < DOLLARNPOINTS-1) { return 0;
SDL_SetError("ERROR: NumPoints = %i\n",numPoints); }
return 0; //copy the last point
} points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
//copy the last point numPoints = DOLLARNPOINTS;
points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
numPoints = DOLLARNPOINTS; centroid.x /= numPoints;
centroid.y /= numPoints;
centroid.x /= numPoints;
centroid.y /= numPoints; //printf("Centroid (%f,%f)",centroid.x,centroid.y);
//Rotate Points so point 0 is left of centroid and solve for the bounding box
//printf("Centroid (%f,%f)",centroid.x,centroid.y); xmin = centroid.x;
//Rotate Points so point 0 is left of centroid and solve for the bounding box xmax = centroid.x;
xmin = centroid.x; ymin = centroid.y;
xmax = centroid.x; ymax = centroid.y;
ymin = centroid.y;
ymax = centroid.y; ang = (float)(SDL_atan2(centroid.y - points[0].y,
centroid.x - points[0].x));
ang = (float)(SDL_atan2(centroid.y - points[0].y,
centroid.x - points[0].x)); for(i = 0;i<numPoints;i++) {
float px = points[i].x;
for(i = 0;i<numPoints;i++) { float py = points[i].y;
float px = points[i].x; points[i].x = (float)((px - centroid.x)*SDL_cos(ang) -
float py = points[i].y; (py - centroid.y)*SDL_sin(ang) + centroid.x);
points[i].x = (float)((px - centroid.x)*SDL_cos(ang) - points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
(py - centroid.y)*SDL_sin(ang) + centroid.x); (py - centroid.y)*SDL_cos(ang) + centroid.y);
points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
(py - centroid.y)*SDL_cos(ang) + centroid.y);
if(points[i].x < xmin) xmin = points[i].x;
if(points[i].x > xmax) xmax = points[i].x;
if(points[i].x < xmin) xmin = points[i].x; if(points[i].y < ymin) ymin = points[i].y;
if(points[i].x > xmax) xmax = points[i].x; if(points[i].y > ymax) ymax = points[i].y;
if(points[i].y < ymin) ymin = points[i].y; }
if(points[i].y > ymax) ymax = points[i].y;
} //Scale points to DOLLARSIZE, and translate to the origin
w = xmax-xmin;
//Scale points to DOLLARSIZE, and translate to the origin h = ymax-ymin;
w = xmax-xmin;
h = ymax-ymin; for(i=0;i<numPoints;i++) {
points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
for(i=0;i<numPoints;i++) { points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w; }
points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h; return numPoints;
}
return numPoints;
} }
float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch) { float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch)
{
SDL_FloatPoint points[DOLLARNPOINTS];
int i;
float bestDiff = 10000;
dollarNormalize(path,points); SDL_FloatPoint points[DOLLARNPOINTS];
int i;
float bestDiff = 10000;
//PrintPath(points); dollarNormalize(path,points);
*bestTempl = -1;
for(i = 0;i < touch->numDollarTemplates;i++) { //PrintPath(points);
float diff = bestDollarDifference(points,touch->dollarTemplate[i].path); *bestTempl = -1;
if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;} for(i = 0;i < touch->numDollarTemplates;i++) {
} float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
return bestDiff; if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
}
return bestDiff;
} }
int SDL_GestureAddTouch(SDL_Touch* touch) { int SDL_GestureAddTouch(SDL_Touch* touch)
SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch, {
(SDL_numGestureTouches + 1) * SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
sizeof(SDL_GestureTouch)); (SDL_numGestureTouches + 1) *
sizeof(SDL_GestureTouch));
if(!gestureTouch) { if(!gestureTouch) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return -1; return -1;
} }
SDL_gestureTouch = gestureTouch; SDL_gestureTouch = gestureTouch;
SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres; SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres; SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres;
SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0; SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres; SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
SDL_gestureTouch[SDL_numGestureTouches].id = touch->id; SDL_gestureTouch[SDL_numGestureTouches].id = touch->id;
SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0; SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE; SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
SDL_numGestureTouches++; SDL_numGestureTouches++;
return 0; return 0;
} }
int SDL_GestureRemoveTouch(SDL_TouchID id) { int SDL_GestureRemoveTouch(SDL_TouchID id)
int i; {
for (i = 0; i < SDL_numGestureTouches; i++) { int i;
if (SDL_gestureTouch[i].id == id) { for (i = 0; i < SDL_numGestureTouches; i++) {
SDL_numGestureTouches--; if (SDL_gestureTouch[i].id == id) {
SDL_memcpy(&SDL_gestureTouch[i], &SDL_gestureTouch[SDL_numGestureTouches], sizeof(SDL_gestureTouch[i])); SDL_numGestureTouches--;
return 1; SDL_memcpy(&SDL_gestureTouch[i], &SDL_gestureTouch[SDL_numGestureTouches], sizeof(SDL_gestureTouch[i]));
return 1;
}
} }
} return -1;
return -1;
} }
SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) { SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
int i; {
for(i = 0;i < SDL_numGestureTouches; i++) { int i;
//printf("%i ?= %i\n",SDL_gestureTouch[i].id,id); for(i = 0;i < SDL_numGestureTouches; i++) {
if(SDL_gestureTouch[i].id == id) return &SDL_gestureTouch[i]; //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
} if(SDL_gestureTouch[i].id == id) return &SDL_gestureTouch[i];
return NULL; }
return NULL;
} }
int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist) { int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
SDL_Event event; {
event.mgesture.type = SDL_MULTIGESTURE; SDL_Event event;
event.mgesture.touchId = touch->id; event.mgesture.type = SDL_MULTIGESTURE;
event.mgesture.x = touch->centroid.x; event.mgesture.touchId = touch->id;
event.mgesture.y = touch->centroid.y; event.mgesture.x = touch->centroid.x;
event.mgesture.dTheta = dTheta; event.mgesture.y = touch->centroid.y;
event.mgesture.dDist = dDist; event.mgesture.dTheta = dTheta;
event.mgesture.numFingers = touch->numDownFingers; event.mgesture.dDist = dDist;
return SDL_PushEvent(&event) > 0; event.mgesture.numFingers = touch->numDownFingers;
return SDL_PushEvent(&event) > 0;
} }
int SDL_SendGestureDollar(SDL_GestureTouch* touch, int SDL_SendGestureDollar(SDL_GestureTouch* touch,
SDL_GestureID gestureId,float error) { SDL_GestureID gestureId,float error)
SDL_Event event; {
event.dgesture.type = SDL_DOLLARGESTURE; SDL_Event event;
event.dgesture.touchId = touch->id; event.dgesture.type = SDL_DOLLARGESTURE;
/* event.dgesture.touchId = touch->id;
/*
//TODO: Add this to give location of gesture? //TODO: Add this to give location of gesture?
event.mgesture.x = touch->centroid.x; event.mgesture.x = touch->centroid.x;
event.mgesture.y = touch->centroid.y; event.mgesture.y = touch->centroid.y;
*/ */
event.dgesture.gestureId = gestureId; event.dgesture.gestureId = gestureId;
event.dgesture.error = error; event.dgesture.error = error;
//A finger came up to trigger this event. //A finger came up to trigger this event.
event.dgesture.numFingers = touch->numDownFingers + 1; event.dgesture.numFingers = touch->numDownFingers + 1;
return SDL_PushEvent(&event) > 0; return SDL_PushEvent(&event) > 0;
} }
int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId) { int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
SDL_Event event; {
event.dgesture.type = SDL_DOLLARRECORD; SDL_Event event;
event.dgesture.touchId = touch->id; event.dgesture.type = SDL_DOLLARRECORD;
event.dgesture.gestureId = gestureId; event.dgesture.touchId = touch->id;
return SDL_PushEvent(&event) > 0; event.dgesture.gestureId = gestureId;
return SDL_PushEvent(&event) > 0;
} }
void SDL_GestureProcessEvent(SDL_Event* event) void SDL_GestureProcessEvent(SDL_Event* event)
{ {
float x,y; float x,y;
SDL_FloatPoint path[DOLLARNPOINTS]; SDL_FloatPoint path[DOLLARNPOINTS];
int index; int index;
int i; int i;
float pathDx, pathDy; float pathDx, pathDy;
SDL_FloatPoint lastP; SDL_FloatPoint lastP;
SDL_FloatPoint lastCentroid; SDL_FloatPoint lastCentroid;
float lDist; float lDist;
float Dist; float Dist;
float dtheta; float dtheta;
float dDist; float dDist;
if(event->type == SDL_FINGERMOTION || if(event->type == SDL_FINGERMOTION ||
event->type == SDL_FINGERDOWN || event->type == SDL_FINGERDOWN ||
event->type == SDL_FINGERUP) { event->type == SDL_FINGERUP) {
SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId); SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
//Shouldn't be possible //Shouldn't be possible
if(inTouch == NULL) return; if(inTouch == NULL) return;
//printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x, //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
// (int)event->tfinger.y, // (int)event->tfinger.y,
// (int)inTouch->res.x,(int)inTouch->res.y); // (int)inTouch->res.x,(int)inTouch->res.y);
x = ((float)event->tfinger.x)/(float)inTouch->res.x; x = ((float)event->tfinger.x)/(float)inTouch->res.x;
y = ((float)event->tfinger.y)/(float)inTouch->res.y; y = ((float)event->tfinger.y)/(float)inTouch->res.y;
//Finger Up //Finger Up
if(event->type == SDL_FINGERUP) { if(event->type == SDL_FINGERUP) {
inTouch->numDownFingers--; inTouch->numDownFingers--;
#ifdef ENABLE_DOLLAR #ifdef ENABLE_DOLLAR
if(inTouch->recording) { if(inTouch->recording) {
inTouch->recording = SDL_FALSE; inTouch->recording = SDL_FALSE;
dollarNormalize(&inTouch->dollarPath,path); dollarNormalize(&inTouch->dollarPath,path);
//PrintPath(path); //PrintPath(path);
if(recordAll) { if(recordAll) {
index = SDL_AddDollarGesture(NULL,path); index = SDL_AddDollarGesture(NULL,path);
for(i = 0;i < SDL_numGestureTouches; i++) for(i = 0;i < SDL_numGestureTouches; i++)
SDL_gestureTouch[i].recording = SDL_FALSE; SDL_gestureTouch[i].recording = SDL_FALSE;
} }
else { else {
index = SDL_AddDollarGesture(inTouch,path); index = SDL_AddDollarGesture(inTouch,path);
} }
if(index >= 0) { if(index >= 0) {
SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash); SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
} }
else { else {
SDL_SendDollarRecord(inTouch,-1); SDL_SendDollarRecord(inTouch,-1);
} }
} }
else { else {
int bestTempl; int bestTempl;
float error; float error;
error = dollarRecognize(&inTouch->dollarPath, error = dollarRecognize(&inTouch->dollarPath,
&bestTempl,inTouch); &bestTempl,inTouch);
if(bestTempl >= 0){ if(bestTempl >= 0){
//Send Event //Send Event
unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash; unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
SDL_SendGestureDollar(inTouch,gestureId,error); SDL_SendGestureDollar(inTouch,gestureId,error);
//printf ("%s\n",);("Dollar error: %f\n",error); //printf ("%s\n",);("Dollar error: %f\n",error);
}
}
#endif
//inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
if(inTouch->numDownFingers > 0) {
inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
x)/inTouch->numDownFingers;
inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
y)/inTouch->numDownFingers;
}
} }
} else if(event->type == SDL_FINGERMOTION) {
#endif float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
//inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers]; float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
if(inTouch->numDownFingers > 0) { //printf("dx,dy: (%f,%f)\n",dx,dy);
inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
x)/inTouch->numDownFingers;
inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
y)/inTouch->numDownFingers;
}
}
else if(event->type == SDL_FINGERMOTION) {
float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
//printf("dx,dy: (%f,%f)\n",dx,dy);
#ifdef ENABLE_DOLLAR #ifdef ENABLE_DOLLAR
SDL_DollarPath* path = &inTouch->dollarPath; SDL_DollarPath* path = &inTouch->dollarPath;
if(path->numPoints < MAXPATHSIZE) { if(path->numPoints < MAXPATHSIZE) {
path->p[path->numPoints].x = inTouch->centroid.x; path->p[path->numPoints].x = inTouch->centroid.x;
path->p[path->numPoints].y = inTouch->centroid.y; path->p[path->numPoints].y = inTouch->centroid.y;
pathDx = pathDx =
(path->p[path->numPoints].x-path->p[path->numPoints-1].x); (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
pathDy = pathDy =
(path->p[path->numPoints].y-path->p[path->numPoints-1].y); (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy); path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
path->numPoints++; path->numPoints++;
} }
#endif #endif
lastP.x = x - dx; lastP.x = x - dx;
lastP.y = y - dy; lastP.y = y - dy;
lastCentroid = inTouch->centroid; lastCentroid = inTouch->centroid;
inTouch->centroid.x += dx/inTouch->numDownFingers; inTouch->centroid.x += dx/inTouch->numDownFingers;
inTouch->centroid.y += dy/inTouch->numDownFingers; inTouch->centroid.y += dy/inTouch->numDownFingers;
//printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y); //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
if(inTouch->numDownFingers > 1) { if(inTouch->numDownFingers > 1) {
SDL_FloatPoint lv; //Vector from centroid to last x,y position SDL_FloatPoint lv; //Vector from centroid to last x,y position
SDL_FloatPoint v; //Vector from centroid to current x,y position SDL_FloatPoint v; //Vector from centroid to current x,y position
//lv = inTouch->gestureLast[j].cv; //lv = inTouch->gestureLast[j].cv;
lv.x = lastP.x - lastCentroid.x; lv.x = lastP.x - lastCentroid.x;
lv.y = lastP.y - lastCentroid.y; lv.y = lastP.y - lastCentroid.y;
lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y); lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
//printf("lDist = %f\n",lDist); //printf("lDist = %f\n",lDist);
v.x = x - inTouch->centroid.x; v.x = x - inTouch->centroid.x;
v.y = y - inTouch->centroid.y; v.y = y - inTouch->centroid.y;
//inTouch->gestureLast[j].cv = v; //inTouch->gestureLast[j].cv = v;
Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y); Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
// SDL_cos(dTheta) = (v . lv)/(|v| * |lv|) // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
//Normalize Vectors to simplify angle calculation //Normalize Vectors to simplify angle calculation
lv.x/=lDist; lv.x/=lDist;
lv.y/=lDist; lv.y/=lDist;
v.x/=Dist; v.x/=Dist;
v.y/=Dist; v.y/=Dist;
dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y); dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
dDist = (Dist - lDist); dDist = (Dist - lDist);
if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
//inTouch->gestureLast[j].dDist = dDist; //inTouch->gestureLast[j].dDist = dDist;
//inTouch->gestureLast[j].dtheta = dtheta; //inTouch->gestureLast[j].dtheta = dtheta;
//printf("dDist = %f, dTheta = %f\n",dDist,dtheta); //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
//gdtheta = gdtheta*.9 + dtheta*.1; //gdtheta = gdtheta*.9 + dtheta*.1;
//gdDist = gdDist*.9 + dDist*.1 //gdDist = gdDist*.9 + dDist*.1
//knob.r += dDist/numDownFingers; //knob.r += dDist/numDownFingers;
//knob.ang += dtheta; //knob.ang += dtheta;
//printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist); //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
//printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist); //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
SDL_SendGestureMulti(inTouch,dtheta,dDist); SDL_SendGestureMulti(inTouch,dtheta,dDist);
} }
else { else {
//inTouch->gestureLast[j].dDist = 0; //inTouch->gestureLast[j].dDist = 0;
//inTouch->gestureLast[j].dtheta = 0; //inTouch->gestureLast[j].dtheta = 0;
//inTouch->gestureLast[j].cv.x = 0; //inTouch->gestureLast[j].cv.x = 0;
//inTouch->gestureLast[j].cv.y = 0; //inTouch->gestureLast[j].cv.y = 0;
} }
//inTouch->gestureLast[j].f.p.x = x; //inTouch->gestureLast[j].f.p.x = x;
//inTouch->gestureLast[j].f.p.y = y; //inTouch->gestureLast[j].f.p.y = y;
//break; //break;
//pressure? //pressure?
} }
if(event->type == SDL_FINGERDOWN) {
inTouch->numDownFingers++; if(event->type == SDL_FINGERDOWN) {
inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
x)/inTouch->numDownFingers; inTouch->numDownFingers++;
inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+ inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
y)/inTouch->numDownFingers; x)/inTouch->numDownFingers;
//printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y, inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
// inTouch->centroid.x,inTouch->centroid.y); y)/inTouch->numDownFingers;
//printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
// inTouch->centroid.x,inTouch->centroid.y);
#ifdef ENABLE_DOLLAR #ifdef ENABLE_DOLLAR
inTouch->dollarPath.length = 0; inTouch->dollarPath.length = 0;
inTouch->dollarPath.p[0].x = x; inTouch->dollarPath.p[0].x = x;
inTouch->dollarPath.p[0].y = y; inTouch->dollarPath.p[0].y = y;
inTouch->dollarPath.numPoints = 1; inTouch->dollarPath.numPoints = 1;
#endif #endif
}
} }
}
} }
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment