src/events/SDL_gesture.c
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Tue, 23 Jul 2013 17:40:18 -0700
changeset 7510 dbba26bab0f8
parent 7509 cf7c2e3493b2
child 7662 d31efd717578
permissions -rw-r--r--
= {{0}} generates a memset() in MSVC, which isn't linked. Whoops!
     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     SDL_FloatPoint points[DOLLARNPOINTS];
   395     int i;
   396     float bestDiff = 10000;
   397 
   398     SDL_memset(points, 0, sizeof(points));
   399 
   400     dollarNormalize(path,points);
   401 
   402     //PrintPath(points);
   403     *bestTempl = -1;
   404     for (i = 0; i < touch->numDollarTemplates; i++) {
   405         float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
   406         if (diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
   407     }
   408     return bestDiff;
   409 }
   410 
   411 int SDL_GestureAddTouch(SDL_TouchID touchId)
   412 {
   413     SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
   414                                                                      (SDL_numGestureTouches + 1) *
   415                                                                      sizeof(SDL_GestureTouch));
   416 
   417     if (!gestureTouch) {
   418         return SDL_OutOfMemory();
   419     }
   420 
   421     SDL_gestureTouch = gestureTouch;
   422 
   423     SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
   424     SDL_gestureTouch[SDL_numGestureTouches].id = touchId;
   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 {
   436     int i;
   437     for (i = 0; i < SDL_numGestureTouches; i++) {
   438         //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
   439         if (SDL_gestureTouch[i].id == id)
   440             return &SDL_gestureTouch[i];
   441     }
   442     return NULL;
   443 }
   444 
   445 int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
   446 {
   447     SDL_Event event;
   448     event.mgesture.type = SDL_MULTIGESTURE;
   449     event.mgesture.touchId = touch->id;
   450     event.mgesture.x = touch->centroid.x;
   451     event.mgesture.y = touch->centroid.y;
   452     event.mgesture.dTheta = dTheta;
   453     event.mgesture.dDist = dDist;
   454     event.mgesture.numFingers = touch->numDownFingers;
   455     return SDL_PushEvent(&event) > 0;
   456 }
   457 
   458 static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
   459                           SDL_GestureID gestureId,float error)
   460 {
   461     SDL_Event event;
   462     event.dgesture.type = SDL_DOLLARGESTURE;
   463     event.dgesture.touchId = touch->id;
   464     event.mgesture.x = touch->centroid.x;
   465     event.mgesture.y = touch->centroid.y;
   466     event.dgesture.gestureId = gestureId;
   467     event.dgesture.error = error;
   468     //A finger came up to trigger this event.
   469     event.dgesture.numFingers = touch->numDownFingers + 1;
   470     return SDL_PushEvent(&event) > 0;
   471 }
   472 
   473 
   474 static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
   475 {
   476     SDL_Event event;
   477     event.dgesture.type = SDL_DOLLARRECORD;
   478     event.dgesture.touchId = touch->id;
   479     event.dgesture.gestureId = gestureId;
   480     return SDL_PushEvent(&event) > 0;
   481 }
   482 
   483 
   484 void SDL_GestureProcessEvent(SDL_Event* event)
   485 {
   486     float x,y;
   487     SDL_FloatPoint path[DOLLARNPOINTS];
   488     int index;
   489     int i;
   490     float pathDx, pathDy;
   491     SDL_FloatPoint lastP;
   492     SDL_FloatPoint lastCentroid;
   493     float lDist;
   494     float Dist;
   495     float dtheta;
   496     float dDist;
   497 
   498     if (event->type == SDL_FINGERMOTION ||
   499         event->type == SDL_FINGERDOWN ||
   500         event->type == SDL_FINGERUP) {
   501         SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   502 
   503         //Shouldn't be possible
   504         if (inTouch == NULL) return;
   505 
   506         x = event->tfinger.x;
   507         y = event->tfinger.y;
   508 
   509         //Finger Up
   510         if (event->type == SDL_FINGERUP) {
   511             inTouch->numDownFingers--;
   512 
   513 #ifdef ENABLE_DOLLAR
   514             if (inTouch->recording) {
   515                 inTouch->recording = SDL_FALSE;
   516                 dollarNormalize(&inTouch->dollarPath,path);
   517                 //PrintPath(path);
   518                 if (recordAll) {
   519                     index = SDL_AddDollarGesture(NULL,path);
   520                     for (i = 0; i < SDL_numGestureTouches; i++)
   521                         SDL_gestureTouch[i].recording = SDL_FALSE;
   522                 }
   523                 else {
   524                     index = SDL_AddDollarGesture(inTouch,path);
   525                 }
   526 
   527                 if (index >= 0) {
   528                     SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   529                 }
   530                 else {
   531                     SDL_SendDollarRecord(inTouch,-1);
   532                 }
   533             }
   534             else {
   535                 int bestTempl;
   536                 float error;
   537                 error = dollarRecognize(&inTouch->dollarPath,
   538                                         &bestTempl,inTouch);
   539                 if (bestTempl >= 0){
   540                     //Send Event
   541                     unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   542                     SDL_SendGestureDollar(inTouch,gestureId,error);
   543                     //printf ("%s\n",);("Dollar error: %f\n",error);
   544                 }
   545             }
   546 #endif
   547             //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   548             if (inTouch->numDownFingers > 0) {
   549                 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   550                                        x)/inTouch->numDownFingers;
   551                 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   552                                        y)/inTouch->numDownFingers;
   553             }
   554         }
   555         else if (event->type == SDL_FINGERMOTION) {
   556             float dx = event->tfinger.dx;
   557             float dy = event->tfinger.dy;
   558 #ifdef ENABLE_DOLLAR
   559             SDL_DollarPath* path = &inTouch->dollarPath;
   560             if (path->numPoints < MAXPATHSIZE) {
   561                 path->p[path->numPoints].x = inTouch->centroid.x;
   562                 path->p[path->numPoints].y = inTouch->centroid.y;
   563                 pathDx =
   564                     (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   565                 pathDy =
   566                     (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   567                 path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   568                 path->numPoints++;
   569             }
   570 #endif
   571             lastP.x = x - dx;
   572             lastP.y = y - dy;
   573             lastCentroid = inTouch->centroid;
   574 
   575             inTouch->centroid.x += dx/inTouch->numDownFingers;
   576             inTouch->centroid.y += dy/inTouch->numDownFingers;
   577             //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
   578             if (inTouch->numDownFingers > 1) {
   579                 SDL_FloatPoint lv; //Vector from centroid to last x,y position
   580                 SDL_FloatPoint v; //Vector from centroid to current x,y position
   581                 //lv = inTouch->gestureLast[j].cv;
   582                 lv.x = lastP.x - lastCentroid.x;
   583                 lv.y = lastP.y - lastCentroid.y;
   584                 lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   585                 //printf("lDist = %f\n",lDist);
   586                 v.x = x - inTouch->centroid.x;
   587                 v.y = y - inTouch->centroid.y;
   588                 //inTouch->gestureLast[j].cv = v;
   589                 Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   590                 // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   591 
   592                 //Normalize Vectors to simplify angle calculation
   593                 lv.x/=lDist;
   594                 lv.y/=lDist;
   595                 v.x/=Dist;
   596                 v.y/=Dist;
   597                 dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   598 
   599                 dDist = (Dist - lDist);
   600                 if (lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   601 
   602                 //inTouch->gestureLast[j].dDist = dDist;
   603                 //inTouch->gestureLast[j].dtheta = dtheta;
   604 
   605                 //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   606                 //gdtheta = gdtheta*.9 + dtheta*.1;
   607                 //gdDist  =  gdDist*.9 +  dDist*.1
   608                 //knob.r += dDist/numDownFingers;
   609                 //knob.ang += dtheta;
   610                 //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   611                 //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   612                 SDL_SendGestureMulti(inTouch,dtheta,dDist);
   613             }
   614             else {
   615                 //inTouch->gestureLast[j].dDist = 0;
   616                 //inTouch->gestureLast[j].dtheta = 0;
   617                 //inTouch->gestureLast[j].cv.x = 0;
   618                 //inTouch->gestureLast[j].cv.y = 0;
   619             }
   620             //inTouch->gestureLast[j].f.p.x = x;
   621             //inTouch->gestureLast[j].f.p.y = y;
   622             //break;
   623             //pressure?
   624         }
   625 
   626         if (event->type == SDL_FINGERDOWN) {
   627 
   628             inTouch->numDownFingers++;
   629             inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
   630                                    x)/inTouch->numDownFingers;
   631             inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   632                                    y)/inTouch->numDownFingers;
   633             //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   634             //     inTouch->centroid.x,inTouch->centroid.y);
   635 
   636 #ifdef ENABLE_DOLLAR
   637             inTouch->dollarPath.length = 0;
   638             inTouch->dollarPath.p[0].x = x;
   639             inTouch->dollarPath.p[0].y = y;
   640             inTouch->dollarPath.numPoints = 1;
   641 #endif
   642         }
   643     }
   644 }
   645 
   646 /* vi: set ts=4 sw=4 expandtab: */