src/events/SDL_gesture.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sat, 01 Jun 2013 21:09:36 +0200
changeset 7252 8ecb54eeaeec
parent 7191 75360622e65f
child 7508 1f64c6874619
permissions -rw-r--r--
Corrected indentation of license.
     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     double ta = -M_PI/4;
   268     double tb = M_PI/4;
   269     double dt = M_PI/90;
   270     float x1 = (float)(PHI*ta + (1-PHI)*tb);
   271     float f1 = dollarDifference(points,templ,x1);
   272     float x2 = (float)((1-PHI)*ta + PHI*tb);
   273     float f2 = dollarDifference(points,templ,x2);
   274     while (SDL_fabs(ta-tb) > dt) {
   275         if (f1 < f2) {
   276             tb = x2;
   277             x2 = x1;
   278             f2 = f1;
   279             x1 = (float)(PHI*ta + (1-PHI)*tb);
   280             f1 = dollarDifference(points,templ,x1);
   281         }
   282         else {
   283             ta = x1;
   284             x1 = x2;
   285             f1 = f2;
   286             x2 = (float)((1-PHI)*ta + PHI*tb);
   287             f2 = dollarDifference(points,templ,x2);
   288         }
   289     }
   290     /*
   291       if (f1 <= f2)
   292           printf("Min angle (x1): %f\n",x1);
   293       else if (f1 >  f2)
   294           printf("Min angle (x2): %f\n",x2);
   295     */
   296     return SDL_min(f1,f2);
   297 }
   298 
   299 //DollarPath contains raw points, plus (possibly) the calculated length
   300 static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
   301 {
   302     int i;
   303     float interval;
   304     float dist;
   305     int numPoints = 0;
   306     SDL_FloatPoint centroid;
   307     float xmin,xmax,ymin,ymax;
   308     float ang;
   309     float w,h;
   310     float length = path->length;
   311 
   312     //Calculate length if it hasn't already been done
   313     if (length <= 0) {
   314         for (i=1;i < path->numPoints; i++) {
   315             float dx = path->p[i  ].x - path->p[i-1].x;
   316             float dy = path->p[i  ].y - path->p[i-1].y;
   317             length += (float)(SDL_sqrt(dx*dx+dy*dy));
   318         }
   319     }
   320 
   321     //Resample
   322     interval = length/(DOLLARNPOINTS - 1);
   323     dist = interval;
   324 
   325     centroid.x = 0;centroid.y = 0;
   326 
   327     //printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
   328     for (i = 1; i < path->numPoints; i++) {
   329         float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
   330                                    (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
   331         //printf("d = %f dist = %f/%f\n",d,dist,interval);
   332         while (dist + d > interval) {
   333             points[numPoints].x = path->p[i-1].x +
   334                 ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
   335             points[numPoints].y = path->p[i-1].y +
   336                 ((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
   337             centroid.x += points[numPoints].x;
   338             centroid.y += points[numPoints].y;
   339             numPoints++;
   340 
   341             dist -= interval;
   342         }
   343         dist += d;
   344     }
   345     if (numPoints < DOLLARNPOINTS-1) {
   346         SDL_SetError("ERROR: NumPoints = %i\n",numPoints);
   347         return 0;
   348     }
   349     //copy the last point
   350     points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
   351     numPoints = DOLLARNPOINTS;
   352 
   353     centroid.x /= numPoints;
   354     centroid.y /= numPoints;
   355 
   356     //printf("Centroid (%f,%f)",centroid.x,centroid.y);
   357     //Rotate Points so point 0 is left of centroid and solve for the bounding box
   358     xmin = centroid.x;
   359     xmax = centroid.x;
   360     ymin = centroid.y;
   361     ymax = centroid.y;
   362 
   363     ang = (float)(SDL_atan2(centroid.y - points[0].y,
   364                             centroid.x - points[0].x));
   365 
   366     for (i = 0; i<numPoints; i++) {
   367         float px = points[i].x;
   368         float py = points[i].y;
   369         points[i].x = (float)((px - centroid.x)*SDL_cos(ang) -
   370                               (py - centroid.y)*SDL_sin(ang) + centroid.x);
   371         points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
   372                               (py - centroid.y)*SDL_cos(ang) + centroid.y);
   373 
   374 
   375         if (points[i].x < xmin) xmin = points[i].x;
   376         if (points[i].x > xmax) xmax = points[i].x;
   377         if (points[i].y < ymin) ymin = points[i].y;
   378         if (points[i].y > ymax) ymax = points[i].y;
   379     }
   380 
   381     //Scale points to DOLLARSIZE, and translate to the origin
   382     w = xmax-xmin;
   383     h = ymax-ymin;
   384 
   385     for (i=0; i<numPoints; i++) {
   386         points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
   387         points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
   388     }
   389     return numPoints;
   390 }
   391 
   392 static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch)
   393 {
   394 
   395     SDL_FloatPoint points[DOLLARNPOINTS];
   396     int i;
   397     float bestDiff = 10000;
   398 
   399     dollarNormalize(path,points);
   400 
   401     //PrintPath(points);
   402     *bestTempl = -1;
   403     for (i = 0; i < touch->numDollarTemplates; i++) {
   404         float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
   405         if (diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
   406     }
   407     return bestDiff;
   408 }
   409 
   410 int SDL_GestureAddTouch(SDL_TouchID touchId)
   411 {
   412     SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
   413                                                                      (SDL_numGestureTouches + 1) *
   414                                                                      sizeof(SDL_GestureTouch));
   415 
   416     if (!gestureTouch) {
   417         return SDL_OutOfMemory();
   418     }
   419 
   420     SDL_gestureTouch = gestureTouch;
   421 
   422     SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
   423     SDL_gestureTouch[SDL_numGestureTouches].id = touchId;
   424 
   425     SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
   426 
   427     SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
   428 
   429     SDL_numGestureTouches++;
   430     return 0;
   431 }
   432 
   433 static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
   434 {
   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)
   439             return &SDL_gestureTouch[i];
   440     }
   441     return NULL;
   442 }
   443 
   444 int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
   445 {
   446     SDL_Event event;
   447     event.mgesture.type = SDL_MULTIGESTURE;
   448     event.mgesture.touchId = touch->id;
   449     event.mgesture.x = touch->centroid.x;
   450     event.mgesture.y = touch->centroid.y;
   451     event.mgesture.dTheta = dTheta;
   452     event.mgesture.dDist = dDist;
   453     event.mgesture.numFingers = touch->numDownFingers;
   454     return SDL_PushEvent(&event) > 0;
   455 }
   456 
   457 static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
   458                           SDL_GestureID gestureId,float error)
   459 {
   460     SDL_Event event;
   461     event.dgesture.type = SDL_DOLLARGESTURE;
   462     event.dgesture.touchId = touch->id;
   463     event.mgesture.x = touch->centroid.x;
   464     event.mgesture.y = touch->centroid.y;
   465     event.dgesture.gestureId = gestureId;
   466     event.dgesture.error = error;
   467     //A finger came up to trigger this event.
   468     event.dgesture.numFingers = touch->numDownFingers + 1;
   469     return SDL_PushEvent(&event) > 0;
   470 }
   471 
   472 
   473 static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
   474 {
   475     SDL_Event event;
   476     event.dgesture.type = SDL_DOLLARRECORD;
   477     event.dgesture.touchId = touch->id;
   478     event.dgesture.gestureId = gestureId;
   479     return SDL_PushEvent(&event) > 0;
   480 }
   481 
   482 
   483 void SDL_GestureProcessEvent(SDL_Event* event)
   484 {
   485     float x,y;
   486     SDL_FloatPoint path[DOLLARNPOINTS];
   487     int index;
   488     int i;
   489     float pathDx, pathDy;
   490     SDL_FloatPoint lastP;
   491     SDL_FloatPoint lastCentroid;
   492     float lDist;
   493     float Dist;
   494     float dtheta;
   495     float dDist;
   496 
   497     if (event->type == SDL_FINGERMOTION ||
   498         event->type == SDL_FINGERDOWN ||
   499         event->type == SDL_FINGERUP) {
   500         SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   501 
   502         //Shouldn't be possible
   503         if (inTouch == NULL) return;
   504 
   505         x = event->tfinger.x;
   506         y = event->tfinger.y;
   507 
   508         //Finger Up
   509         if (event->type == SDL_FINGERUP) {
   510             inTouch->numDownFingers--;
   511 
   512 #ifdef ENABLE_DOLLAR
   513             if (inTouch->recording) {
   514                 inTouch->recording = SDL_FALSE;
   515                 dollarNormalize(&inTouch->dollarPath,path);
   516                 //PrintPath(path);
   517                 if (recordAll) {
   518                     index = SDL_AddDollarGesture(NULL,path);
   519                     for (i = 0; i < SDL_numGestureTouches; i++)
   520                         SDL_gestureTouch[i].recording = SDL_FALSE;
   521                 }
   522                 else {
   523                     index = SDL_AddDollarGesture(inTouch,path);
   524                 }
   525 
   526                 if (index >= 0) {
   527                     SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   528                 }
   529                 else {
   530                     SDL_SendDollarRecord(inTouch,-1);
   531                 }
   532             }
   533             else {
   534                 int bestTempl;
   535                 float error;
   536                 error = dollarRecognize(&inTouch->dollarPath,
   537                                         &bestTempl,inTouch);
   538                 if (bestTempl >= 0){
   539                     //Send Event
   540                     unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   541                     SDL_SendGestureDollar(inTouch,gestureId,error);
   542                     //printf ("%s\n",);("Dollar error: %f\n",error);
   543                 }
   544             }
   545 #endif
   546             //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   547             if (inTouch->numDownFingers > 0) {
   548                 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   549                                        x)/inTouch->numDownFingers;
   550                 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   551                                        y)/inTouch->numDownFingers;
   552             }
   553         }
   554         else if (event->type == SDL_FINGERMOTION) {
   555             float dx = event->tfinger.dx;
   556             float dy = event->tfinger.dy;
   557 #ifdef ENABLE_DOLLAR
   558             SDL_DollarPath* path = &inTouch->dollarPath;
   559             if (path->numPoints < MAXPATHSIZE) {
   560                 path->p[path->numPoints].x = inTouch->centroid.x;
   561                 path->p[path->numPoints].y = inTouch->centroid.y;
   562                 pathDx =
   563                     (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   564                 pathDy =
   565                     (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   566                 path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   567                 path->numPoints++;
   568             }
   569 #endif
   570             lastP.x = x - dx;
   571             lastP.y = y - dy;
   572             lastCentroid = inTouch->centroid;
   573 
   574             inTouch->centroid.x += dx/inTouch->numDownFingers;
   575             inTouch->centroid.y += dy/inTouch->numDownFingers;
   576             //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
   577             if (inTouch->numDownFingers > 1) {
   578                 SDL_FloatPoint lv; //Vector from centroid to last x,y position
   579                 SDL_FloatPoint v; //Vector from centroid to current x,y position
   580                 //lv = inTouch->gestureLast[j].cv;
   581                 lv.x = lastP.x - lastCentroid.x;
   582                 lv.y = lastP.y - lastCentroid.y;
   583                 lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   584                 //printf("lDist = %f\n",lDist);
   585                 v.x = x - inTouch->centroid.x;
   586                 v.y = y - inTouch->centroid.y;
   587                 //inTouch->gestureLast[j].cv = v;
   588                 Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   589                 // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   590 
   591                 //Normalize Vectors to simplify angle calculation
   592                 lv.x/=lDist;
   593                 lv.y/=lDist;
   594                 v.x/=Dist;
   595                 v.y/=Dist;
   596                 dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   597 
   598                 dDist = (Dist - lDist);
   599                 if (lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   600 
   601                 //inTouch->gestureLast[j].dDist = dDist;
   602                 //inTouch->gestureLast[j].dtheta = dtheta;
   603 
   604                 //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   605                 //gdtheta = gdtheta*.9 + dtheta*.1;
   606                 //gdDist  =  gdDist*.9 +  dDist*.1
   607                 //knob.r += dDist/numDownFingers;
   608                 //knob.ang += dtheta;
   609                 //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   610                 //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   611                 SDL_SendGestureMulti(inTouch,dtheta,dDist);
   612             }
   613             else {
   614                 //inTouch->gestureLast[j].dDist = 0;
   615                 //inTouch->gestureLast[j].dtheta = 0;
   616                 //inTouch->gestureLast[j].cv.x = 0;
   617                 //inTouch->gestureLast[j].cv.y = 0;
   618             }
   619             //inTouch->gestureLast[j].f.p.x = x;
   620             //inTouch->gestureLast[j].f.p.y = y;
   621             //break;
   622             //pressure?
   623         }
   624 
   625         if (event->type == SDL_FINGERDOWN) {
   626 
   627             inTouch->numDownFingers++;
   628             inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
   629                                    x)/inTouch->numDownFingers;
   630             inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   631                                    y)/inTouch->numDownFingers;
   632             //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   633             //     inTouch->centroid.x,inTouch->centroid.y);
   634 
   635 #ifdef ENABLE_DOLLAR
   636             inTouch->dollarPath.length = 0;
   637             inTouch->dollarPath.p[0].x = x;
   638             inTouch->dollarPath.p[0].y = y;
   639             inTouch->dollarPath.numPoints = 1;
   640 #endif
   641         }
   642     }
   643 }
   644 
   645 /* vi: set ts=4 sw=4 expandtab: */