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