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