diff --git a/egui/src/input_state/touch_state.rs b/egui/src/input_state/touch_state.rs index 41d1a590..e6437063 100644 --- a/egui/src/input_state/touch_state.rs +++ b/egui/src/input_state/touch_state.rs @@ -1,11 +1,10 @@ -use std::{ - collections::BTreeMap, - f32::consts::{PI, TAU}, - fmt::Debug, -}; +use std::{collections::BTreeMap, fmt::Debug}; -use crate::{data::input::TouchDeviceId, Event, RawInput, TouchId, TouchPhase}; -use epaint::emath::{Pos2, Vec2}; +use crate::{ + data::input::TouchDeviceId, + emath::{normalized_angle, Pos2, Vec2}, + Event, RawInput, TouchId, TouchPhase, +}; /// All you probably need to know about a multi-touch gesture. pub struct MultiTouchInfo { @@ -196,7 +195,7 @@ impl TouchState { num_touches: self.active_touches.len(), zoom_delta, zoom_delta_2d: zoom_delta2, - rotation_delta: normalized_angle(state.current.heading, state_previous.heading), + rotation_delta: normalized_angle(state.current.heading - state_previous.heading), translation_delta: state.current.avg_pos - state_previous.avg_pos, force: state.current.avg_force, } @@ -294,27 +293,6 @@ impl Debug for TouchState { } } -/// Calculate difference between two directions, such that the absolute value of the result is -/// minimized. -fn normalized_angle(current_direction: f32, previous_direction: f32) -> f32 { - let mut angle = current_direction - previous_direction; - angle %= TAU; - if angle > PI { - angle -= TAU; - } else if angle < -PI { - angle += TAU; - } - angle -} - -#[test] -fn normalizing_angle_from_350_to_0_yields_10() { - assert!( - (normalized_angle(0_f32.to_radians(), 350_f32.to_radians()) - 10_f32.to_radians()).abs() - <= 5. * f32::EPSILON // many conversions (=divisions) involved => high error rate - ); -} - #[derive(Clone, Debug)] enum PinchType { Horizontal, diff --git a/emath/src/lib.rs b/emath/src/lib.rs index 040d5f92..c29e048e 100644 --- a/emath/src/lib.rs +++ b/emath/src/lib.rs @@ -331,3 +331,36 @@ impl_num_ext!(f64); impl_num_ext!(usize); impl_num_ext!(Vec2); impl_num_ext!(Pos2); + +// ---------------------------------------------------------------------------- + +/// Wrap angle to `[-PI, PI]` range. +pub fn normalized_angle(mut angle: f32) -> f32 { + use std::f32::consts::{PI, TAU}; + angle %= TAU; + if angle > PI { + angle -= TAU; + } else if angle < -PI { + angle += TAU; + } + angle +} + +#[test] +fn test_normalized_angle() { + macro_rules! almost_eq { + ($left:expr, $right:expr) => { + let left = $left; + let right = $right; + assert!((left - right).abs() < 1e-6, "{} != {}", left, right); + }; + } + + use std::f32::consts::TAU; + almost_eq!(normalized_angle(-3.0 * TAU), 0.0); + almost_eq!(normalized_angle(-2.3 * TAU), -0.3 * TAU); + almost_eq!(normalized_angle(-TAU), 0.0); + almost_eq!(normalized_angle(0.0), 0.0); + almost_eq!(normalized_angle(TAU), 0.0); + almost_eq!(normalized_angle(2.7 * TAU), -0.3 * TAU); +}