pub struct CASpring {
pub response: f32,
pub damping_ratio: f32,
}Expand description
Authentic macOS CoreAnimation damped harmonic oscillator spring model.
Matches Apple’s CASpringAnimation and SwiftUI .spring(response:dampingRatio:).
Provides exact closed-form analytical solutions for underdamped ($\zeta < 1$),
critically damped ($\zeta = 1$), and overdamped ($\zeta > 1$) regimes without
numerical Euler drift or floating-point overflow.
§Example
use egui_macview::CASpring;
// Create a responsive spring (0.35s period, 0.85 damping ratio)
let spring = CASpring::new(0.35, 0.85);
// Evaluate position x(t) in [0.0, 1.0]
let x_start = spring.evaluate(0.0);
let x_mid = spring.evaluate(0.15);
let x_settled = spring.evaluate(spring.settling_duration());
assert_eq!(x_start, 0.0);
assert!(x_mid > 0.0 && x_mid < 1.1);
assert!((x_settled - 1.0).abs() < 0.005);Fields§
§response: f32Perceptual oscillation period $T_0$ in seconds ($\ge 0.0001$).
damping_ratio: f32Dimensionless damping ratio $\zeta$ ($\ge 0.0$).
- $\zeta < 1.0$: Underdamped (oscillates with decaying overshoot).
- $\zeta = 1.0$: Critically damped (fastest decay with zero overshoot).
- $\zeta > 1.0$: Overdamped (smooth monotonic decay without oscillation).
Implementations§
Source§impl CASpring
impl CASpring
Sourcepub fn new(response: f32, damping_ratio: f32) -> Self
pub fn new(response: f32, damping_ratio: f32) -> Self
Creates a new CASpring from cycle period response (in seconds)
and dimensionless damping_ratio ($\zeta$).
Sourcepub fn from_perceptual(response: f32, damping_ratio: f32) -> Self
pub fn from_perceptual(response: f32, damping_ratio: f32) -> Self
Creates a CASpring using Apple SwiftUI / AppKit perceptual parameters
response (in seconds) and damping_ratio.
Sourcepub fn from_frequency(omega_0: f32, damping_ratio: f32) -> Self
pub fn from_frequency(omega_0: f32, damping_ratio: f32) -> Self
Creates a CASpring from undamped angular frequency $\omega_0$ (in rad/s)
and damping ratio $\zeta$.
Sourcepub fn from_physical(mass: f32, stiffness: f32, damping: f32) -> Self
pub fn from_physical(mass: f32, stiffness: f32, damping: f32) -> Self
Creates a CASpring from physical mass $m$, stiffness $k$, and damping $c$.
Sourcepub fn omega_0(&self) -> f32
pub fn omega_0(&self) -> f32
Undamped natural angular frequency $\omega_0 = \frac{2\pi}{\text{response}}$ in rad/s.
Sourcepub fn omega_d(&self) -> f32
pub fn omega_d(&self) -> f32
Damped angular frequency $\omega_d = \omega_0 \sqrt{|1 - \zeta^2|}$ in rad/s.
Sourcepub fn settling_duration(&self) -> f32
pub fn settling_duration(&self) -> f32
Analytical settling duration $t_{\text{settle}} = \frac{-\ln(\epsilon)}{\zeta \omega_0} = \frac{6.907755}{\zeta \omega_0}$ for underdamped/critically damped oscillators ($\zeta \le 1$), and the dominant pole $\frac{6.907755}{\zeta \omega_0 - \omega_d}$ for overdamped systems ($\zeta > 1$), to within $\epsilon = 0.001$ (0.1%) of target resting state.
Sourcepub fn animate_f32(&self, ctx: &Context, id: Id, target: f32) -> f32
pub fn animate_f32(&self, ctx: &Context, id: Id, target: f32) -> f32
Evaluates a stateful CASpring transition toward target using egui temporary memory,
requesting a repaint only while (target - start_val).abs() > f32::EPSILON and
elapsed < self.settling_duration().
Sourcepub fn animate_f32_at(
&self,
ctx: &Context,
id: Id,
target: f32,
now: f64,
frame_paced: bool,
) -> f32
pub fn animate_f32_at( &self, ctx: &Context, id: Id, target: f32, now: f64, frame_paced: bool, ) -> f32
Evaluates a stateful CASpring transition toward target at explicit timestamp now,
performing zero spring math or IdTypeMap write locks when settled at rest.
Sourcepub fn position_at(&self, t: f32) -> f32
pub fn position_at(&self, t: f32) -> f32
Evaluates displacement $x(t) \in [0.0, 1.0]$ at time $t$ in seconds.
Sourcepub fn overshoot_ratio(&self) -> f32
pub fn overshoot_ratio(&self) -> f32
Theoretical peak overshoot ratio over resting state (0.0 if critically or overdamped).
Trait Implementations§
impl Copy for CASpring
Source§impl<'de> Deserialize<'de> for CASpring
impl<'de> Deserialize<'de> for CASpring
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl StructuralPartialEq for CASpring
Auto Trait Implementations§
impl Forget for CASpring
impl Freeze for CASpring
impl RefUnwindSafe for CASpring
impl Send for CASpring
impl Sync for CASpring
impl Unpin for CASpring
impl UnsafeUnpin for CASpring
impl UnwindSafe for CASpring
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more