1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSensors module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40
41#include "qtwistsensorgesturerecognizer.h"
42
43#include <QtCore/qmath.h>
44
45QT_BEGIN_NAMESPACE
46
47#define TIMER_TIMEOUT 750
48QTwistSensorGestureRecognizer::QTwistSensorGestureRecognizer(QObject *parent)
49 : QSensorGestureRecognizer(parent)
50 , orientationReading(0)
51 , active(0)
52 , detecting(0)
53 , checking(0)
54 , increaseCount(0)
55 , decreaseCount(0)
56 , lastAngle(0)
57 , detectedAngle(0)
58{
59}
60
61QTwistSensorGestureRecognizer::~QTwistSensorGestureRecognizer()
62{
63}
64
65void QTwistSensorGestureRecognizer::create()
66{
67}
68
69QString QTwistSensorGestureRecognizer::id() const
70{
71 return QString("QtSensors.twist");
72}
73
74bool QTwistSensorGestureRecognizer::start()
75{
76 if (QtSensorGestureSensorHandler::instance()->startSensor(sensor: QtSensorGestureSensorHandler::Accel)) {
77 if (QtSensorGestureSensorHandler::instance()->startSensor(sensor: QtSensorGestureSensorHandler::Orientation)) {
78 active = true;
79 connect(sender: QtSensorGestureSensorHandler::instance(),SIGNAL(orientationReadingChanged(QOrientationReading*)),
80 receiver: this,SLOT(orientationReadingChanged(QOrientationReading*)));
81
82 connect(sender: QtSensorGestureSensorHandler::instance(),SIGNAL(accelReadingChanged(QAccelerometerReading*)),
83 receiver: this,SLOT(accelChanged(QAccelerometerReading*)));
84 } else {
85 QtSensorGestureSensorHandler::instance()->stopSensor(sensor: QtSensorGestureSensorHandler::Accel);
86 active = false;
87 }
88 } else {
89
90 active = false;
91 }
92
93 return active;
94}
95
96bool QTwistSensorGestureRecognizer::stop()
97{
98 QtSensorGestureSensorHandler::instance()->stopSensor(sensor: QtSensorGestureSensorHandler::Accel);
99 QtSensorGestureSensorHandler::instance()->stopSensor(sensor: QtSensorGestureSensorHandler::Orientation);
100 disconnect(sender: QtSensorGestureSensorHandler::instance(),SIGNAL(orientationReadingChanged(QOrientationReading*)),
101 receiver: this,SLOT(orientationReadingChanged(QOrientationReading*)));
102
103 disconnect(sender: QtSensorGestureSensorHandler::instance(),SIGNAL(accelReadingChanged(QAccelerometerReading*)),
104 receiver: this,SLOT(accelChanged(QAccelerometerReading*)));
105
106 reset();
107 orientationList.clear();
108 active = false;
109 return active;
110}
111
112bool QTwistSensorGestureRecognizer::isActive()
113{
114 return active;
115}
116
117void QTwistSensorGestureRecognizer::orientationReadingChanged(QOrientationReading *reading)
118{
119 orientationReading = reading;
120 if (orientationList.count() == 3)
121 orientationList.removeFirst();
122
123 orientationList.append(t: reading->orientation());
124
125 if (orientationList.count() == 3
126 && orientationList.at(i: 2) == QOrientationReading::FaceUp
127 && (orientationList.at(i: 1) == QOrientationReading::RightUp
128 || orientationList.at(i: 1) == QOrientationReading::LeftUp)) {
129 checkTwist();
130 }
131
132 checkOrientation();
133}
134
135bool QTwistSensorGestureRecognizer::checkOrientation()
136{
137 if (orientationReading->orientation() == QOrientationReading::TopDown
138 || orientationReading->orientation() == QOrientationReading::FaceDown) {
139 reset();
140 return false;
141 }
142 return true;
143}
144
145void QTwistSensorGestureRecognizer::accelChanged(QAccelerometerReading *reading)
146{
147 if (orientationReading == 0)
148 return;
149
150 const qreal x = reading->x();
151 const qreal y = reading->y();
152 const qreal z = reading->z();
153
154 if (!detecting && !checking&& dataList.count() > 21)
155 dataList.removeFirst();
156
157 qreal angle = qRadiansToDegrees(radians: qAtan(v: x / qSqrt(v: y * y + z * z)));
158
159 if (qAbs(t: angle) > 2) {
160 if (detecting) {
161 if ((angle > 0 && angle < lastAngle)
162 || (angle < 0 && angle > lastAngle)) {
163 decreaseCount++;
164 } else {
165 if (decreaseCount > 0)
166 decreaseCount--;
167 }
168 }
169
170 if (!detecting && ((angle > 0 && angle > lastAngle)
171 || (angle < 0 && angle < lastAngle))
172 && ((angle > 0 && lastAngle > 0)
173 || (angle < 0 && lastAngle < 0))) {
174 increaseCount++;
175 } else
176 if (!detecting && increaseCount > 3 && qAbs(t: angle) > 30) {
177 decreaseCount = 0;
178 detecting = true;
179 detectedAngle = qRadiansToDegrees(radians: qAtan(v: y / qSqrt(v: x * x + z * z)));
180 }
181 } else {
182 increaseCount = 0;
183 increaseCount = 0;
184 }
185
186 lastAngle = angle;
187 if (detecting && decreaseCount >= 4 && qAbs(t: angle) < 25) {
188 checkTwist();
189 }
190
191 twistAccelData data;
192 data.x = x;
193 data.y = y;
194 data.z = z;
195
196 if (qAbs(t: x) > 1)
197 dataList.append(t: data);
198
199 if (qAbs(t: z) > 15.0) {
200 reset();
201 }
202
203}
204
205void QTwistSensorGestureRecognizer::checkTwist()
206{
207 checking = true;
208 int lastx = 0;
209 bool ok = false;
210 bool spinpoint = false;
211
212 if (detectedAngle < 0) {
213 reset();
214 return;
215 }
216
217 //// check for orientation changes first
218 if (orientationList.count() < 2)
219 return;
220
221 if (orientationList.count() > 2)
222 if (orientationList.at(i: 0) == orientationList.at(i: 2)
223 && (orientationList.at(i: 1) == QOrientationReading::LeftUp
224 || orientationList.at(i: 1) == QOrientationReading::RightUp)) {
225 ok = true;
226 if (orientationList.at(i: 1) == QOrientationReading::RightUp)
227 detectedAngle = 1;
228 else
229 detectedAngle = -1;
230 }
231
232 // now the manual increase/decrease count
233 if (!ok) {
234 if (increaseCount < 1 || decreaseCount < 3)
235 return;
236
237 if (increaseCount > 6 && decreaseCount > 4) {
238 ok = true;
239 if (orientationList.at(i: 1) == QOrientationReading::RightUp)
240 detectedAngle = 1;
241 else
242 detectedAngle = -1;
243 }
244 }
245 // now we're really grasping for anything
246 if (!ok)
247 for (int i = 0; i < dataList.count(); i++) {
248 twistAccelData curData = dataList.at(i);
249 if (!spinpoint && qAbs(t: curData.x) < 1)
250 continue;
251 if (curData.z >= 0 ) {
252 if (!spinpoint && (curData.x > lastx || curData.x < lastx) && curData.x - lastx > 1) {
253 ok = true;
254 } else if (spinpoint && (curData.x < lastx || curData.x > lastx)&& lastx - curData.x > 1) {
255 ok = true;
256 } else {
257 ok = false;
258 }
259 } else if (!spinpoint && curData.z < 0) {
260 spinpoint = true;
261 } else if (spinpoint && curData.z > 9) {
262 break;
263 }
264
265 lastx = curData.x;
266 }
267 if (ok) {
268 if (detectedAngle > 0) {
269 Q_EMIT twistLeft();
270 Q_EMIT detected("twistLeft");
271 } else {
272 Q_EMIT twistRight();
273 Q_EMIT detected("twistRight");
274 }
275 }
276 reset();
277}
278
279void QTwistSensorGestureRecognizer::reset()
280{
281 detecting = false;
282 checking = false;
283 dataList.clear();
284 increaseCount = 0;
285 decreaseCount = 0;
286 lastAngle = 0;
287}
288
289
290
291QT_END_NAMESPACE
292

source code of qtsensors/src/plugins/sensorgestures/qtsensors/qtwistsensorgesturerecognizer.cpp