src/events/SDL_gesture.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 7009 161b7b6a5303
child 7191 75360622e65f
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


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