src/events/SDL_gesture.c
author Jim Grandpre <jim.tla@gmail.com>
Wed, 04 Aug 2010 23:17:30 -0400
changeset 4683 15dfe42edbfd
parent 4682 4ba1048a324c
child 4684 f47c2640c667
permissions -rw-r--r--
Fixed gestureMulti. Disabled dollar gesture temporarily.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software    Founation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    17 
    18     Sam Lantinga
    19     slouken@libsdl.org
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* General mouse handling code for SDL */
    24 
    25 #include "SDL_events.h"
    26 #include "SDL_events_c.h"
    27 #include "SDL_gesture_c.h"
    28 
    29 //TODO: Replace with malloc
    30 #define MAXFINGERS 5
    31 #define MAXTOUCHES 2
    32 #define MAXTEMPLATES 4
    33 #define MAXPATHSIZE 1024
    34 
    35 #define DOLLARNPOINTS 64
    36 #define DOLLARSIZE 256
    37 
    38 //PHI = ((sqrt(5)-1)/2)
    39 #define PHI 0.618033989 
    40 
    41 typedef struct {
    42   float x,y;
    43 } Point;
    44 
    45 
    46 typedef struct {
    47   Point p;
    48   float pressure;
    49   SDL_FingerID id;
    50 } Finger;
    51 
    52 
    53 typedef struct {
    54   float length;
    55   
    56   int numPoints;
    57   Point p[MAXPATHSIZE];
    58 } DollarPath;
    59 
    60 
    61 typedef struct {
    62   Finger f;
    63   Point cv;
    64   float dtheta,dDist;
    65   DollarPath dollarPath;
    66 } TouchPoint;
    67 
    68 typedef struct {
    69   Point path[DOLLARNPOINTS];
    70   unsigned long hash;
    71 } DollarTemplate;
    72 
    73 typedef struct {
    74   SDL_GestureID id;
    75   Point res;
    76   Point centroid;
    77   TouchPoint gestureLast[MAXFINGERS];
    78   Uint16 numDownFingers;
    79 
    80   int numDollarTemplates;
    81   DollarTemplate dollarTemplate[MAXTEMPLATES];
    82 
    83   SDL_bool recording;
    84 } GestureTouch;
    85 
    86 GestureTouch gestureTouch[MAXTOUCHES];
    87 int numGestureTouches = 0;
    88 SDL_bool recordAll;
    89 
    90 int SDL_RecordGesture(SDL_TouchID touchId) {
    91   int i;
    92   if(touchId < 0) recordAll = SDL_TRUE;
    93   for(i = 0;i < numGestureTouches; i++) {
    94     if((touchId < 0) || (gestureTouch[i].id == touchId)) {
    95       gestureTouch[i].recording = SDL_TRUE;
    96       if(touchId >= 0)
    97 	return 1;
    98     }      
    99   }
   100   return (touchId < 0);
   101 }
   102 
   103 unsigned long SDL_HashDollar(Point* points) {
   104   unsigned long hash = 5381;
   105   int i;
   106   for(i = 0;i < DOLLARNPOINTS; i++) { 
   107     hash = ((hash<<5) + hash) + points[i].x;
   108     hash = ((hash<<5) + hash) + points[i].y;
   109   }
   110   return hash;
   111 }
   112 
   113 
   114 static int SaveTemplate(DollarTemplate *templ, SDL_RWops * src) {
   115   if(src == NULL) return 0;
   116 
   117   int i;
   118   
   119   //No Longer storing the Hash, rehash on load
   120   //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
   121 
   122   if(SDL_RWwrite(src,templ->path,
   123 		 sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) 
   124     return 0;
   125 
   126   return 1;
   127 }
   128 
   129 
   130 int SDL_SaveAllDollarTemplates(SDL_RWops *src) {  
   131   int i,j,rtrn = 0;
   132   for(i = 0; i < numGestureTouches; i++) {
   133     GestureTouch* touch = &gestureTouch[i];
   134     for(j = 0;j < touch->numDollarTemplates; j++) {
   135 	rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
   136     }
   137   }
   138   return rtrn;  
   139 }
   140 
   141 int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src) {
   142   int i,j;
   143   for(i = 0; i < numGestureTouches; i++) {
   144     GestureTouch* touch = &gestureTouch[i];
   145     for(j = 0;j < touch->numDollarTemplates; j++) {
   146       if(touch->dollarTemplate[i].hash == gestureId) {
   147 	return SaveTemplate(&touch->dollarTemplate[i],src);
   148       }
   149     }
   150   }
   151   SDL_SetError("Unknown gestureId");
   152   return -1;
   153 }
   154 
   155 //path is an already sampled set of points
   156 //Returns the index of the gesture on success, or -1
   157 static int SDL_AddDollarGesture(GestureTouch* inTouch,Point* path) {
   158   if(inTouch == NULL) {
   159     if(numGestureTouches == 0) return -1;
   160     int i = 0;
   161     for(i = 0;i < numGestureTouches; i++) {
   162       inTouch = &gestureTouch[i];
   163       if(inTouch->numDollarTemplates < MAXTEMPLATES) {
   164 	DollarTemplate *templ = 
   165 	  &inTouch->dollarTemplate[inTouch->numDollarTemplates];
   166 	memcpy(templ->path,path,DOLLARNPOINTS*sizeof(Point));
   167 	templ->hash = SDL_HashDollar(templ->path);
   168 	inTouch->numDollarTemplates++;
   169       }
   170     }
   171     return inTouch->numDollarTemplates - 1;
   172   }else if(inTouch->numDollarTemplates < MAXTEMPLATES) {
   173     DollarTemplate *templ = 
   174       &inTouch->dollarTemplate[inTouch->numDollarTemplates];
   175     memcpy(templ->path,path,DOLLARNPOINTS*sizeof(Point));
   176     templ->hash = SDL_HashDollar(templ->path);
   177     inTouch->numDollarTemplates++;
   178     return inTouch->numDollarTemplates - 1;
   179   }
   180   return -1;
   181 }
   182 
   183 int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) {
   184   if(src == NULL) return 0;
   185   int i,loaded = 0;
   186   GestureTouch *touch = NULL;
   187   if(touchId >= 0) {
   188     for(i = 0;i < numGestureTouches; i++)
   189       if(gestureTouch[i].id == touchId)
   190 	touch = &gestureTouch[i];
   191     if(touch == NULL) return -1;
   192   }
   193 
   194   while(1) {
   195     DollarTemplate templ;
   196     //fscanf(fp,"%lu ",&templ.hash);
   197     /*
   198     for(i = 0;i < DOLLARNPOINTS; i++) {		
   199       int x,y;
   200       if(fscanf(fp,"%i %i ",&x,&y) != 2) break;
   201       templ.path[i].x = x;
   202       templ.path[i].y = y;
   203     }
   204     fscanf(fp,"\n");
   205     */
   206     if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) break;
   207 
   208     if(touchId >= 0) {
   209       printf("Adding loaded gesture to 1 touch\n");
   210       if(SDL_AddDollarGesture(touch,templ.path)) loaded++;
   211     }
   212     else {
   213       printf("Adding to: %i touches\n",numGestureTouches);
   214       for(i = 0;i < numGestureTouches; i++) {
   215 	touch = &gestureTouch[i];
   216 	printf("Adding loaded gesture to + touches\n");
   217 	//TODO: What if this fails?
   218 	SDL_AddDollarGesture(touch,templ.path);	
   219       }
   220       loaded++;
   221     }
   222   }
   223 
   224   return loaded; 
   225 }
   226 
   227 
   228 float dollarDifference(Point* points,Point* templ,float ang) {
   229   //  Point p[DOLLARNPOINTS];
   230   float dist = 0;
   231   Point p;
   232   int i;
   233   for(i = 0; i < DOLLARNPOINTS; i++) {
   234     p.x = points[i].x * cos(ang) - points[i].y * sin(ang);
   235     p.y = points[i].x * sin(ang) + points[i].y * cos(ang);
   236     dist += sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
   237 		 (p.y-templ[i].y)*(p.y-templ[i].y));
   238   }
   239   return dist/DOLLARNPOINTS;
   240   
   241 }
   242 
   243 float bestDollarDifference(Point* points,Point* templ) {
   244   //------------BEGIN DOLLAR BLACKBOX----------------//
   245   //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
   246   //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
   247   float ta = -M_PI/4;
   248   float tb = M_PI/4;
   249   float dt = M_PI/90;
   250   float x1 = PHI*ta + (1-PHI)*tb;
   251   float f1 = dollarDifference(points,templ,x1);
   252   float x2 = (1-PHI)*ta + PHI*tb;
   253   float f2 = dollarDifference(points,templ,x2);
   254   while(abs(ta-tb) > dt) {
   255     if(f1 < f2) {
   256       tb = x2;
   257       x2 = x1;
   258       f2 = f1;
   259       x1 = PHI*ta + (1-PHI)*tb;
   260       f1 = dollarDifference(points,templ,x1);
   261     }
   262     else {
   263       ta = x1;
   264       x1 = x2;
   265       f1 = f2;
   266       x2 = (1-PHI)*ta + PHI*tb;
   267       f2 = dollarDifference(points,templ,x2);
   268     }
   269   }
   270   /*
   271   if(f1 <= f2)
   272     printf("Min angle (x1): %f\n",x1);
   273   else if(f1 >  f2)
   274     printf("Min angle (x2): %f\n",x2);
   275   */
   276   return SDL_min(f1,f2);  
   277 }
   278 
   279 //DollarPath contains raw points, plus (possibly) the calculated length
   280 int dollarNormalize(DollarPath path,Point *points) {
   281   int i;
   282   //Calculate length if it hasn't already been done
   283   if(path.length <= 0) {
   284     for(i=1;i<path.numPoints;i++) {
   285       float dx = path.p[i  ].x - 
   286 	         path.p[i-1].x;
   287       float dy = path.p[i  ].y - 
   288 	         path.p[i-1].y;
   289       path.length += sqrt(dx*dx+dy*dy);
   290     }
   291   }
   292 
   293 
   294   //Resample
   295   float interval = path.length/(DOLLARNPOINTS - 1);
   296   float dist = 0;
   297 
   298   int numPoints = 0;
   299   Point centroid; centroid.x = 0;centroid.y = 0;
   300   //printf("(%f,%f)\n",path.p[path.numPoints-1].x,path.p[path.numPoints-1].y);
   301   for(i = 1;i < path.numPoints;i++) {
   302     float d = sqrt((path.p[i-1].x-path.p[i].x)*(path.p[i-1].x-path.p[i].x)+
   303 		   (path.p[i-1].y-path.p[i].y)*(path.p[i-1].y-path.p[i].y));
   304     //printf("d = %f dist = %f/%f\n",d,dist,interval);
   305     while(dist + d > interval) {
   306       points[numPoints].x = path.p[i-1].x + 
   307 	((interval-dist)/d)*(path.p[i].x-path.p[i-1].x);
   308       points[numPoints].y = path.p[i-1].y + 
   309 	((interval-dist)/d)*(path.p[i].y-path.p[i-1].y);
   310       centroid.x += points[numPoints].x;
   311       centroid.y += points[numPoints].y;
   312       numPoints++;
   313 
   314       dist -= interval;
   315     }
   316     dist += d;
   317   }
   318   if(numPoints < 1) return 0;
   319   centroid.x /= numPoints;
   320   centroid.y /= numPoints;
   321  
   322   //printf("Centroid (%f,%f)",centroid.x,centroid.y);
   323   //Rotate Points so point 0 is left of centroid and solve for the bounding box
   324   float xmin,xmax,ymin,ymax;
   325   xmin = centroid.x;
   326   xmax = centroid.x;
   327   ymin = centroid.y;
   328   ymax = centroid.y;
   329   
   330   float ang = atan2(centroid.y - points[0].y,
   331 		    centroid.x - points[0].x);
   332 
   333   for(i = 0;i<numPoints;i++) {					       
   334     float px = points[i].x;
   335     float py = points[i].y;
   336     points[i].x = (px - centroid.x)*cos(ang) - 
   337                   (py - centroid.y)*sin(ang) + centroid.x;
   338     points[i].y = (px - centroid.x)*sin(ang) + 
   339                   (py - centroid.y)*cos(ang) + centroid.y;
   340 
   341 
   342     if(points[i].x < xmin) xmin = points[i].x;
   343     if(points[i].x > xmax) xmax = points[i].x; 
   344     if(points[i].y < ymin) ymin = points[i].y;
   345     if(points[i].y > ymax) ymax = points[i].y;
   346   }
   347 
   348   //Scale points to DOLLARSIZE, and translate to the origin
   349   float w = xmax-xmin;
   350   float h = ymax-ymin;
   351 
   352   for(i=0;i<numPoints;i++) {
   353     points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
   354     points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
   355   }  
   356   return numPoints;
   357 }
   358 
   359 float dollarRecognize(DollarPath path,int *bestTempl,GestureTouch* touch) {
   360 	
   361 	Point points[DOLLARNPOINTS];
   362 	int numPoints = dollarNormalize(path,points);
   363 	int i;
   364 	
   365 	int bestDiff = 10000;
   366 	*bestTempl = -1;
   367 	for(i = 0;i < touch->numDollarTemplates;i++) {
   368 		int diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
   369 		if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
   370 	}
   371 	return bestDiff;
   372 }
   373 
   374 int SDL_GestureAddTouch(SDL_Touch* touch) { 
   375   if(numGestureTouches >= MAXTOUCHES) return -1;
   376   
   377   gestureTouch[numGestureTouches].res.x = touch->xres;
   378   gestureTouch[numGestureTouches].res.y = touch->yres;
   379   gestureTouch[numGestureTouches].numDownFingers = 0;
   380 
   381   gestureTouch[numGestureTouches].res.x = touch->xres;
   382   gestureTouch[numGestureTouches].id = touch->id;
   383 
   384   gestureTouch[numGestureTouches].numDollarTemplates = 0;
   385 
   386   gestureTouch[numGestureTouches].recording = SDL_FALSE;
   387 
   388   numGestureTouches++;
   389   return 0;
   390 }
   391 
   392 GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) {
   393   int i;
   394   for(i = 0;i < numGestureTouches; i++) {
   395     //printf("%i ?= %i\n",gestureTouch[i].id,id);
   396     if(gestureTouch[i].id == id) return &gestureTouch[i];
   397   }
   398   return NULL;
   399 }
   400 
   401 int SDL_SendGestureMulti(GestureTouch* touch,float dTheta,float dDist) {
   402   SDL_Event event;
   403   event.mgesture.type = SDL_MULTIGESTURE;
   404   event.mgesture.touchId = touch->id;
   405   event.mgesture.x = touch->centroid.x;
   406   event.mgesture.y = touch->centroid.y;
   407   event.mgesture.dTheta = dTheta;
   408   event.mgesture.dDist = dDist;  
   409   event.mgesture.numFingers = touch->numDownFingers;
   410   return SDL_PushEvent(&event) > 0;
   411 }
   412 
   413 int SDL_SendGestureDollar(GestureTouch* touch,
   414 			  SDL_GestureID gestureId,float error) {
   415   SDL_Event event;
   416   event.dgesture.type = SDL_DOLLARGESTURE;
   417   event.dgesture.touchId = touch->id;
   418   /*
   419     //TODO: Add this to give location of gesture?
   420   event.mgesture.x = touch->centroid.x;
   421   event.mgesture.y = touch->centroid.y;
   422   */
   423   event.dgesture.gestureId = gestureId;
   424   event.dgesture.error = error;  
   425   return SDL_PushEvent(&event) > 0;
   426 }
   427 
   428 
   429 int SDL_SendDollarRecord(GestureTouch* touch,SDL_GestureID gestureId) {
   430   SDL_Event event;
   431   event.dgesture.type = SDL_DOLLARRECORD;
   432   event.dgesture.touchId = touch->id;
   433   event.dgesture.gestureId = gestureId;
   434 
   435   return SDL_PushEvent(&event) > 0;
   436 }
   437 
   438 
   439 void SDL_GestureProcessEvent(SDL_Event* event)
   440 {
   441   if(event->type == SDL_FINGERMOTION || 
   442      event->type == SDL_FINGERDOWN ||
   443      event->type == SDL_FINGERUP) {
   444     GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   445     
   446     //Shouldn't be possible
   447     if(inTouch == NULL) return;
   448     
   449     //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
   450     //	   (int)event->tfinger.y,
   451     //   (int)inTouch->res.x,(int)inTouch->res.y);
   452 
   453     
   454     float x = ((float)event->tfinger.x)/(float)inTouch->res.x;
   455     float y = ((float)event->tfinger.y)/(float)inTouch->res.y;   
   456 
   457 
   458     //Finger Up
   459     if(event->type == SDL_FINGERUP) {
   460       inTouch->numDownFingers--;
   461       
   462 #ifdef ENABLE_DOLLAR
   463       if(inTouch->recording) {
   464 	inTouch->recording = SDL_FALSE;
   465 	Point path[DOLLARNPOINTS];
   466 	dollarNormalize(inTouch->gestureLast[j].dollarPath,path);
   467 	int index;
   468 	if(recordAll) {
   469 	  index = SDL_AddDollarGesture(NULL,path);
   470 	  int i;
   471 	  for(i = 0;i < numGestureTouches; i++)
   472 	    gestureTouch[i].recording = SDL_FALSE;
   473 	}
   474 	else {
   475 	  index = SDL_AddDollarGesture(inTouch,path);
   476 	}
   477 	
   478 	if(index >= 0) {
   479 	  SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   480 	}
   481 	else {
   482 	  SDL_SendDollarRecord(inTouch,-1);
   483 	}
   484       }
   485       else {	
   486 	int bestTempl;
   487 	float error;
   488 	error = dollarRecognize(inTouch->gestureLast[j].dollarPath,
   489 				&bestTempl,inTouch);
   490 	if(bestTempl >= 0){
   491 	  //Send Event
   492 	  unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   493 	  SDL_SendGestureDollar(inTouch,gestureId,error);
   494 	    printf ("%s\n",);("Dollar error: %f\n",error);
   495 	}
   496       }
   497 #endif 
   498       //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   499       if(inTouch->numDownFingers > 0) {
   500 	inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   501 			       x)/inTouch->numDownFingers;
   502 	inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   503 			       y)/inTouch->numDownFingers;
   504       }
   505     }
   506     else if(event->type == SDL_FINGERMOTION) {
   507       float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
   508       float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
   509       //printf("dx,dy: (%f,%f)\n",dx,dy); 
   510 #ifdef ENABLE_DOLLAR
   511       DollarPath* path = &inTouch->gestureLast[j].dollarPath;
   512       if(path->numPoints < MAXPATHSIZE) {
   513 	path->p[path->numPoints].x = x;
   514 	path->p[path->numPoints].y = y;
   515 	path->length += sqrt(dx*dx + dy*dy);
   516 	path->numPoints++;
   517       }
   518 #endif
   519       Point lastP;
   520       lastP.x = x - dx;
   521       lastP.y = y - dy;
   522       Point lastCentroid;
   523       lastCentroid = inTouch->centroid;
   524       
   525       inTouch->centroid.x += dx/inTouch->numDownFingers;
   526       inTouch->centroid.y += dy/inTouch->numDownFingers;    
   527       if(inTouch->numDownFingers > 1) {
   528 	Point lv; //Vector from centroid to last x,y position
   529 	Point v; //Vector from centroid to current x,y position
   530 	//lv = inTouch->gestureLast[j].cv;
   531 	lv.x = lastP.x - lastCentroid.x;
   532 	lv.y = lastP.y - lastCentroid.y;
   533 	float lDist = sqrt(lv.x*lv.x + lv.y*lv.y);
   534 	//printf("lDist = %f\n",lDist);
   535 	v.x = x - inTouch->centroid.x;
   536 	v.y = y - inTouch->centroid.y;
   537 	//inTouch->gestureLast[j].cv = v;
   538 	float Dist = sqrt(v.x*v.x+v.y*v.y);
   539 	// cos(dTheta) = (v . lv)/(|v| * |lv|)
   540 	
   541 	//Normalize Vectors to simplify angle calculation
   542 	lv.x/=lDist;
   543 	lv.y/=lDist;
   544 	v.x/=Dist;
   545 	v.y/=Dist;
   546 	float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   547 	
   548 	float dDist = (Dist - lDist);
   549 	if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   550 	
   551 	//inTouch->gestureLast[j].dDist = dDist;
   552 	//inTouch->gestureLast[j].dtheta = dtheta;
   553 	
   554 	//printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   555 	//gdtheta = gdtheta*.9 + dtheta*.1;
   556 	//gdDist  =  gdDist*.9 +  dDist*.1
   557 	//knob.r += dDist/numDownFingers;
   558 	//knob.ang += dtheta;
   559 	//printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   560 	//printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   561 	SDL_SendGestureMulti(inTouch,dtheta,dDist);
   562       }
   563       else {
   564 	//inTouch->gestureLast[j].dDist = 0;
   565 	//inTouch->gestureLast[j].dtheta = 0;
   566 	//inTouch->gestureLast[j].cv.x = 0;
   567 	//inTouch->gestureLast[j].cv.y = 0;
   568       }
   569       //inTouch->gestureLast[j].f.p.x = x;
   570       //inTouch->gestureLast[j].f.p.y = y;
   571       //break;
   572       //pressure?
   573     }
   574     
   575     if(event->type == SDL_FINGERDOWN) {
   576 
   577       inTouch->numDownFingers++;
   578       inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ 
   579 			     x)/inTouch->numDownFingers;
   580       inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   581 			     y)/inTouch->numDownFingers;
   582       printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   583 	     inTouch->centroid.x,inTouch->centroid.y);
   584       /*
   585 	inTouch->gestureLast[j].f.id = event->tfinger.fingerId;
   586 	inTouch->gestureLast[j].f.p.x  = x;
   587 	inTouch->gestureLast[j].f.p.y  = y;	
   588 	inTouch->gestureLast[j].cv.x = 0;
   589 	inTouch->gestureLast[j].cv.y = 0;
   590       */
   591 #ifdef ENABlE_DOLLAR
   592       inTouch->gestureLast[j].dollarPath.length = 0;
   593       inTouch->gestureLast[j].dollarPath.p[0].x = x;
   594       inTouch->gestureLast[j].dollarPath.p[0].y = y;
   595       inTouch->gestureLast[j].dollarPath.numPoints = 1;
   596 #endif
   597     }
   598   }
   599 }
   600 
   601   /* vi: set ts=4 sw=4 expandtab: */
   602