Gesture Library
multistroke.c
Go to the documentation of this file.
1 #include "multistroke.h"
2 
3 #include "math.h"
4 #include "stroke.h"
5 #include "utils.h"
6 
8 
10  for (int i = 0; i < MAX_TOUCHES; i++) {
12  multistroke_d[i].uid = 0;
13  multistroke_d[i].size = 0;
14  multistroke_d[i].dx = 0;
15  multistroke_d[i].dy = 0;
16  multistroke_d[i].rotation = 0;
17  multistroke_d[i].scale = 1;
18  multistroke_d[i].dx0 = 0;
19  multistroke_d[i].dy0 = 0;
20  multistroke_d[i].rotation0 = 0;
21  multistroke_d[i].scale0 = 1;
22  multistroke_d[i].cx = 0;
23  multistroke_d[i].cy = 0;
24  for (int j = 0; j < MAX_TOUCHES; j++) {
25  multistroke_d[i].strokes[j] = 0;
26  multistroke_d[i].sx[j] = 0;
27  multistroke_d[i].sy[j] = 0;
28  }
29  }
30 }
31 
32 static void update_multistroke(multistroke_t* ms, int group);
33 static void zero_multistroke(multistroke_t* ms);
34 static void calculate_center(multistroke_t* ms);
35 static void calculate_transform(multistroke_t* ms);
36 
38  int free_index = -1;
39  const stroke_t* strokes = get_stroke();
40  for (int i = 0; i < MAX_TOUCHES; i++) {
41  if (multistroke_d[i].uid == strokes[event->group].uid && multistroke_d[i].size) {
42  update_multistroke(multistroke_d + i, event->group);
43  return;
44  } else if (free_index < 0 && !multistroke_d[i].size) {
45  free_index = i;
46  }
47  }
48  if (free_index >= 0 && strokes[event->group].state == RECOGNIZER_STATE_IN_PROGRESS) {
49  update_multistroke(multistroke_d + free_index, event->group);
50  }
51 }
52 
54  return multistroke_d;
55 }
56 
57 static void update_multistroke(multistroke_t* ms, int group) {
58  const stroke_t* strokes = get_stroke();
59  ms->uid = strokes[group].uid;
60  if (!ms->strokes[group]) {
61  switch (ms->state) {
64  ms->strokes[group] = 1;
65  zero_multistroke(ms);
66  calculate_center(ms);
67  if (ms->size > 1) {
69  }
70  break;
72  ms->strokes[group] = 1;
73  calculate_center(ms);
74  break;
75  default:
76  break;
77  }
78  } else {
80  calculate_transform(ms);
81  if (strokes[group].state == RECOGNIZER_STATE_COMPLETED) {
82  ms->strokes[group] = 0;
83  calculate_center(ms);
84  if (ms->size < 2) {
86  }
87  }
88  } else if (strokes[group].state == RECOGNIZER_STATE_COMPLETED) {
89  ms->strokes[group] = 0;
90  calculate_center(ms);
91  }
92  }
93 }
94 
95 static void zero_multistroke(multistroke_t* ms) {
96  ms->dx = 0;
97  ms->dy = 0;
98  ms->rotation = 0;
99  ms->scale = 1;
100 }
101 
102 static void calculate_center(multistroke_t* ms) {
103  // copy last translation and rotation and scaling
104  ms->dx0 = ms->dx;
105  ms->dy0 = ms->dy;
106  ms->rotation0 = ms->rotation;
107  ms->scale0 = ms->scale;
108 
109  // calculate new center
110  const stroke_t* strokes = get_stroke();
111  ms->size = 0;
112  float x = 0;
113  float y = 0;
114  for (int i = 0; i < MAX_TOUCHES; i++) {
115  if (ms->strokes[i]) {
116  x += strokes[i].x;
117  y += strokes[i].y;
118  ms->size++;
119  }
120  }
121  ms->cx = x / ms->size;
122  ms->cy = y / ms->size;
123 
124  // calculate new scaled offsets
125  float dx[MAX_TOUCHES];
126  float dy[MAX_TOUCHES];
127  float a = 0;
128  for (int i = 0; i < MAX_TOUCHES; i++) {
129  if (ms->strokes[i]) {
130  dx[i] = strokes[i].x - ms->cx;
131  dy[i] = strokes[i].y - ms->cy;
132  a += SQUARE(dx[i]) + SQUARE(dy[i]);
133  }
134  }
135  for (int i = 0; i < MAX_TOUCHES; i++) {
136  if (ms->strokes[i]) {
137  ms->sx[i] = dx[i] / a;
138  ms->sy[i] = dy[i] / a;
139  }
140  }
141 }
142 
143 static void calculate_transform(multistroke_t* ms) {
144  // calculate current center
145  const stroke_t* strokes = get_stroke();
146  float cx = 0;
147  float cy = 0;
148  for (int i = 0; i < MAX_TOUCHES; i++) {
149  if (ms->strokes[i]) {
150  cx += strokes[i].x;
151  cy += strokes[i].y;
152  }
153  }
154  cx /= ms->size;
155  cy /= ms->size;
156 
157  // calculate translation
158  ms->dx = ms->dx0 + (cx - ms->cx);
159  ms->dy = ms->dy0 + (cy - ms->cy);
160 
161  // calculate rotation and scaling
162  float a = 0;
163  float b = 0;
164  for (int i = 0; i < MAX_TOUCHES; i++) {
165  if (ms->strokes[i]) {
166  float dx = strokes[i].x - cx;
167  float dy = strokes[i].y - cy;
168  a += ms->sx[i] * dx + ms->sy[i] * dy;
169  b += ms->sx[i] * dy - ms->sy[i] * dx;
170  }
171  }
172  ms->rotation = ms->rotation0 + atan2f(b, a);
173  ms->scale = ms->scale0 * sqrtf(SQUARE_SUM(a, b));
174 }
#define MAX_TOUCHES
Definition: gestureparams.h:5
void recognize_multistroke(const touch_event_t *event)
Recognize multistroke gesture. This gesture allows the number of fingers to change.
Definition: multistroke.c:37
void init_multistroke()
Initialize multistroke data structures.
Definition: multistroke.c:9
multistroke_t multistroke_d[MAX_TOUCHES]
Definition: multistroke.c:7
const multistroke_t * get_multistroke()
Access array of multistroke_t of size MAX_TOUCHES.
Definition: multistroke.c:53
state
This represents the state of individual gesture recognizers.
Definition: recognizer.h:4
@ RECOGNIZER_STATE_IN_PROGRESS
Definition: recognizer.h:10
@ RECOGNIZER_STATE_NULL
Definition: recognizer.h:6
@ RECOGNIZER_STATE_COMPLETED
Definition: recognizer.h:14
const stroke_t * get_stroke()
Access array of stroke_t of size MAX_TOUCHES.
Definition: stroke.c:47
Data structure for stroke gesture data.
Definition: multistroke.h:8
float sy[MAX_TOUCHES]
Definition: multistroke.h:37
float scale
Definition: multistroke.h:21
float rotation
Definition: multistroke.h:19
float scale0
Definition: multistroke.h:31
char strokes[MAX_TOUCHES]
Definition: multistroke.h:24
state_t state
Definition: multistroke.h:10
float rotation0
Definition: multistroke.h:29
float sx[MAX_TOUCHES]
Definition: multistroke.h:36
Data structure for stroke gesture data.
Definition: stroke.h:12
state_t state
Definition: stroke.h:14
int uid
Definition: stroke.h:19
float y
Definition: stroke.h:28
float x
Definition: stroke.h:27
To use the gesture library, users create touch events and fill in the appropriate fields.
Definition: gesturelib.h:17
unsigned int group
Definition: gesturelib.h:31
#define SQUARE_SUM(x, y)
Definition: utils.h:4
#define SQUARE(x)
Definition: utils.h:3