• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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