From 7beca553eeb033611951917dec0f135c6144e1f1 Mon Sep 17 00:00:00 2001 From: Xu Shaohua Date: Tue, 1 Aug 2023 08:37:19 +0800 Subject: [PATCH] physics: Add horizontal projectile motion --- physics/src/horizontal_projectile_motion.rs | 74 +++++++++++++++++++++ physics/src/lib.rs | 1 + 2 files changed, 75 insertions(+) create mode 100644 physics/src/horizontal_projectile_motion.rs diff --git a/physics/src/horizontal_projectile_motion.rs b/physics/src/horizontal_projectile_motion.rs new file mode 100644 index 00000000..c576b840 --- /dev/null +++ b/physics/src/horizontal_projectile_motion.rs @@ -0,0 +1,74 @@ +// Copyright (c) 2023 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be found +// in the LICENSE file. + +//! Horizontal Projectile Motion problem in physics. +//! +//! [Projectile motion](https://en.wikipedia.org/wiki/Projectile_motion) + +/// Acceleration Constant on Earth (unit m/s^2) +pub const G: f64 = 9.80665; + +// Check that the arguments are valid +#[must_use] +fn check_args(init_velocity: f64, angle: f64) -> bool { + init_velocity >= 0.0 && (1.0..=90.0).contains(&angle) +} + +/// Returns the horizontal distance that the object cover +#[must_use] +pub fn horizontal_distance(init_velocity: f64, angle: f64) -> f64 { + debug_assert!(check_args(init_velocity, angle)); + let radians = (2.0 * angle).to_radians(); + init_velocity.powi(2) * (radians).sin() / G +} + +/// Returns the maximum height that the object reach +#[must_use] +pub fn max_height(init_velocity: f64, angle: f64) -> f64 { + debug_assert!(check_args(init_velocity, angle)); + let radians = angle.to_radians(); + init_velocity.powi(2) * radians.sin().powi(2) / (2.0 * G) +} + +/// Returns total time of the motion +#[must_use] +pub fn total_time(init_velocity: f64, angle: f64) -> f64 { + debug_assert!(check_args(init_velocity, angle)); + let radians = angle.to_radians(); + 2.0 * init_velocity * radians.sin() / G +} + +pub trait Round2 { + #[must_use] + fn round2(self) -> Self; +} + +impl Round2 for f64 { + fn round2(self) -> Self { + (self * 100.0).round() / 100.0 + } +} + +#[cfg(test)] +mod tests { + use super::{horizontal_distance, max_height, total_time, Round2}; + + #[test] + fn test_horizontal_distance() { + assert_eq!(horizontal_distance(30.0, 45.0).round2(), 91.77); + assert_eq!(horizontal_distance(100.0, 78.0).round2(), 414.76); + } + + #[test] + fn test_max_height() { + assert_eq!(max_height(30.0, 45.0).round2(), 22.94); + assert_eq!(max_height(100.0, 78.0).round2(), 487.82); + } + + #[test] + fn test_total_time() { + assert_eq!(total_time(30.0, 45.0).round2(), 4.33); + assert_eq!(total_time(100.0, 78.0).round2(), 19.95); + } +} diff --git a/physics/src/lib.rs b/physics/src/lib.rs index a2e336d3..a64c106d 100644 --- a/physics/src/lib.rs +++ b/physics/src/lib.rs @@ -14,6 +14,7 @@ pub mod archimedes_principle; pub mod casimir_effect; pub mod centripetal_force; pub mod grahams_law; +pub mod horizontal_projectile_motion; pub mod hubble_parameter; pub mod ideal_gas_law; pub mod kinetic_energy;