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