xref: /aosp_15_r20/external/libchrome-gestures/src/finger_metrics.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
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(short tracking_id,stime_t timestamp)37 FingerMetrics::FingerMetrics(short tracking_id, stime_t timestamp)
38     : tracking_id_(tracking_id),
39       origin_time_(timestamp) {}
40 
FingerMetrics(const FingerState & state,stime_t timestamp)41 FingerMetrics::FingerMetrics(const FingerState& state,
42                              stime_t timestamp)
43     : tracking_id_(state.tracking_id),
44       position_(state.position_x, state.position_y),
45       origin_position_(state.position_x, state.position_y),
46       origin_time_(timestamp) {}
47 
Update(const FingerState & state,stime_t timestamp,bool gesture_start)48 void FingerMetrics::Update(const FingerState& state, stime_t timestamp,
49                            bool gesture_start) {
50   Vector2 new_position = Vector2(state.position_x, state.position_y);
51   delta_ = Sub(new_position, position_);
52   position_ = new_position;
53 
54   if (gesture_start) {
55     start_position_ = position_;
56     start_time_ = timestamp;
57   }
58 }
59 
CloseEnoughToGesture(const Vector2 & pos_a,const Vector2 & pos_b) const60 bool Metrics::CloseEnoughToGesture(const Vector2& pos_a,
61                                    const Vector2& pos_b) const {
62   float horiz_axis_sq =
63       properties_->two_finger_close_horizontal_distance_thresh.val_ *
64       properties_->two_finger_close_horizontal_distance_thresh.val_;
65   float vert_axis_sq =
66       properties_->two_finger_close_vertical_distance_thresh.val_ *
67       properties_->two_finger_close_vertical_distance_thresh.val_;
68   Vector2 delta = Sub(pos_a, pos_b);
69   // Equation of ellipse:
70   //    ,.--+--..
71   //  ,'   V|    `.   x^2   y^2
72   // |      +------|  --- + --- < 1
73   //  \        H  /   H^2   V^2
74   //   `-..__,,.-'
75   return vert_axis_sq * delta.x * delta.x + horiz_axis_sq * delta.y * delta.y
76          < vert_axis_sq * horiz_axis_sq;
77 }
78 
Metrics(MetricsProperties * properties)79 Metrics::Metrics(MetricsProperties* properties) : properties_(properties) {
80   fingers_.reserve(kMaxFingers);
81 }
82 
GetFinger(short tracking_id) const83 const FingerMetrics* Metrics::GetFinger(short tracking_id) const {
84   for (auto iter = fingers_.cbegin(); iter != fingers_.cend(); ++iter) {
85     if(iter->tracking_id() == tracking_id) {
86       return &(*iter);
87     }
88   }
89   return nullptr;
90 }
91 
GetFinger(const FingerState & state) const92 const FingerMetrics* Metrics::GetFinger(const FingerState& state) const {
93   return GetFinger(state.tracking_id);
94 }
95 
Update(const HardwareState & hwstate)96 void Metrics::Update(const HardwareState& hwstate) {
97   int previous_count = fingers_.size();
98   int existing_count = 0;
99   int new_count = 0;
100 
101   // create metrics for new fingers
102   for (int i=0; i<hwstate.finger_cnt; ++i) {
103     const FingerState& state = hwstate.fingers[i];
104     if (GetFinger(state.tracking_id) == nullptr) {
105       fingers_.push_back(FingerMetrics(state,
106                                        hwstate.timestamp));
107       ++new_count;
108     } else {
109       ++existing_count;
110     }
111   }
112 
113   // remove metrics for lifted fingers
114   if (existing_count != previous_count) {
115     auto iter = fingers_.begin();
116     while (iter != fingers_.end()) {
117       if (!hwstate.GetFingerState(iter->tracking_id()))
118         iter = fingers_.erase(iter);
119       else
120         ++iter;
121     }
122   }
123 
124   // when a new finger has been added or a finger has been removed
125   // we consider this to be a new gesture starting
126   bool gesture_start = (existing_count != previous_count) || new_count > 0;
127   for (FingerMetrics& finger: fingers_) {
128     const FingerState* fs = hwstate.GetFingerState(finger.tracking_id());
129     if (!fs) {
130       Err("Unexpected missing finger state!");
131       continue;
132     }
133     finger.Update(*fs, hwstate.timestamp, gesture_start);
134   }
135 }
136 
Clear()137 void Metrics::Clear() {
138   fingers_.clear();
139 }
140 
SetFingerOriginTimestampForTesting(short tracking_id,stime_t time)141 void Metrics::SetFingerOriginTimestampForTesting(short tracking_id,
142                                                  stime_t time) {
143   for (auto iter = fingers_.begin(); iter != fingers_.end(); ++iter) {
144     if(iter->tracking_id() == tracking_id) {
145       fingers_.erase(iter);
146       break;
147     }
148   }
149   fingers_.push_back(FingerMetrics(tracking_id, time));
150 }
151 
152 }  // namespace gestures
153