From 3201df50bd8192b6ea0063bc45dc2af14e7780d6 Mon Sep 17 00:00:00 2001 From: Ellen Emilia Anna Zscheile Date: Thu, 9 Jan 2025 01:03:42 +0100 Subject: [PATCH] Revert "feat(math): introduce dedicated data type for normalized angles" This reverts commit b4fe7006b7481b7103714dabee5b20e887059d13. The reverted commit introduced an autorouter regression, observable in 4x_3rd_order_smd_lc_filters test using egui (see Matrix chat). --- src/geometry/primitive.rs | 9 ++- src/math/mod.rs | 136 ++------------------------------------ 2 files changed, 14 insertions(+), 131 deletions(-) diff --git a/src/geometry/primitive.rs b/src/geometry/primitive.rs index 80474a9..59082bb 100644 --- a/src/geometry/primitive.rs +++ b/src/geometry/primitive.rs @@ -266,7 +266,8 @@ impl BendShape { } pub fn start_angle(&self) -> f64 { - *math::NormalizedAngle::atan2(self.from - self.inner_circle.pos) + let r = self.from - self.inner_circle.pos; + math::vector_angle(r) } pub fn spanned_angle(&self) -> f64 { @@ -279,7 +280,11 @@ impl BendShape { // atan2 returns values normalized into the range (-pi, pi] // so for angles below 0 we add 1 winding to get a nonnegative angle - angle.non_negative() + if angle < 0.0 { + angle + TAU + } else { + angle + } } /// Render this bend as a list of points on its circle. diff --git a/src/math/mod.rs b/src/math/mod.rs index f0bb08a..3698058 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: MIT -use core::{cmp, ops}; use geo::algorithm::line_measures::{Distance, Euclidean}; use geo::{geometry::Point, point, Line}; pub use specctra_core::math::{Circle, PointWithRotation}; @@ -98,139 +97,18 @@ pub fn between_vectors(p: Point, from: Point, to: Point) -> bool { } } -/// An angle that is measured counterclockwise and normalized into range (-pi, pi] (like atan2). -#[derive(Clone, Copy, Debug)] -pub struct NormalizedAngle(f64); - -impl cmp::PartialOrd for NormalizedAngle { - #[inline(always)] - fn partial_cmp(&self, oth: &Self) -> Option { - Some(self.cmp(oth)) - } -} - -impl cmp::Ord for NormalizedAngle { - #[inline(always)] - fn cmp(&self, oth: &Self) -> cmp::Ordering { - self.0.total_cmp(&oth.0) - } -} - -impl cmp::PartialEq for NormalizedAngle { - fn eq(&self, oth: &Self) -> bool { - self.cmp(oth) == cmp::Ordering::Equal - } -} - -impl cmp::Eq for NormalizedAngle {} - -impl NormalizedAngle { - pub const ZERO: Self = Self(0.0); - - fn normalize_single_step(mut angle: f64) -> Self { - use core::f64::consts::{PI, TAU}; - if !(angle.is_nan() || angle.is_infinite()) { - if angle <= -PI { - angle += TAU; - } - if angle > PI { - angle -= TAU; - } - assert!((-PI..PI).contains(&(-angle))); - } - Self(angle) - } - - /// Computes the (directed) angle between the positive X axis and the vector. - #[inline] - pub fn atan2(pt: Point) -> Self { - NormalizedAngle(pt.0.x.atan2(pt.0.y)) - } - - #[must_use] - pub fn non_negative(self) -> f64 { - let mut angle = self.0; - if angle < 0.0 { - angle + core::f64::consts::TAU - } else { - angle - } - } - - /// Rotate this angle by 180° - #[must_use] - pub fn flip(self) -> Self { - Self::normalize_single_step(self.0 + core::f64::consts::PI) - } -} - -impl From for NormalizedAngle { - fn from(mut angle: f64) -> Self { - use core::f64::consts::{PI, TAU}; - if !(angle.is_nan() || angle.is_infinite()) { - while angle <= -PI { - angle += TAU; - } - while angle > PI { - angle -= TAU; - } - debug_assert!((-PI..PI).contains(&(-angle))); - } - Self(angle) - } -} - -impl ops::Deref for NormalizedAngle { - type Target = f64; - - #[inline(always)] - fn deref(&self) -> &f64 { - &self.0 - } -} - -impl ops::Add for NormalizedAngle { - type Output = Self; - - fn add(self, oth: Self) -> Self { - Self::normalize_single_step(self.0 + oth.0) - } -} - -impl ops::AddAssign for NormalizedAngle { - fn add_assign(&mut self, oth: Self) { - *self = Self::normalize_single_step(self.0 + oth.0); - } -} - -impl ops::Sub for NormalizedAngle { - type Output = Self; - - fn sub(self, oth: Self) -> Self { - Self::normalize_single_step(self.0 - oth.0) - } -} - -impl ops::SubAssign for NormalizedAngle { - fn sub_assign(&mut self, oth: Self) { - *self = Self::normalize_single_step(self.0 - oth.0); - } -} - -impl ops::MulAssign for NormalizedAngle { - fn mul_assign(&mut self, oth: f64) { - *self = (self.0 * oth).into(); - } +/// Computes the (directed) angle between the positive X axis and the vector. +/// +/// The result is measured counterclockwise and normalized into range (-pi, pi] (like atan2). +pub fn vector_angle(vector: Point) -> f64 { + vector.y().atan2(vector.x()) } /// Computes the (directed) angle between two vectors. /// /// The result is measured counterclockwise and normalized into range (-pi, pi] (like atan2). -pub fn angle_between(v1: Point, v2: Point) -> NormalizedAngle { - NormalizedAngle::atan2(geo::point! { - x: dot_product(v1, v2), - y: perp_dot_product(v1, v2) - }) +pub fn angle_between(v1: Point, v2: Point) -> f64 { + perp_dot_product(v1, v2).atan2(dot_product(v1, v2)) } pub fn seq_perp_dot_product(start: Point, stop: Point, reference: Point) -> f64 {