• 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 #include "include/finger_metrics.h"
6 
7 namespace gestures {
8 
Add(const Vector2 & left,const Vector2 & right)9 Vector2 Add(const Vector2& left, const Vector2& right) {
10   return Vector2(left).Add(right);
11 }
12 
Sub(const Vector2 & left,const Vector2 & right)13 Vector2 Sub(const Vector2& left, const Vector2& right) {
14   return Vector2(left).Sub(right);
15 }
16 
Dot(const Vector2 & left,const Vector2 & right)17 float Dot(const Vector2& left, const Vector2& right) {
18   return left.x * right.x +  left.y * right.y;
19 }
20 
MetricsProperties(PropRegistry * prop_reg)21 MetricsProperties::MetricsProperties(PropRegistry* prop_reg)
22     : two_finger_close_horizontal_distance_thresh(
23           prop_reg,
24           "Two Finger Horizontal Close Distance Thresh",
25           50.0),
26       two_finger_close_vertical_distance_thresh(
27           prop_reg,
28           "Two Finger Vertical Close Distance Thresh",
29           45.0) {}
30 
FingerMetrics()31 FingerMetrics::FingerMetrics()
32     : tracking_id_(-1) {}
33 
FingerMetrics(short tracking_id)34 FingerMetrics::FingerMetrics(short tracking_id)
35     : tracking_id_(tracking_id) {}
36 
FingerMetrics(const FingerState & state,stime_t timestamp)37 FingerMetrics::FingerMetrics(const FingerState& state,
38                              stime_t timestamp)
39     : tracking_id_(state.tracking_id),
40       position_(state.position_x, state.position_y),
41       origin_position_(state.position_x, state.position_y),
42       origin_time_(timestamp) {}
43 
Update(const FingerState & state,stime_t timestamp,bool gesture_start)44 void FingerMetrics::Update(const FingerState& state, stime_t timestamp,
45                            bool gesture_start) {
46   Vector2 new_position = Vector2(state.position_x, state.position_y);
47   delta_ = Sub(new_position, position_);
48   position_ = new_position;
49 
50   if (gesture_start) {
51     start_position_ = position_;
52     start_time_ = timestamp;
53   }
54 }
55 
CloseEnoughToGesture(const Vector2 & pos_a,const Vector2 & pos_b) const56 bool Metrics::CloseEnoughToGesture(const Vector2& pos_a,
57                                    const Vector2& pos_b) const {
58   float horiz_axis_sq =
59       properties_->two_finger_close_horizontal_distance_thresh.val_ *
60       properties_->two_finger_close_horizontal_distance_thresh.val_;
61   float vert_axis_sq =
62       properties_->two_finger_close_vertical_distance_thresh.val_ *
63       properties_->two_finger_close_vertical_distance_thresh.val_;
64   Vector2 delta = Sub(pos_a, pos_b);
65   // Equation of ellipse:
66   //    ,.--+--..
67   //  ,'   V|    `.   x^2   y^2
68   // |      +------|  --- + --- < 1
69   //  \        H  /   H^2   V^2
70   //   `-..__,,.-'
71   return vert_axis_sq * delta.x * delta.x + horiz_axis_sq * delta.y * delta.y
72          < vert_axis_sq * horiz_axis_sq;
73 }
74 
Metrics(MetricsProperties * properties)75 Metrics::Metrics(MetricsProperties* properties) : properties_(properties) {}
76 
GetFinger(short tracking_id) const77 const FingerMetrics* Metrics::GetFinger(short tracking_id) const {
78   auto iter = fingers_.find(FingerMetrics(tracking_id));
79   if (iter != fingers_.end())
80     return iter;
81   else
82     return NULL;
83 }
84 
GetFinger(const FingerState & state) const85 const FingerMetrics* Metrics::GetFinger(const FingerState& state) const {
86   return GetFinger(state.tracking_id);
87 }
88 
Update(const HardwareState & hwstate)89 void Metrics::Update(const HardwareState& hwstate) {
90   int previous_count = fingers_.size();
91   int existing_count = 0;
92   int new_count = 0;
93 
94   // create metrics for new fingers
95   for (int i=0; i<hwstate.finger_cnt; ++i) {
96     const FingerState& state = hwstate.fingers[i];
97     auto iter = fingers_.find(FingerMetrics(state.tracking_id));
98     if (iter == fingers_.end()) {
99       fingers_.push_back(FingerMetrics(state,
100                                        hwstate.timestamp));
101       ++new_count;
102     } else {
103       ++existing_count;
104     }
105   }
106 
107   // remove metrics for lifted fingers
108   if (existing_count != previous_count) {
109     auto iter = fingers_.begin();
110     while (iter != fingers_.end()) {
111       if (!hwstate.GetFingerState(iter->tracking_id()))
112         iter = fingers_.erase(iter);
113       else
114         ++iter;
115     }
116   }
117 
118   // when a new finger has been added or a finger has been removed
119   // we consider this to be a new gesture starting
120   bool gesture_start = (existing_count != previous_count) || new_count > 0;
121   for (FingerMetrics& finger: fingers_) {
122     const FingerState* fs = hwstate.GetFingerState(finger.tracking_id());
123     if (!fs) {
124       Err("Unexpected missing finger state!");
125       continue;
126     }
127     finger.Update(*fs, hwstate.timestamp, gesture_start);
128   }
129 }
130 
Clear()131 void Metrics::Clear() {
132   fingers_.clear();
133 }
134 
135 }  // namespace gestures
136