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