// Copyright 2012 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "include/finger_metrics.h" namespace gestures { Vector2 Add(const Vector2& left, const Vector2& right) { return Vector2(left).Add(right); } Vector2 Sub(const Vector2& left, const Vector2& right) { return Vector2(left).Sub(right); } float Dot(const Vector2& left, const Vector2& right) { return left.x * right.x + left.y * right.y; } MetricsProperties::MetricsProperties(PropRegistry* prop_reg) : two_finger_close_horizontal_distance_thresh( prop_reg, "Two Finger Horizontal Close Distance Thresh", 50.0), two_finger_close_vertical_distance_thresh( prop_reg, "Two Finger Vertical Close Distance Thresh", 45.0) {} FingerMetrics::FingerMetrics() : tracking_id_(-1) {} FingerMetrics::FingerMetrics(short tracking_id) : tracking_id_(tracking_id) {} FingerMetrics::FingerMetrics(short tracking_id, stime_t timestamp) : tracking_id_(tracking_id), origin_time_(timestamp) {} FingerMetrics::FingerMetrics(const FingerState& state, stime_t timestamp) : tracking_id_(state.tracking_id), position_(state.position_x, state.position_y), origin_position_(state.position_x, state.position_y), origin_time_(timestamp) {} void FingerMetrics::Update(const FingerState& state, stime_t timestamp, bool gesture_start) { Vector2 new_position = Vector2(state.position_x, state.position_y); delta_ = Sub(new_position, position_); position_ = new_position; if (gesture_start) { start_position_ = position_; start_time_ = timestamp; } } bool Metrics::CloseEnoughToGesture(const Vector2& pos_a, const Vector2& pos_b) const { float horiz_axis_sq = properties_->two_finger_close_horizontal_distance_thresh.val_ * properties_->two_finger_close_horizontal_distance_thresh.val_; float vert_axis_sq = properties_->two_finger_close_vertical_distance_thresh.val_ * properties_->two_finger_close_vertical_distance_thresh.val_; Vector2 delta = Sub(pos_a, pos_b); // Equation of ellipse: // ,.--+--.. // ,' V| `. x^2 y^2 // | +------| --- + --- < 1 // \ H / H^2 V^2 // `-..__,,.-' return vert_axis_sq * delta.x * delta.x + horiz_axis_sq * delta.y * delta.y < vert_axis_sq * horiz_axis_sq; } Metrics::Metrics(MetricsProperties* properties) : properties_(properties) { fingers_.reserve(kMaxFingers); } const FingerMetrics* Metrics::GetFinger(short tracking_id) const { for (auto iter = fingers_.cbegin(); iter != fingers_.cend(); ++iter) { if(iter->tracking_id() == tracking_id) { return &(*iter); } } return nullptr; } const FingerMetrics* Metrics::GetFinger(const FingerState& state) const { return GetFinger(state.tracking_id); } void Metrics::Update(const HardwareState& hwstate) { int previous_count = fingers_.size(); int existing_count = 0; int new_count = 0; // create metrics for new fingers for (int i=0; itracking_id())) iter = fingers_.erase(iter); else ++iter; } } // when a new finger has been added or a finger has been removed // we consider this to be a new gesture starting bool gesture_start = (existing_count != previous_count) || new_count > 0; for (FingerMetrics& finger: fingers_) { const FingerState* fs = hwstate.GetFingerState(finger.tracking_id()); if (!fs) { Err("Unexpected missing finger state!"); continue; } finger.Update(*fs, hwstate.timestamp, gesture_start); } } void Metrics::Clear() { fingers_.clear(); } void Metrics::SetFingerOriginTimestampForTesting(short tracking_id, stime_t time) { for (auto iter = fingers_.begin(); iter != fingers_.end(); ++iter) { if(iter->tracking_id() == tracking_id) { fingers_.erase(iter); break; } } fingers_.push_back(FingerMetrics(tracking_id, time)); } } // namespace gestures