Gesture Library
multidrag.c
Go to the documentation of this file.
1 #include "multidrag.h"
2 
3 #include "drag.h"
4 #include "math.h"
5 #include "utils.h"
6 
8 
9 void init_multidrag() {
10  for (int i = 0; i < MAX_TOUCHES; i++) {
12  multidrag_d[i].uid = 0;
13  multidrag_d[i].size = 0;
14  multidrag_d[i].dx = 0;
15  multidrag_d[i].dy = 0;
16  multidrag_d[i].rotation = 0;
17  multidrag_d[i].scale = 1;
18  multidrag_d[i].dx0 = 0;
19  multidrag_d[i].dy0 = 0;
20  multidrag_d[i].rotation0 = 0;
21  multidrag_d[i].scale0 = 1;
22  multidrag_d[i].cx = 0;
23  multidrag_d[i].cy = 0;
24  for (int j = 0; j < MAX_TOUCHES; j++) {
25  multidrag_d[i].strokes[j] = 0;
26  multidrag_d[i].sx[j] = 0;
27  multidrag_d[i].sy[j] = 0;
28  }
29  }
30 }
31 
32 static void update_multidrag(multidrag_t* md, int group);
33 static void zero_multidrag(multidrag_t* md);
34 static void calculate_center(multidrag_t* md);
35 static void calculate_transform(multidrag_t* md);
36 
37 void recognize_multidrag(const touch_event_t* event) {
38  int free_index = -1;
39  const stroke_t* strokes = get_stroke();
40  for (int i = 0; i < MAX_TOUCHES; i++) {
41  if (multidrag_d[i].uid == strokes[event->group].uid && multidrag_d[i].size) {
42  update_multidrag(multidrag_d + i, event->group);
43  return;
44  } else if (free_index < 0 && !multidrag_d[i].size) {
45  free_index = i;
46  }
47  }
48  if (free_index >= 0 && strokes[event->group].state == RECOGNIZER_STATE_IN_PROGRESS) {
49  update_multidrag(multidrag_d + free_index, event->group);
50  }
51 }
52 
54  return multidrag_d;
55 }
56 
57 static void update_multidrag(multidrag_t* md, int group) {
58  const stroke_t* strokes = get_stroke();
59  md->uid = strokes[group].uid;
60  if (!md->strokes[group]) {
61  switch (md->state) {
66  md->strokes[group] = 1;
67  calculate_center(md);
68  if (md->size > 0) {
70  }
71  break;
72  default:
73  break;
74  }
75  } else {
76  switch (md->state) {
78  calculate_transform(md);
79  if (strokes[group].state == RECOGNIZER_STATE_COMPLETED) {
80  md->strokes[group] = 0;
81  calculate_center(md);
82  if (md->size < 2) {
84  }
85  }
86  break;
88  if (strokes[group].state == RECOGNIZER_STATE_IN_PROGRESS) {
89  if (md->size > 1) {
90  float dist = SQUARE_SUM(strokes[group].x - md->px[group], strokes[group].y - md->py[group]);
91  if (dist > SQUARE(DRAG_DIST_MIN)) {
92  zero_multidrag(md);
93  calculate_center(md);
95  }
96  }
97  } else {
98  md->strokes[group] = 0;
99  calculate_center(md);
100  if (md->size < 1) {
102  }
103  }
104  break;
105  default:
106  if (strokes[group].state == RECOGNIZER_STATE_COMPLETED) {
107  md->strokes[group] = 0;
108  calculate_center(md);
109  }
110  break;
111  }
112  }
113 }
114 
115 static void zero_multidrag(multidrag_t* md) {
116  md->dx = 0;
117  md->dy = 0;
118  md->rotation = 0;
119  md->scale = 1;
120 }
121 
122 static void calculate_center(multidrag_t* md) {
123  // copy last translation and rotation and scaling
124  md->dx0 = md->dx;
125  md->dy0 = md->dy;
126  md->rotation0 = md->rotation;
127  md->scale0 = md->scale;
128 
129  // calculate new center
130  const stroke_t* strokes = get_stroke();
131  md->size = 0;
132  float x = 0;
133  float y = 0;
134  for (int i = 0; i < MAX_TOUCHES; i++) {
135  if (md->strokes[i]) {
136  md->px[i] = strokes[i].x;
137  x += strokes[i].x;
138  md->py[i] = strokes[i].y;
139  y += strokes[i].y;
140  md->size++;
141  }
142  }
143  md->cx = x / md->size;
144  md->cy = y / md->size;
145 
146  // calculate new scaled offsets
147  float dx[MAX_TOUCHES];
148  float dy[MAX_TOUCHES];
149  float a = 0;
150  for (int i = 0; i < MAX_TOUCHES; i++) {
151  if (md->strokes[i]) {
152  dx[i] = strokes[i].x - md->cx;
153  dy[i] = strokes[i].y - md->cy;
154  a += SQUARE(dx[i]) + SQUARE(dy[i]);
155  }
156  }
157  for (int i = 0; i < MAX_TOUCHES; i++) {
158  if (md->strokes[i]) {
159  md->sx[i] = dx[i] / a;
160  md->sy[i] = dy[i] / a;
161  }
162  }
163 }
164 
165 static void calculate_transform(multidrag_t* md) {
166  // calculate current center
167  const stroke_t* strokes = get_stroke();
168  float cx = 0;
169  float cy = 0;
170  for (int i = 0; i < MAX_TOUCHES; i++) {
171  if (md->strokes[i]) {
172  cx += strokes[i].x;
173  cy += strokes[i].y;
174  }
175  }
176  cx /= md->size;
177  cy /= md->size;
178 
179  // calculate translation
180  md->dx = md->dx0 + (cx - md->cx);
181  md->dy = md->dy0 + (cy - md->cy);
182 
183  // calculate rotation and scaling
184  float a = 0;
185  float b = 0;
186  for (int i = 0; i < MAX_TOUCHES; i++) {
187  if (md->strokes[i]) {
188  float dx = strokes[i].x - cx;
189  float dy = strokes[i].y - cy;
190  a += md->sx[i] * dx + md->sy[i] * dy;
191  b += md->sx[i] * dy - md->sy[i] * dx;
192  }
193  }
194  md->rotation = md->rotation0 + atan2f(b, a);
195  md->scale = md->scale0 * sqrtf(SQUARE_SUM(a, b));
196 }
#define MAX_TOUCHES
Definition: gestureparams.h:5
#define DRAG_DIST_MIN
Definition: gestureparams.h:35
const multidrag_t * get_multidrag()
Access array of multidrag_t of size MAX_TOUCHES.
Definition: multidrag.c:53
void init_multidrag()
Initialize multidrag data structures.
Definition: multidrag.c:9
multidrag_t multidrag_d[MAX_TOUCHES]
Definition: multidrag.c:7
void recognize_multidrag(const touch_event_t *event)
Recognize multidrag gesture. This gesture locks the number of fingers once any finger starts moving.
Definition: multidrag.c:37
state
This represents the state of individual gesture recognizers.
Definition: recognizer.h:4
@ RECOGNIZER_STATE_IN_PROGRESS
Definition: recognizer.h:10
@ RECOGNIZER_STATE_FAILED
Definition: recognizer.h:12
@ RECOGNIZER_STATE_NULL
Definition: recognizer.h:6
@ RECOGNIZER_STATE_COMPLETED
Definition: recognizer.h:14
@ RECOGNIZER_STATE_POSSIBLE
Definition: recognizer.h:8
const stroke_t * get_stroke()
Access array of stroke_t of size MAX_TOUCHES.
Definition: stroke.c:47
Data structure for multidrag gesture data.
Definition: multidrag.h:8
float sy[MAX_TOUCHES]
Definition: multidrag.h:40
float scale
Definition: multidrag.h:21
float rotation
Definition: multidrag.h:19
float scale0
Definition: multidrag.h:31
char strokes[MAX_TOUCHES]
Definition: multidrag.h:24
float dx0
Definition: multidrag.h:26
int size
Definition: multidrag.h:14
float py[MAX_TOUCHES]
Definition: multidrag.h:34
state_t state
Definition: multidrag.h:10
float cx
Definition: multidrag.h:36
int uid
Definition: multidrag.h:12
float cy
Definition: multidrag.h:37
float rotation0
Definition: multidrag.h:29
float dy
Definition: multidrag.h:17
float sx[MAX_TOUCHES]
Definition: multidrag.h:39
float dx
Definition: multidrag.h:16
float dy0
Definition: multidrag.h:27
float px[MAX_TOUCHES]
Definition: multidrag.h:33
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