src/events/SDL_gesture.c
changeset 6070 69b6275bb5dc
parent 6044 35448a5ea044
parent 6069 fbb37897c788
child 6071 72f06ae88e7e
equal deleted inserted replaced
6064:498e0234dfe6 6070:69b6275bb5dc
     9   Permission is granted to anyone to use this software for any purpose,
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    11   freely, subject to the following restrictions:
    12 
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    14   claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    15   in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    16   appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    18   misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    20 */
    21 
    21 
    22 #include "SDL_config.h"
    22 #include "SDL_config.h"
    23 
    23 
    34 
    34 
    35 //TODO: Replace with malloc
    35 //TODO: Replace with malloc
    36 
    36 
    37 #define MAXPATHSIZE 1024
    37 #define MAXPATHSIZE 1024
    38 
    38 
    39  
    39 
    40 
    40 
    41 
    41 
    42 #define DOLLARNPOINTS 64
    42 #define DOLLARNPOINTS 64
    43 #define DOLLARSIZE 256
    43 #define DOLLARSIZE 256
    44 
    44 
    45 #define ENABLE_DOLLAR
    45 #define ENABLE_DOLLAR
    46 
    46 
    47 #define PHI 0.618033989 
    47 #define PHI 0.618033989
    48 
    48 
    49 typedef struct {
    49 typedef struct {
    50   float x,y;
    50     float x,y;
    51 } SDL_FloatPoint;
    51 } SDL_FloatPoint;
    52 
    52 
    53 typedef struct {
    53 typedef struct {
    54   float length;
    54     float length;
    55   
    55 
    56   int numPoints;
    56     int numPoints;
    57   SDL_FloatPoint p[MAXPATHSIZE];
    57     SDL_FloatPoint p[MAXPATHSIZE];
    58 } SDL_DollarPath;
    58 } SDL_DollarPath;
    59 
    59 
    60 typedef struct {
    60 typedef struct {
    61   SDL_FloatPoint path[DOLLARNPOINTS];
    61     SDL_FloatPoint path[DOLLARNPOINTS];
    62   unsigned long hash;
    62     unsigned long hash;
    63 } SDL_DollarTemplate;
    63 } SDL_DollarTemplate;
    64 
    64 
    65 typedef struct {
    65 typedef struct {
    66   SDL_GestureID id;
    66     SDL_TouchID id;
    67   SDL_FloatPoint res;
    67     SDL_FloatPoint res;
    68   SDL_FloatPoint centroid;
    68     SDL_FloatPoint centroid;
    69   SDL_DollarPath dollarPath;
    69     SDL_DollarPath dollarPath;
    70   Uint16 numDownFingers;
    70     Uint16 numDownFingers;
    71 
    71 
    72   int numDollarTemplates;
    72     int numDollarTemplates;
    73   SDL_DollarTemplate *dollarTemplate;
    73     SDL_DollarTemplate *dollarTemplate;
    74 
    74 
    75   SDL_bool recording;
    75     SDL_bool recording;
    76 } SDL_GestureTouch;
    76 } SDL_GestureTouch;
    77 
    77 
    78 SDL_GestureTouch *SDL_gestureTouch;
    78 SDL_GestureTouch *SDL_gestureTouch;
    79 int SDL_numGestureTouches = 0;
    79 int SDL_numGestureTouches = 0;
    80 SDL_bool recordAll;
    80 SDL_bool recordAll;
    81 
    81 
    82 #if 0
    82 #if 0
    83 static void PrintPath(SDL_FloatPoint *path) {
    83 static void PrintPath(SDL_FloatPoint *path)
    84   int i;
    84 {
    85   printf("Path:");
    85     int i;
    86   for(i=0;i<DOLLARNPOINTS;i++) {
    86     printf("Path:");
    87     printf(" (%f,%f)",path[i].x,path[i].y);
    87     for (i=0; i<DOLLARNPOINTS; i++) {
    88   }
    88         printf(" (%f,%f)",path[i].x,path[i].y);
    89   printf("\n");
    89     }
       
    90     printf("\n");
    90 }
    91 }
    91 #endif
    92 #endif
    92 
    93 
    93 int SDL_RecordGesture(SDL_TouchID touchId) {
    94 int SDL_RecordGesture(SDL_TouchID touchId)
    94   int i;
    95 {
    95   if(touchId < 0) recordAll = SDL_TRUE;
    96     int i;
    96   for(i = 0;i < SDL_numGestureTouches; i++) {
    97     if (touchId < 0) recordAll = SDL_TRUE;
    97     if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
    98     for (i = 0; i < SDL_numGestureTouches; i++) {
    98       SDL_gestureTouch[i].recording = SDL_TRUE;
    99         if ((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
    99       if(touchId >= 0)
   100             SDL_gestureTouch[i].recording = SDL_TRUE;
   100         return 1;
   101             if (touchId >= 0)
   101     }      
   102                 return 1;
   102   }
   103         }
   103   return (touchId < 0);
   104     }
   104 }
   105     return (touchId < 0);
   105 
   106 }
   106 static unsigned long SDL_HashDollar(SDL_FloatPoint* points) {
   107 
   107   unsigned long hash = 5381;
   108 static unsigned long SDL_HashDollar(SDL_FloatPoint* points)
   108   int i;
   109 {
   109   for(i = 0;i < DOLLARNPOINTS; i++) { 
   110     unsigned long hash = 5381;
   110     hash = ((hash<<5) + hash) + (unsigned long)points[i].x;
   111     int i;
   111     hash = ((hash<<5) + hash) + (unsigned long)points[i].y;
   112     for (i = 0; i < DOLLARNPOINTS; i++) {
   112   }
   113         hash = ((hash<<5) + hash) + (unsigned long)points[i].x;
   113   return hash;
   114         hash = ((hash<<5) + hash) + (unsigned long)points[i].y;
   114 }
   115     }
   115 
   116     return hash;
   116 
   117 }
   117 static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src) {
   118 
   118   if(src == NULL) return 0;
   119 
   119 
   120 static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src)
   120   
   121 {
   121   //No Longer storing the Hash, rehash on load
   122     if (src == NULL) return 0;
   122   //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
   123 
   123   
   124 
   124   if(SDL_RWwrite(src,templ->path,
   125     //No Longer storing the Hash, rehash on load
   125                  sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) 
   126     //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
   126     return 0;
   127 
   127 
   128     if (SDL_RWwrite(src,templ->path,
   128   return 1;
   129                     sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
   129 }
   130         return 0;
   130 
   131 
   131 
   132     return 1;
   132 int SDL_SaveAllDollarTemplates(SDL_RWops *src) {  
   133 }
   133   int i,j,rtrn = 0;
   134 
   134   for(i = 0; i < SDL_numGestureTouches; i++) {
   135 
   135     SDL_GestureTouch* touch = &SDL_gestureTouch[i];
   136 int SDL_SaveAllDollarTemplates(SDL_RWops *src)
   136     for(j = 0;j < touch->numDollarTemplates; j++) {
   137 {
   137         rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
   138     int i,j,rtrn = 0;
   138     }
   139     for (i = 0; i < SDL_numGestureTouches; i++) {
   139   }
   140         SDL_GestureTouch* touch = &SDL_gestureTouch[i];
   140   return rtrn;  
   141         for (j = 0; j < touch->numDollarTemplates; j++) {
   141 }
   142             rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
   142 
   143         }
   143 int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src) {
   144     }
   144   int i,j;
   145     return rtrn;
   145   for(i = 0; i < SDL_numGestureTouches; i++) {
   146 }
   146     SDL_GestureTouch* touch = &SDL_gestureTouch[i];
   147 
   147     for(j = 0;j < touch->numDollarTemplates; j++) {
   148 int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src)
   148       if(touch->dollarTemplate[i].hash == gestureId) {
   149 {
   149         return SaveTemplate(&touch->dollarTemplate[i],src);
   150     int i,j;
   150       }
   151     for (i = 0; i < SDL_numGestureTouches; i++) {
   151     }
   152         SDL_GestureTouch* touch = &SDL_gestureTouch[i];
   152   }
   153         for (j = 0; j < touch->numDollarTemplates; j++) {
   153   SDL_SetError("Unknown gestureId");
   154             if (touch->dollarTemplate[i].hash == gestureId) {
   154   return -1;
   155                 return SaveTemplate(&touch->dollarTemplate[i],src);
       
   156             }
       
   157         }
       
   158     }
       
   159     SDL_SetError("Unknown gestureId");
       
   160     return -1;
   155 }
   161 }
   156 
   162 
   157 //path is an already sampled set of points
   163 //path is an already sampled set of points
   158 //Returns the index of the gesture on success, or -1
   164 //Returns the index of the gesture on success, or -1
   159 static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch,SDL_FloatPoint* path) {
   165 static int SDL_AddDollarGesture_one(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
   160   SDL_DollarTemplate* dollarTemplate;
   166 {
   161   SDL_DollarTemplate *templ;
   167     SDL_DollarTemplate* dollarTemplate;
   162   int i = 0;
   168     SDL_DollarTemplate *templ;
   163   if(inTouch == NULL) {
   169     int index;
   164     if(SDL_numGestureTouches == 0) return -1;
   170 
   165     for(i = 0;i < SDL_numGestureTouches; i++) {
   171     index = inTouch->numDollarTemplates;
   166       inTouch = &SDL_gestureTouch[i];
   172     dollarTemplate =
   167 
       
   168     dollarTemplate = 
       
   169         (SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
   173         (SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
   170                     (inTouch->numDollarTemplates + 1) * 
   174                                           (index + 1) *
   171                     sizeof(SDL_DollarTemplate));
   175                                           sizeof(SDL_DollarTemplate));
   172       if(!dollarTemplate) {
   176     if (!dollarTemplate) {
   173         SDL_OutOfMemory();
   177         SDL_OutOfMemory();
   174         return -1;
   178         return -1;
   175       }
   179     }
   176         
       
   177       inTouch->dollarTemplate = dollarTemplate;
       
   178 
       
   179     templ = 
       
   180         &inTouch->dollarTemplate[inTouch->numDollarTemplates];
       
   181       SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
       
   182       templ->hash = SDL_HashDollar(templ->path);
       
   183       inTouch->numDollarTemplates++;    
       
   184     }
       
   185     return inTouch->numDollarTemplates - 1;
       
   186   } else {
       
   187     SDL_DollarTemplate* dollarTemplate = 
       
   188       ( SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
       
   189                   (inTouch->numDollarTemplates + 1) * 
       
   190                   sizeof(SDL_DollarTemplate));
       
   191     if(!dollarTemplate) {
       
   192       SDL_OutOfMemory();
       
   193       return -1;
       
   194     }
       
   195     
       
   196     inTouch->dollarTemplate = dollarTemplate;
   180     inTouch->dollarTemplate = dollarTemplate;
   197 
   181 
   198     templ = 
   182     templ = &inTouch->dollarTemplate[index];
   199       &inTouch->dollarTemplate[inTouch->numDollarTemplates];
   183     SDL_memcpy(templ->path, path, DOLLARNPOINTS*sizeof(SDL_FloatPoint));
   200     SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
       
   201     templ->hash = SDL_HashDollar(templ->path);
   184     templ->hash = SDL_HashDollar(templ->path);
   202     inTouch->numDollarTemplates++;
   185     inTouch->numDollarTemplates++;
   203     return inTouch->numDollarTemplates - 1;
   186 
   204   }
   187     return index;
   205   return -1;
   188 }
   206 }
   189 
   207 
   190 static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
   208 int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) {
   191 {
   209   int i,loaded = 0;
   192     int index;
   210   SDL_GestureTouch *touch = NULL;
   193     int i = 0;
   211   if(src == NULL) return 0;
   194     if (inTouch == NULL) {
   212   if(touchId >= 0) {
   195         if (SDL_numGestureTouches == 0) return -1;
   213     for(i = 0;i < SDL_numGestureTouches; i++)
   196         for (i = 0; i < SDL_numGestureTouches; i++) {
   214       if(SDL_gestureTouch[i].id == touchId)
   197             inTouch = &SDL_gestureTouch[i];
   215         touch = &SDL_gestureTouch[i];
   198             index = SDL_AddDollarGesture_one(inTouch, path);
   216     if(touch == NULL) return -1;
   199             if (index < 0)
   217   }
   200                 return -1;
   218 
   201         }
   219   while(1) {
   202         // Use the index of the last one added.
   220     SDL_DollarTemplate templ;
   203         return index;
   221 
   204     } else {
   222     if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < 
   205         return SDL_AddDollarGesture_one(inTouch, path);
   223        DOLLARNPOINTS) break;
   206     }
   224 
   207     return -1;
   225     if(touchId >= 0) {
   208 }
   226       //printf("Adding loaded gesture to 1 touch\n");
   209 
   227       if(SDL_AddDollarGesture(touch,templ.path)) loaded++;
   210 int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
   228     }
   211 {
   229     else {
   212     int i,loaded = 0;
   230       //printf("Adding to: %i touches\n",SDL_numGestureTouches);
   213     SDL_GestureTouch *touch = NULL;
   231       for(i = 0;i < SDL_numGestureTouches; i++) {
   214     if (src == NULL) return 0;
   232         touch = &SDL_gestureTouch[i];
   215     if (touchId >= 0) {
   233         //printf("Adding loaded gesture to + touches\n");
   216         for (i = 0; i < SDL_numGestureTouches; i++)
   234         //TODO: What if this fails?
   217             if (SDL_gestureTouch[i].id == touchId)
   235         SDL_AddDollarGesture(touch,templ.path);        
   218                 touch = &SDL_gestureTouch[i];
   236       }
   219         if (touch == NULL) return -1;
   237       loaded++;
   220     }
   238     }
   221 
   239   }
   222     while (1) {
   240 
   223         SDL_DollarTemplate templ;
   241   return loaded; 
   224 
   242 }
   225         if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) <
   243 
   226            DOLLARNPOINTS) break;
   244 
   227 
   245 static float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang) {
   228         if (touchId >= 0) {
   246   //  SDL_FloatPoint p[DOLLARNPOINTS];
   229             //printf("Adding loaded gesture to 1 touch\n");
   247   float dist = 0;
   230             if (SDL_AddDollarGesture(touch, templ.path) >= 0)
   248   SDL_FloatPoint p;
   231                 loaded++;
   249   int i;
   232         }
   250   for(i = 0; i < DOLLARNPOINTS; i++) {
   233         else {
   251     p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
   234             //printf("Adding to: %i touches\n",SDL_numGestureTouches);
   252     p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
   235             for (i = 0; i < SDL_numGestureTouches; i++) {
   253     dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
   236                 touch = &SDL_gestureTouch[i];
   254                  (p.y-templ[i].y)*(p.y-templ[i].y)));
   237                 //printf("Adding loaded gesture to + touches\n");
   255   }
   238                 //TODO: What if this fails?
   256   return dist/DOLLARNPOINTS;
   239                 SDL_AddDollarGesture(touch,templ.path);
   257   
   240             }
   258 }
   241             loaded++;
   259 
   242         }
   260 static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ) {
   243     }
   261   //------------BEGIN DOLLAR BLACKBOX----------------//
   244 
   262   //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
   245     return loaded;
   263   //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
   246 }
   264   double ta = -M_PI/4;
   247 
   265   double tb = M_PI/4;
   248 
   266   double dt = M_PI/90;
   249 static float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang)
   267   float x1 = (float)(PHI*ta + (1-PHI)*tb);
   250 {
   268   float f1 = dollarDifference(points,templ,x1);
   251     //  SDL_FloatPoint p[DOLLARNPOINTS];
   269   float x2 = (float)((1-PHI)*ta + PHI*tb);
   252     float dist = 0;
   270   float f2 = dollarDifference(points,templ,x2);
   253     SDL_FloatPoint p;
   271   while(SDL_fabs(ta-tb) > dt) {
   254     int i;
   272     if(f1 < f2) {
   255     for (i = 0; i < DOLLARNPOINTS; i++) {
   273       tb = x2;
   256         p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
   274       x2 = x1;
   257         p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
   275       f2 = f1;
   258         dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
   276       x1 = (float)(PHI*ta + (1-PHI)*tb);
   259                                  (p.y-templ[i].y)*(p.y-templ[i].y)));
   277       f1 = dollarDifference(points,templ,x1);
   260     }
   278     }
   261     return dist/DOLLARNPOINTS;
   279     else {
   262 
   280       ta = x1;
   263 }
   281       x1 = x2;
   264 
   282       f1 = f2;
   265 static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
   283       x2 = (float)((1-PHI)*ta + PHI*tb);
   266 {
   284       f2 = dollarDifference(points,templ,x2);
   267     //------------BEGIN DOLLAR BLACKBOX----------------//
   285     }
   268     //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
   286   }
   269     //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
   287   /*
   270     double ta = -M_PI/4;
   288   if(f1 <= f2)
   271     double tb = M_PI/4;
   289     printf("Min angle (x1): %f\n",x1);
   272     double dt = M_PI/90;
   290   else if(f1 >  f2)
   273     float x1 = (float)(PHI*ta + (1-PHI)*tb);
   291     printf("Min angle (x2): %f\n",x2);
   274     float f1 = dollarDifference(points,templ,x1);
   292   */
   275     float x2 = (float)((1-PHI)*ta + PHI*tb);
   293   return SDL_min(f1,f2);  
   276     float f2 = dollarDifference(points,templ,x2);
       
   277     while (SDL_fabs(ta-tb) > dt) {
       
   278         if (f1 < f2) {
       
   279             tb = x2;
       
   280             x2 = x1;
       
   281             f2 = f1;
       
   282             x1 = (float)(PHI*ta + (1-PHI)*tb);
       
   283             f1 = dollarDifference(points,templ,x1);
       
   284         }
       
   285         else {
       
   286             ta = x1;
       
   287             x1 = x2;
       
   288             f1 = f2;
       
   289             x2 = (float)((1-PHI)*ta + PHI*tb);
       
   290             f2 = dollarDifference(points,templ,x2);
       
   291         }
       
   292     }
       
   293     /*
       
   294       if (f1 <= f2)
       
   295           printf("Min angle (x1): %f\n",x1);
       
   296       else if (f1 >  f2)
       
   297           printf("Min angle (x2): %f\n",x2);
       
   298     */
       
   299     return SDL_min(f1,f2);
   294 }
   300 }
   295 
   301 
   296 //DollarPath contains raw points, plus (possibly) the calculated length
   302 //DollarPath contains raw points, plus (possibly) the calculated length
   297 static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points) {
   303 static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
   298   int i;
   304 {
   299   float interval;
   305     int i;
   300   float dist;
   306     float interval;
   301   int numPoints = 0;
   307     float dist;
   302   SDL_FloatPoint centroid; 
   308     int numPoints = 0;
   303   float xmin,xmax,ymin,ymax;
   309     SDL_FloatPoint centroid;
   304   float ang;
   310     float xmin,xmax,ymin,ymax;
   305   float w,h;
   311     float ang;
   306   float length = path->length;
   312     float w,h;
   307 
   313     float length = path->length;
   308   //Calculate length if it hasn't already been done
   314 
   309   if(length <= 0) {
   315     //Calculate length if it hasn't already been done
   310     for(i=1;i<path->numPoints;i++) {
   316     if (length <= 0) {
   311       float dx = path->p[i  ].x - 
   317         for (i=1;i < path->numPoints; i++) {
   312                  path->p[i-1].x;
   318             float dx = path->p[i  ].x - path->p[i-1].x;
   313       float dy = path->p[i  ].y - 
   319             float dy = path->p[i  ].y - path->p[i-1].y;
   314                  path->p[i-1].y;
   320             length += (float)(SDL_sqrt(dx*dx+dy*dy));
   315       length += (float)(SDL_sqrt(dx*dx+dy*dy));
   321         }
   316     }
   322     }
   317   }
   323 
   318 
   324     //Resample
   319   //Resample
   325     interval = length/(DOLLARNPOINTS - 1);
   320   interval = length/(DOLLARNPOINTS - 1);
   326     dist = interval;
   321   dist = interval;
   327 
   322 
   328     centroid.x = 0;centroid.y = 0;
   323   centroid.x = 0;centroid.y = 0;
   329 
   324   
   330     //printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
   325   //printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
   331     for (i = 1; i < path->numPoints; i++) {
   326   for(i = 1;i < path->numPoints;i++) {
   332         float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
   327     float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
   333                                    (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
   328                              (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
   334         //printf("d = %f dist = %f/%f\n",d,dist,interval);
   329     //printf("d = %f dist = %f/%f\n",d,dist,interval);
   335         while (dist + d > interval) {
   330     while(dist + d > interval) {
   336             points[numPoints].x = path->p[i-1].x +
   331       points[numPoints].x = path->p[i-1].x + 
   337                 ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
   332         ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
   338             points[numPoints].y = path->p[i-1].y +
   333       points[numPoints].y = path->p[i-1].y + 
   339                 ((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
   334         ((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
   340             centroid.x += points[numPoints].x;
   335       centroid.x += points[numPoints].x;
   341             centroid.y += points[numPoints].y;
   336       centroid.y += points[numPoints].y;
   342             numPoints++;
   337       numPoints++;
   343 
   338 
   344             dist -= interval;
   339       dist -= interval;
   345         }
   340     }
   346         dist += d;
   341     dist += d;
   347     }
   342   }
   348     if (numPoints < DOLLARNPOINTS-1) {
   343   if(numPoints < DOLLARNPOINTS-1) {
   349         SDL_SetError("ERROR: NumPoints = %i\n",numPoints);
   344     SDL_SetError("ERROR: NumPoints = %i\n",numPoints); 
   350         return 0;
       
   351     }
       
   352     //copy the last point
       
   353     points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
       
   354     numPoints = DOLLARNPOINTS;
       
   355 
       
   356     centroid.x /= numPoints;
       
   357     centroid.y /= numPoints;
       
   358 
       
   359     //printf("Centroid (%f,%f)",centroid.x,centroid.y);
       
   360     //Rotate Points so point 0 is left of centroid and solve for the bounding box
       
   361     xmin = centroid.x;
       
   362     xmax = centroid.x;
       
   363     ymin = centroid.y;
       
   364     ymax = centroid.y;
       
   365 
       
   366     ang = (float)(SDL_atan2(centroid.y - points[0].y,
       
   367                             centroid.x - points[0].x));
       
   368 
       
   369     for (i = 0; i<numPoints; i++) {
       
   370         float px = points[i].x;
       
   371         float py = points[i].y;
       
   372         points[i].x = (float)((px - centroid.x)*SDL_cos(ang) -
       
   373                               (py - centroid.y)*SDL_sin(ang) + centroid.x);
       
   374         points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
       
   375                               (py - centroid.y)*SDL_cos(ang) + centroid.y);
       
   376 
       
   377 
       
   378         if (points[i].x < xmin) xmin = points[i].x;
       
   379         if (points[i].x > xmax) xmax = points[i].x;
       
   380         if (points[i].y < ymin) ymin = points[i].y;
       
   381         if (points[i].y > ymax) ymax = points[i].y;
       
   382     }
       
   383 
       
   384     //Scale points to DOLLARSIZE, and translate to the origin
       
   385     w = xmax-xmin;
       
   386     h = ymax-ymin;
       
   387 
       
   388     for (i=0; i<numPoints; i++) {
       
   389         points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
       
   390         points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
       
   391     }
       
   392     return numPoints;
       
   393 }
       
   394 
       
   395 static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch)
       
   396 {
       
   397 
       
   398     SDL_FloatPoint points[DOLLARNPOINTS];
       
   399     int i;
       
   400     float bestDiff = 10000;
       
   401 
       
   402     dollarNormalize(path,points);
       
   403 
       
   404     //PrintPath(points);
       
   405     *bestTempl = -1;
       
   406     for (i = 0; i < touch->numDollarTemplates; i++) {
       
   407         float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
       
   408         if (diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
       
   409     }
       
   410     return bestDiff;
       
   411 }
       
   412 
       
   413 int SDL_GestureAddTouch(SDL_Touch* touch)
       
   414 {
       
   415     SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
       
   416                                                                      (SDL_numGestureTouches + 1) *
       
   417                                                                      sizeof(SDL_GestureTouch));
       
   418 
       
   419     if (!gestureTouch) {
       
   420         SDL_OutOfMemory();
       
   421         return -1;
       
   422     }
       
   423 
       
   424     SDL_gestureTouch = gestureTouch;
       
   425 
       
   426     SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
       
   427     SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres;
       
   428     SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
       
   429 
       
   430     SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
       
   431     SDL_gestureTouch[SDL_numGestureTouches].id = touch->id;
       
   432 
       
   433     SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
       
   434 
       
   435     SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
       
   436 
       
   437     SDL_numGestureTouches++;
   345     return 0;
   438     return 0;
   346   }
   439 }
   347   //copy the last point
   440 
   348   points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
   441 static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
   349   numPoints = DOLLARNPOINTS;
   442 {
   350 
   443     int i;
   351   centroid.x /= numPoints;
   444     for (i = 0; i < SDL_numGestureTouches; i++) {
   352   centroid.y /= numPoints;
   445         //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
   353  
   446         if (SDL_gestureTouch[i].id == id)
   354   //printf("Centroid (%f,%f)",centroid.x,centroid.y);
   447             return &SDL_gestureTouch[i];
   355   //Rotate Points so point 0 is left of centroid and solve for the bounding box
   448     }
   356   xmin = centroid.x;
   449     return NULL;
   357   xmax = centroid.x;
   450 }
   358   ymin = centroid.y;
   451 
   359   ymax = centroid.y;
   452 int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
   360   
   453 {
   361   ang = (float)(SDL_atan2(centroid.y - points[0].y,
   454     SDL_Event event;
   362                     centroid.x - points[0].x));
   455     event.mgesture.type = SDL_MULTIGESTURE;
   363 
   456     event.mgesture.touchId = touch->id;
   364   for(i = 0;i<numPoints;i++) {                                               
   457     event.mgesture.x = touch->centroid.x;
   365     float px = points[i].x;
   458     event.mgesture.y = touch->centroid.y;
   366     float py = points[i].y;
   459     event.mgesture.dTheta = dTheta;
   367     points[i].x = (float)((px - centroid.x)*SDL_cos(ang) - 
   460     event.mgesture.dDist = dDist;
   368                   (py - centroid.y)*SDL_sin(ang) + centroid.x);
   461     event.mgesture.numFingers = touch->numDownFingers;
   369     points[i].y = (float)((px - centroid.x)*SDL_sin(ang) + 
   462     return SDL_PushEvent(&event) > 0;
   370                   (py - centroid.y)*SDL_cos(ang) + centroid.y);
       
   371 
       
   372 
       
   373     if(points[i].x < xmin) xmin = points[i].x;
       
   374     if(points[i].x > xmax) xmax = points[i].x; 
       
   375     if(points[i].y < ymin) ymin = points[i].y;
       
   376     if(points[i].y > ymax) ymax = points[i].y;
       
   377   }
       
   378 
       
   379   //Scale points to DOLLARSIZE, and translate to the origin
       
   380   w = xmax-xmin;
       
   381   h = ymax-ymin;
       
   382 
       
   383   for(i=0;i<numPoints;i++) {
       
   384     points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
       
   385     points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
       
   386   }  
       
   387   return numPoints;
       
   388 }
       
   389 
       
   390 static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch) {
       
   391         
       
   392         SDL_FloatPoint points[DOLLARNPOINTS];
       
   393         int i;
       
   394         float bestDiff = 10000;
       
   395 
       
   396         dollarNormalize(path,points);
       
   397 
       
   398         //PrintPath(points);
       
   399         *bestTempl = -1;
       
   400         for(i = 0;i < touch->numDollarTemplates;i++) {
       
   401                 float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
       
   402                 if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
       
   403         }
       
   404         return bestDiff;
       
   405 }
       
   406 
       
   407 int SDL_GestureAddTouch(SDL_Touch* touch) {  
       
   408   SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
       
   409                                                (SDL_numGestureTouches + 1) *
       
   410                                                sizeof(SDL_GestureTouch));
       
   411 
       
   412   if(!gestureTouch) {
       
   413     SDL_OutOfMemory();
       
   414     return -1;
       
   415   }
       
   416 
       
   417   SDL_gestureTouch = gestureTouch;
       
   418 
       
   419   SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
       
   420   SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres;
       
   421   SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
       
   422 
       
   423   SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
       
   424   SDL_gestureTouch[SDL_numGestureTouches].id = touch->id;
       
   425 
       
   426   SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
       
   427 
       
   428   SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
       
   429 
       
   430   SDL_numGestureTouches++;
       
   431   return 0;
       
   432 }
       
   433 
       
   434 static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) {
       
   435   int i;
       
   436   for(i = 0;i < SDL_numGestureTouches; i++) {
       
   437     //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
       
   438     if(SDL_gestureTouch[i].id == id) return &SDL_gestureTouch[i];
       
   439   }
       
   440   return NULL;
       
   441 }
       
   442 
       
   443 static int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist) {
       
   444   SDL_Event event;
       
   445   event.mgesture.type = SDL_MULTIGESTURE;
       
   446   event.mgesture.touchId = touch->id;
       
   447   event.mgesture.x = touch->centroid.x;
       
   448   event.mgesture.y = touch->centroid.y;
       
   449   event.mgesture.dTheta = dTheta;
       
   450   event.mgesture.dDist = dDist;  
       
   451   event.mgesture.numFingers = touch->numDownFingers;
       
   452   return SDL_PushEvent(&event) > 0;
       
   453 }
   463 }
   454 
   464 
   455 static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
   465 static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
   456                           SDL_GestureID gestureId,float error) {
   466                           SDL_GestureID gestureId,float error)
   457   SDL_Event event;
   467 {
   458   event.dgesture.type = SDL_DOLLARGESTURE;
   468     SDL_Event event;
   459   event.dgesture.touchId = touch->id;
   469     event.dgesture.type = SDL_DOLLARGESTURE;
   460   /*
   470     event.dgesture.touchId = touch->id;
       
   471     /*
   461     //TODO: Add this to give location of gesture?
   472     //TODO: Add this to give location of gesture?
   462   event.mgesture.x = touch->centroid.x;
   473     event.mgesture.x = touch->centroid.x;
   463   event.mgesture.y = touch->centroid.y;
   474     event.mgesture.y = touch->centroid.y;
   464   */
   475     */
   465   event.dgesture.gestureId = gestureId;
   476     event.dgesture.gestureId = gestureId;
   466   event.dgesture.error = error;  
   477     event.dgesture.error = error;
   467   //A finger came up to trigger this event.
   478     //A finger came up to trigger this event.
   468   event.dgesture.numFingers = touch->numDownFingers + 1; 
   479     event.dgesture.numFingers = touch->numDownFingers + 1;
   469   return SDL_PushEvent(&event) > 0;
   480     return SDL_PushEvent(&event) > 0;
   470 }
   481 }
   471 
   482 
   472 
   483 
   473 static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId) {
   484 static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
   474   SDL_Event event;
   485 {
   475   event.dgesture.type = SDL_DOLLARRECORD;
   486     SDL_Event event;
   476   event.dgesture.touchId = touch->id;
   487     event.dgesture.type = SDL_DOLLARRECORD;
   477   event.dgesture.gestureId = gestureId;
   488     event.dgesture.touchId = touch->id;
   478   return SDL_PushEvent(&event) > 0;
   489     event.dgesture.gestureId = gestureId;
       
   490     return SDL_PushEvent(&event) > 0;
   479 }
   491 }
   480 
   492 
   481 
   493 
   482 void SDL_GestureProcessEvent(SDL_Event* event)
   494 void SDL_GestureProcessEvent(SDL_Event* event)
   483 {
   495 {
   484   float x,y; 
   496     float x,y;
   485   SDL_FloatPoint path[DOLLARNPOINTS];
   497     SDL_FloatPoint path[DOLLARNPOINTS];
   486   int index;
   498     int index;
   487   int i;
   499     int i;
   488   float pathDx, pathDy;
   500     float pathDx, pathDy;
   489   SDL_FloatPoint lastP;
   501     SDL_FloatPoint lastP;
   490   SDL_FloatPoint lastCentroid;
   502     SDL_FloatPoint lastCentroid;
   491   float lDist;
   503     float lDist;
   492   float Dist;
   504     float Dist;
   493   float dtheta;
   505     float dtheta;
   494   float dDist;
   506     float dDist;
   495 
   507 
   496   if(event->type == SDL_FINGERMOTION || 
   508     if (event->type == SDL_FINGERMOTION ||
   497      event->type == SDL_FINGERDOWN ||
   509         event->type == SDL_FINGERDOWN ||
   498      event->type == SDL_FINGERUP) {
   510         event->type == SDL_FINGERUP) {
   499     SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   511         SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   500     
   512 
   501     //Shouldn't be possible
   513         //Shouldn't be possible
   502     if(inTouch == NULL) return;
   514         if (inTouch == NULL) return;
   503     
   515 
   504     //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
   516         //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
   505     //           (int)event->tfinger.y,
   517         //           (int)event->tfinger.y,
   506     //   (int)inTouch->res.x,(int)inTouch->res.y);
   518         //   (int)inTouch->res.x,(int)inTouch->res.y);
   507 
   519 
   508     
   520 
   509     x = ((float)event->tfinger.x)/(float)inTouch->res.x;
   521         x = ((float)event->tfinger.x)/(float)inTouch->res.x;
   510     y = ((float)event->tfinger.y)/(float)inTouch->res.y;   
   522         y = ((float)event->tfinger.y)/(float)inTouch->res.y;
   511 
   523 
   512 
   524 
   513     //Finger Up
   525         //Finger Up
   514     if(event->type == SDL_FINGERUP) {
   526         if (event->type == SDL_FINGERUP) {
   515       inTouch->numDownFingers--;
   527             inTouch->numDownFingers--;
   516       
   528 
   517 #ifdef ENABLE_DOLLAR
   529 #ifdef ENABLE_DOLLAR
   518       if(inTouch->recording) {
   530             if (inTouch->recording) {
   519         inTouch->recording = SDL_FALSE;        
   531                 inTouch->recording = SDL_FALSE;
   520         dollarNormalize(&inTouch->dollarPath,path);
   532                 dollarNormalize(&inTouch->dollarPath,path);
   521         //PrintPath(path);
   533                 //PrintPath(path);
   522         if(recordAll) {
   534                 if (recordAll) {
   523           index = SDL_AddDollarGesture(NULL,path);
   535                     index = SDL_AddDollarGesture(NULL,path);
   524           for(i = 0;i < SDL_numGestureTouches; i++)
   536                     for (i = 0; i < SDL_numGestureTouches; i++)
   525             SDL_gestureTouch[i].recording = SDL_FALSE;
   537                         SDL_gestureTouch[i].recording = SDL_FALSE;
   526         }
   538                 }
   527         else {
   539                 else {
   528           index = SDL_AddDollarGesture(inTouch,path);
   540                     index = SDL_AddDollarGesture(inTouch,path);
   529         }
   541                 }
   530         
   542 
   531         if(index >= 0) {
   543                 if (index >= 0) {
   532           SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   544                     SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   533         }
   545                 }
   534         else {
   546                 else {
   535           SDL_SendDollarRecord(inTouch,-1);
   547                     SDL_SendDollarRecord(inTouch,-1);
   536         }
   548                 }
   537       }
   549             }
   538       else {        
   550             else {
   539         int bestTempl;
   551                 int bestTempl;
   540         float error;
   552                 float error;
   541         error = dollarRecognize(&inTouch->dollarPath,
   553                 error = dollarRecognize(&inTouch->dollarPath,
   542                                 &bestTempl,inTouch);
   554                                         &bestTempl,inTouch);
   543         if(bestTempl >= 0){
   555                 if (bestTempl >= 0){
   544           //Send Event
   556                     //Send Event
   545           unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   557                     unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   546           SDL_SendGestureDollar(inTouch,gestureId,error);
   558                     SDL_SendGestureDollar(inTouch,gestureId,error);
   547           //printf ("%s\n",);("Dollar error: %f\n",error);
   559                     //printf ("%s\n",);("Dollar error: %f\n",error);
   548         }
   560                 }
   549       }
   561             }
   550 #endif 
   562 #endif
   551       //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   563             //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   552       if(inTouch->numDownFingers > 0) {
   564             if (inTouch->numDownFingers > 0) {
   553         inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   565                 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   554                                x)/inTouch->numDownFingers;
   566                                        x)/inTouch->numDownFingers;
   555         inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   567                 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   556                                y)/inTouch->numDownFingers;
   568                                        y)/inTouch->numDownFingers;
   557       }
   569             }
   558     }
   570         }
   559     else if(event->type == SDL_FINGERMOTION) {
   571         else if (event->type == SDL_FINGERMOTION) {
   560       float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
   572             float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
   561       float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
   573             float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
   562       //printf("dx,dy: (%f,%f)\n",dx,dy); 
   574             //printf("dx,dy: (%f,%f)\n",dx,dy);
   563 #ifdef ENABLE_DOLLAR
   575 #ifdef ENABLE_DOLLAR
   564       SDL_DollarPath* path = &inTouch->dollarPath;
   576             SDL_DollarPath* path = &inTouch->dollarPath;
   565       if(path->numPoints < MAXPATHSIZE) {
   577             if (path->numPoints < MAXPATHSIZE) {
   566         path->p[path->numPoints].x = inTouch->centroid.x;
   578                 path->p[path->numPoints].x = inTouch->centroid.x;
   567         path->p[path->numPoints].y = inTouch->centroid.y;
   579                 path->p[path->numPoints].y = inTouch->centroid.y;
   568         pathDx = 
   580                 pathDx =
   569           (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   581                     (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   570         pathDy = 
   582                 pathDy =
   571           (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   583                     (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   572         path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   584                 path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   573         path->numPoints++;
   585                 path->numPoints++;
   574       }
   586             }
   575 #endif
   587 #endif
   576       lastP.x = x - dx;
   588             lastP.x = x - dx;
   577       lastP.y = y - dy;
   589             lastP.y = y - dy;
   578       lastCentroid = inTouch->centroid;
   590             lastCentroid = inTouch->centroid;
   579       
   591 
   580       inTouch->centroid.x += dx/inTouch->numDownFingers;
   592             inTouch->centroid.x += dx/inTouch->numDownFingers;
   581       inTouch->centroid.y += dy/inTouch->numDownFingers;
   593             inTouch->centroid.y += dy/inTouch->numDownFingers;
   582       //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
   594             //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
   583       if(inTouch->numDownFingers > 1) {
   595             if (inTouch->numDownFingers > 1) {
   584         SDL_FloatPoint lv; //Vector from centroid to last x,y position
   596                 SDL_FloatPoint lv; //Vector from centroid to last x,y position
   585         SDL_FloatPoint v; //Vector from centroid to current x,y position
   597                 SDL_FloatPoint v; //Vector from centroid to current x,y position
   586         //lv = inTouch->gestureLast[j].cv;
   598                 //lv = inTouch->gestureLast[j].cv;
   587         lv.x = lastP.x - lastCentroid.x;
   599                 lv.x = lastP.x - lastCentroid.x;
   588         lv.y = lastP.y - lastCentroid.y;
   600                 lv.y = lastP.y - lastCentroid.y;
   589         lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   601                 lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   590         //printf("lDist = %f\n",lDist);
   602                 //printf("lDist = %f\n",lDist);
   591         v.x = x - inTouch->centroid.x;
   603                 v.x = x - inTouch->centroid.x;
   592         v.y = y - inTouch->centroid.y;
   604                 v.y = y - inTouch->centroid.y;
   593         //inTouch->gestureLast[j].cv = v;
   605                 //inTouch->gestureLast[j].cv = v;
   594         Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   606                 Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   595         // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   607                 // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   596         
   608 
   597         //Normalize Vectors to simplify angle calculation
   609                 //Normalize Vectors to simplify angle calculation
   598         lv.x/=lDist;
   610                 lv.x/=lDist;
   599         lv.y/=lDist;
   611                 lv.y/=lDist;
   600         v.x/=Dist;
   612                 v.x/=Dist;
   601         v.y/=Dist;
   613                 v.y/=Dist;
   602         dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   614                 dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   603         
   615 
   604         dDist = (Dist - lDist);
   616                 dDist = (Dist - lDist);
   605         if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   617                 if (lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   606         
   618 
   607         //inTouch->gestureLast[j].dDist = dDist;
   619                 //inTouch->gestureLast[j].dDist = dDist;
   608         //inTouch->gestureLast[j].dtheta = dtheta;
   620                 //inTouch->gestureLast[j].dtheta = dtheta;
   609         
   621 
   610         //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   622                 //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   611         //gdtheta = gdtheta*.9 + dtheta*.1;
   623                 //gdtheta = gdtheta*.9 + dtheta*.1;
   612         //gdDist  =  gdDist*.9 +  dDist*.1
   624                 //gdDist  =  gdDist*.9 +  dDist*.1
   613         //knob.r += dDist/numDownFingers;
   625                 //knob.r += dDist/numDownFingers;
   614         //knob.ang += dtheta;
   626                 //knob.ang += dtheta;
   615         //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   627                 //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   616         //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   628                 //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   617         SDL_SendGestureMulti(inTouch,dtheta,dDist);
   629                 SDL_SendGestureMulti(inTouch,dtheta,dDist);
   618       }
   630             }
   619       else {
   631             else {
   620         //inTouch->gestureLast[j].dDist = 0;
   632                 //inTouch->gestureLast[j].dDist = 0;
   621         //inTouch->gestureLast[j].dtheta = 0;
   633                 //inTouch->gestureLast[j].dtheta = 0;
   622         //inTouch->gestureLast[j].cv.x = 0;
   634                 //inTouch->gestureLast[j].cv.x = 0;
   623         //inTouch->gestureLast[j].cv.y = 0;
   635                 //inTouch->gestureLast[j].cv.y = 0;
   624       }
   636             }
   625       //inTouch->gestureLast[j].f.p.x = x;
   637             //inTouch->gestureLast[j].f.p.x = x;
   626       //inTouch->gestureLast[j].f.p.y = y;
   638             //inTouch->gestureLast[j].f.p.y = y;
   627       //break;
   639             //break;
   628       //pressure?
   640             //pressure?
   629     }
   641         }
   630     
   642 
   631     if(event->type == SDL_FINGERDOWN) {
   643         if (event->type == SDL_FINGERDOWN) {
   632 
   644 
   633       inTouch->numDownFingers++;
   645             inTouch->numDownFingers++;
   634       inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ 
   646             inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
   635                              x)/inTouch->numDownFingers;
   647                                    x)/inTouch->numDownFingers;
   636       inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   648             inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   637                              y)/inTouch->numDownFingers;
   649                                    y)/inTouch->numDownFingers;
   638       //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   650             //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   639       //     inTouch->centroid.x,inTouch->centroid.y);
   651             //     inTouch->centroid.x,inTouch->centroid.y);
   640 
   652 
   641 #ifdef ENABLE_DOLLAR
   653 #ifdef ENABLE_DOLLAR
   642       inTouch->dollarPath.length = 0;
   654             inTouch->dollarPath.length = 0;
   643       inTouch->dollarPath.p[0].x = x;
   655             inTouch->dollarPath.p[0].x = x;
   644       inTouch->dollarPath.p[0].y = y;
   656             inTouch->dollarPath.p[0].y = y;
   645       inTouch->dollarPath.numPoints = 1;
   657             inTouch->dollarPath.numPoints = 1;
   646 #endif
   658 #endif
   647     }
   659         }
   648   }
   660     }
   649 }
   661 }
   650 
   662 
   651   /* vi: set ts=4 sw=4 expandtab: */
   663 /* vi: set ts=4 sw=4 expandtab: */
   652