Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
662 lines (558 loc) · 18.3 KB

SDL_gesture.c

File metadata and controls

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