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

Latest commit

 

History

History
executable file
·
663 lines (563 loc) · 20.8 KB

SDL_gesture.c

File metadata and controls

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