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 }