| // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "touch_noise_filter/far_apart_taps_filter.h" |
| |
| #include <base/basictypes.h> |
| |
| #include <cmath> |
| #include <cstddef> |
| #include <cstdio> |
| |
| namespace touch_noise_filter { |
| |
| namespace { |
| |
| // Minimum squared distance between taps to be considered far apart. |
| __s32 kMinDistance2 = 1500 * 1500; |
| |
| // Max time between taps considered. |
| double kMaxTapDeltaSecs = 0.03; |
| |
| // Maximum squared movement of a touch to still be considered a tap. |
| __s32 kMaxTapMovement2 = 20 * 20; |
| |
| // Returns the squared distance between (x1, y1) and (x2, y2). |
| __s32 Distance2(__s32 x1, __s32 y1, __s32 x2, __s32 y2) { |
| return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); |
| } |
| |
| } // namespace {} |
| |
| void FarApartTapsFilter::FilterFrame(Frame* previous, Frame* current, |
| size_t num_slots) { |
| // Remove old taps and touches moving more than min delta. |
| double tapCutoff = current->timestamp_ - kMaxTapDeltaSecs; |
| for (size_t i = 0; i < num_slots; i++) { |
| if (tracked_taps_[i].start_ < tapCutoff) |
| tracked_taps_[i].start_ = 0; |
| } |
| |
| for (size_t slot = 0; slot < num_slots; slot++) { |
| Finger* cur = ¤t->fingers_[slot]; |
| Finger* prev = &previous->fingers_[slot]; |
| |
| // Only look at slots with active touches. |
| if (cur->tracking_id_ == -1 && prev->tracking_id_ == -1) |
| continue; |
| |
| bool arrived = prev->tracking_id_ == -1 && cur->tracking_id_ > 0; |
| bool departing = prev->tracking_id_ >= 0 && cur->tracking_id_ == -1; |
| |
| if (arrived) { |
| // Track new finger info. |
| tracked_taps_[slot] = Tap(current->timestamp_, cur->x_pos_, cur->y_pos_); |
| } else if (tracked_taps_[slot].start_ > 0) { |
| // Check if this finger has moved too far to be considered a tap. |
| if (kMaxTapMovement2 < Distance2(cur->x_pos_, cur->y_pos_, |
| tracked_taps_[slot].x_pos_, tracked_taps_[slot].y_pos_)) |
| tracked_taps_[slot].start_ = 0; |
| } |
| |
| if (tracked_taps_[slot].start_ > 0) { |
| // Check distance from other tracked taps. |
| __s32 min_distance2 = -1; |
| for (size_t i = 0; i < num_slots; i++) { |
| if (i == slot || tracked_taps_[i].start_ == 0) |
| continue; |
| |
| __s32 dist2 = Distance2(tracked_taps_[i].x_pos_, |
| tracked_taps_[i].y_pos_, |
| cur->x_pos_, cur->y_pos_); |
| if (min_distance2 < 0 || dist2 < min_distance2) |
| min_distance2 = dist2; |
| } |
| |
| if (min_distance2 > kMinDistance2) { |
| // The other finger should see this one on its next frame and also |
| // get canceled. |
| Log("Cancel tracking id %d %.0fpx from other current taps.", |
| departing ? prev->tracking_id_ : cur->tracking_id_, |
| sqrt(min_distance2)); |
| cur->canceled_ = true; |
| } |
| } |
| |
| if (departing) |
| tracked_taps_[slot].start_ = 0; |
| } |
| } |
| |
| } // namespace touch_noise_filter |