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