File indexing completed on 2025-01-05 04:35:06

0001 /*
0002  * This file is part of the mouse gesture package.
0003  * Copyright (C) 2006 Johan Thelin <e8johan@gmail.com>
0004  * All rights reserved.
0005  *
0006  * Redistribution and use in source and binary forms, with or
0007  * without modification, are permitted provided that the
0008  * following conditions are met:
0009  *
0010  *   - Redistributions of source code must retain the above
0011  *     copyright notice, this list of conditions and the
0012  *     following disclaimer.
0013  *   - Redistributions in binary form must reproduce the
0014  *     above copyright notice, this list of conditions and
0015  *     the following disclaimer in the documentation and/or
0016  *     other materials provided with the distribution.
0017  *   - The names of its contributors may be used to endorse
0018  *     or promote products derived from this software without
0019  *     specific prior written permission.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
0022  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
0023  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0024  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0025  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0026  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0029  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0030  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0031  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0033  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  *
0036  */
0037 
0038 #include "adv_recognizer.h"
0039 #include <algorithm>
0040 
0041 using namespace Gesture;
0042 
0043 RealTimeMouseGestureRecognizer::RealTimeMouseGestureRecognizer(int minimumMovement, double minimumMatch, bool allowDiagonals)
0044     : minimumMatch(minimumMatch), allowDiagonals(allowDiagonals)
0045 {
0046     minimumMovement2 = minimumMovement * minimumMovement;
0047 
0048     directions.resize(64);
0049     lastX = 0;
0050     lastY = 0;
0051     lastDirection = NoMatch;
0052 }
0053 
0054 RealTimeMouseGestureRecognizer::~RealTimeMouseGestureRecognizer()
0055 {
0056 
0057 }
0058 
0059 
0060 const Direction dirsD[8] = {
0061     Down,
0062     Up,
0063     Right,
0064     Left,
0065     DownRight,
0066     DownLeft,
0067     UpLeft,
0068     UpRight
0069 };
0070 
0071 void RealTimeMouseGestureRecognizer::addPoint(int x, int y)
0072 {
0073     int dx, dy;
0074 
0075     dx = x - lastX;
0076     dy = y - lastY;
0077 
0078     if (dx * dx + dy * dy < minimumMovement2) {
0079         return;
0080     }
0081 
0082     Direction direction;
0083 
0084     const int _directions[8][2] = {
0085         {0, 15}, //down 0
0086         {0, -15}, //up 1
0087         {15, 0}, //right 2
0088         { -15, 0}, //left 3
0089         {10, 10}, //down right 4
0090         { -10, 10}, //down left 5
0091         { -10, -10}, //up left 6
0092         {10, -10}//up right 7
0093     };
0094     int maxValue = 0;
0095     int maxIndex = -1;
0096 
0097     for (int i = 0; i < (allowDiagonals ? 8 : 4); i++) {
0098         int value = dx * _directions[i][0] + dy * _directions[i][1];
0099         if (value > maxValue) {
0100             maxValue = value;
0101             maxIndex = i;
0102         }
0103     }
0104 
0105     direction = dirsD[maxIndex];
0106 
0107     if (direction != lastDirection) {
0108         directions.push_back(direction);
0109         recognizeGesture();
0110     }
0111 
0112 
0113     lastX = x;
0114     lastY = y;
0115     lastDirection = direction;
0116 }
0117 
0118 struct DirectionSort {
0119     bool operator()(const GestureDefinition &a, const GestureDefinition &b) {
0120         return a.directions.size() > b.directions.size();
0121     }
0122 };
0123 
0124 void RealTimeMouseGestureRecognizer::addGestureDefinition(const GestureDefinition &gesture)
0125 {
0126     gestures.push_back(gesture);
0127     std::sort(gestures.begin(), gestures.end(), DirectionSort());
0128 }
0129 
0130 void RealTimeMouseGestureRecognizer::clearGestureDefinitions()
0131 {
0132     gestures.clear();
0133 }
0134 
0135 void RealTimeMouseGestureRecognizer::recognizeGesture()
0136 {
0137     int first = gestures.size();
0138 
0139     for (GestureList::const_iterator gi = gestures.begin(); gi != gestures.end(); ++gi) {
0140         int readIndex = directions.getReadPointer();
0141 
0142         try {
0143             bool match = true;
0144 
0145             for (DirectionList::const_iterator di = gi->directions.begin(); di != gi->directions.end() && match; ++di) {
0146                 Direction d = directions.pop();
0147                 if (*di != d) {
0148                     match = false;
0149                 }
0150             }
0151 
0152             if (match) {
0153                 if (gi->callbackClass) {
0154                     gi->callbackClass->callback();
0155                 }
0156                 return;
0157             }
0158             else {
0159                 first--;
0160                 directions.setReadPointerTo(readIndex);
0161             }
0162         }
0163         catch (const std::exception &) {
0164             directions.setReadPointerTo(readIndex);
0165         }
0166     }
0167 
0168     if (first == 0) {
0169         directions.pop();
0170     }
0171 }