1 // Copyright 2012 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef GESTURES_FINGER_METRICS_H_ 6 #define GESTURES_FINGER_METRICS_H_ 7 8 #include <cmath> 9 10 #include "include/gestures.h" 11 #include "include/prop_registry.h" 12 #include "include/vector.h" 13 14 namespace gestures { 15 16 static const size_t kMaxFingers = 10; 17 static const size_t kMaxGesturingFingers = 4; 18 static const size_t kMaxTapFingers = 10; 19 20 // A datastructure describing a 2D vector in the mathematical sense. 21 struct Vector2 { Vector2Vector222 Vector2() : x(0), y(0) {} Vector2Vector223 Vector2(float x, float y) : x(x), y(y) {} Vector2Vector224 Vector2(const Vector2& other) : x(other.x), y(other.y) {} Vector2Vector225 explicit Vector2(const FingerState& state) : x(state.position_x), 26 y(state.position_y) {} 27 SubVector228 Vector2 Sub(const Vector2& other) { 29 return Vector2(x - other.x, y - other.y); 30 } 31 AddVector232 Vector2 Add(const Vector2& other) { 33 return Vector2(x + other.x, y + other.y); 34 } 35 MagSqVector236 float MagSq() const { 37 return x * x + y * y; 38 } MagVector239 float Mag() const { 40 return sqrtf(MagSq()); 41 } 42 bool operator==(const Vector2& that) const { 43 return x == that.x && y == that.y; 44 } 45 bool operator!=(const Vector2& that) const { 46 return !(*this == that); 47 } 48 49 float x; 50 float y; 51 }; 52 53 extern Vector2 Add(const Vector2& left, const Vector2& right); 54 extern Vector2 Sub(const Vector2& left, const Vector2& right); 55 extern float Dot(const Vector2& left, const Vector2& right); 56 57 class MetricsProperties { 58 public: 59 explicit MetricsProperties(PropRegistry* prop_reg); 60 61 // Maximum distance [mm] two fingers may be separated and still be eligible 62 // for a two-finger gesture (e.g., scroll / tap / click). These define an 63 // ellipse with horizontal and vertical axes lengths (think: radii). 64 DoubleProperty two_finger_close_horizontal_distance_thresh; 65 DoubleProperty two_finger_close_vertical_distance_thresh; 66 }; 67 68 // This class describes a finger and derives additional metrics that 69 // are useful for gesture recognition. 70 // In contrast to a FingerState an instance of this class has the 71 // lifetime of the duration the finger touches the touchpad. This allows 72 // metrics to be derived from the history of a finger. 73 class FingerMetrics { 74 public: 75 FingerMetrics(); 76 explicit FingerMetrics(short tracking_id); 77 FingerMetrics(const FingerState& state, stime_t timestamp); 78 79 // Update the finger metrics from a FingerState. 80 // gesture_start: true if fingers have been added or removed during this 81 // sync. 82 void Update(const FingerState& state, stime_t timestamp, 83 bool gesture_start); 84 tracking_id()85 short tracking_id() const { return tracking_id_; } 86 87 // current position position()88 Vector2 position() const { return position_; } 89 90 // position delta between current and last frame delta()91 Vector2 delta() const { return delta_; } 92 93 // origin is the time and position where the finger first touched origin_position()94 Vector2 origin_position() const { return origin_position_; } origin_time()95 stime_t origin_time() const { return origin_time_; } origin_delta()96 Vector2 origin_delta() const { return Sub(position_, origin_position_); } 97 98 // start is the time and postion where the fingers were located 99 // when the last of all current fingers touched (i.e. the gesture started) start_position()100 Vector2 start_position() const { return start_position_; } start_time()101 stime_t start_time() const { return start_time_; } start_delta()102 Vector2 start_delta() const { return Sub(position_, start_position_); } 103 104 // instances with the same tracking id are considered equal. 105 bool operator==(const FingerMetrics& other) const { 106 return other.tracking_id() == tracking_id_; 107 } 108 109 private: 110 short tracking_id_; 111 Vector2 position_; 112 Vector2 delta_; 113 Vector2 origin_position_; 114 Vector2 start_position_; 115 stime_t origin_time_; 116 stime_t start_time_; 117 }; 118 119 // The Metrics class is a container for FingerMetrics and additional 120 // metrics that are based on the interaction of multiple fingers. 121 // It is responsible for keeping the FingerMetrics instances updated 122 // with the latest FingerStates. 123 class Metrics { 124 public: 125 Metrics(MetricsProperties* properties); 126 127 bool CloseEnoughToGesture(const Vector2& pos_a, 128 const Vector2& pos_b) const; 129 130 // A collection of FingerMetrics describing the current hardware state. 131 // The collection is sorted to yield the oldest finger first. fingers()132 vector<FingerMetrics, kMaxFingers>& fingers() { return fingers_; } 133 134 // Find a FingerMetrics instance by it's tracking id. 135 // Returns NULL if not found. GetFinger(short tracking_id)136 FingerMetrics* GetFinger(short tracking_id) { 137 return const_cast<FingerMetrics*>( 138 const_cast<const Metrics*>(this)->GetFinger(tracking_id)); 139 } 140 const FingerMetrics* GetFinger(short tracking_id) const; 141 142 FingerMetrics* GetFinger(const FingerState& state); 143 const FingerMetrics* GetFinger(const FingerState& state) const; 144 145 // Update the collection of FingerMetrics using information from 'hwstate'. 146 void Update(const HardwareState& hwstate); 147 148 // Clear all finger information 149 void Clear(); 150 151 private: 152 vector<FingerMetrics, kMaxFingers> fingers_; 153 154 MetricsProperties* properties_; 155 std::unique_ptr<MetricsProperties> own_properties_; 156 }; 157 158 } // namespace gestures 159 160 #endif // GESTURES_FINGER_METRICS_H_ 161