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