1- /* *
2- * @file
3- * @brief Ground to ground [projectile
4- * motion](https://en.wikipedia.org/wiki/Projectile_motion) equation
5- * implementations
6- * @details Ground to ground projectile motion is when a projectile's trajectory
7- * starts at the ground, reaches the apex, then falls back on the ground.
8- *
9- * @author [Focusucof](https://github.com/Focusucof)
10- */
11-
12- #include < cassert> // / for assert()
1+ #include < cassert> // /< for assert()
132#define _USE_MATH_DEFINES
14- #include < cmath> // / for std::pow(), std::sin(), and std::cos()
15- #include < iostream> // / for IO operations
3+ #include < cmath> // /< for std::pow(), std::sin(), and std::cos()
4+ #include < iostream> // /< for IO operations
165
176/* *
187 * @namespace physics
2211// Define gravity as a constant within guidelines
2312constexpr double GRAVITY = 9.80665 ; // /< Standard gravity (m/s^2)
2413
14+ // New constants for rounding precision
15+ constexpr double ROUND_PRECISION_3 = 1000.0 ; // /< Precision for rounding to 3 decimal places
16+ constexpr double ROUND_PRECISION_2 = 100.0 ; // /< Precision for rounding to 2 decimal places
17+ constexpr double EPSILON = 0.001 ; // /< Tolerance for floating-point comparison
2518
2619namespace physics {
2720/* *
2821 * @namespace ground_to_ground_projectile_motion
29- * @brief Functions for the Ground to ground [projectile
30- * motion](https://en.wikipedia.org/wiki/Projectile_motion) equation
22+ * @brief Functions for the Ground to ground [projectile motion](https://en.wikipedia.org/wiki/Projectile_motion) equation
3123 */
3224namespace ground_to_ground_projectile_motion {
3325/* *
34- * @brief Convert radians to degrees
35- * @param radian Angle in radians
36- * @returns Angle in degrees
26+ * @brief Convert degrees to radians
27+ * @param degrees Angle in degrees
28+ * @returns Angle in radians
3729 */
38-
3930double degrees_to_radians (double degrees){
40- double radians = degrees * (M_PI / 180 );
41- return radians;
31+ return degrees * (M_PI / 180 );
32+ }
33+
34+ /* *
35+ * @brief Validate input parameters for projectile motion
36+ * @param velocity Initial velocity of the projectile
37+ * @param angle Launch angle in degrees
38+ * @returns True if inputs are valid, false otherwise
39+ */
40+ bool is_valid_input (double velocity, double angle) {
41+ return velocity >= 0.0 && angle >= 0.0 && angle <= 90.0 ;
4242}
4343
4444/* *
@@ -50,19 +50,20 @@ double degrees_to_radians(double degrees){
5050 */
5151template <typename T>
5252T time_of_flight (T initial_velocity, T angle, double gravity = GRAVITY) {
53- double Viy = initial_velocity * ( std::sin (degrees_to_radians (angle) )); // calculate y component of the initial velocity
53+ double Viy = initial_velocity * std::sin (degrees_to_radians (angle)); // calculate y component of the initial velocity
5454 return 2.0 * Viy / gravity;
5555}
5656
5757/* *
5858 * @brief Calculate the horizontal distance that the projectile travels
5959 * @param initial_velocity The starting velocity of the projectile
60+ * @param angle The angle that the projectile is launched at in degrees
6061 * @param time The time that the projectile is in the air
6162 * @returns Horizontal distance that the projectile travels
6263 */
6364template <typename T>
6465T horizontal_range (T initial_velocity, T angle, T time) {
65- double Vix = initial_velocity * ( std::cos (degrees_to_radians (angle) )); // calculate x component of the initial velocity
66+ double Vix = initial_velocity * std::cos (degrees_to_radians (angle)); // calculate x component of the initial velocity
6667 return Vix * time;
6768}
6869
@@ -75,8 +76,8 @@ T horizontal_range(T initial_velocity, T angle, T time) {
7576 */
7677template <typename T>
7778T max_height (T initial_velocity, T angle, double gravity = GRAVITY) {
78- double Viy = initial_velocity * ( std::sin (degrees_to_radians (angle) )); // calculate y component of the initial velocity
79- return ( std::pow (Viy, 2 ) / (2.0 * gravity) );
79+ double Viy = initial_velocity * std::sin (degrees_to_radians (angle)); // calculate y component of the initial velocity
80+ return std::pow (Viy, 2 ) / (2.0 * gravity);
8081}
8182} // namespace ground_to_ground_projectile_motion
8283} // namespace physics
@@ -90,49 +91,52 @@ static void test() {
9091 double initial_velocity = 5.0 ; // double initial_velocity input
9192 double angle = 40.0 ; // double angle input
9293
94+ // Validate inputs
95+ assert (physics::ground_to_ground_projectile_motion::is_valid_input (initial_velocity, angle));
96+
9397 // 1st test
9498 double expected_time_of_flight = 0.655 ; // expected time output
9599 double flight_time_output =
96- std::round (physics::ground_to_ground_projectile_motion::time_of_flight (initial_velocity, angle) * 1000.0 ) /
97- 1000.0 ; // round output to 3 decimal places
100+ std::round (physics::ground_to_ground_projectile_motion::time_of_flight (initial_velocity, angle) * ROUND_PRECISION_3 ) /
101+ ROUND_PRECISION_3 ; // round output to 3 decimal places
98102
99103 std::cout << " Projectile Flight Time (double)" << std::endl;
100104 std::cout << " Input Initial Velocity: " << initial_velocity << std::endl;
101105 std::cout << " Input Angle: " << angle << std::endl;
102106 std::cout << " Expected Output: " << expected_time_of_flight << std::endl;
103107 std::cout << " Output: " << flight_time_output << std::endl;
104- assert (flight_time_output == expected_time_of_flight);
108+ assert (std::abs ( flight_time_output - expected_time_of_flight) < EPSILON );
105109 std::cout << " TEST PASSED" << std::endl << std::endl;
106110
107111 // 2nd test
108112 double expected_horizontal_range = 2.51 ; // expected range output
109113 double horizontal_range_output =
110114 std::round (physics::ground_to_ground_projectile_motion::horizontal_range (initial_velocity, angle,
111115 flight_time_output) *
112- 100.0 ) /
113- 100.0 ; // round output to 2 decimal places
116+ ROUND_PRECISION_2 ) /
117+ ROUND_PRECISION_2 ; // round output to 2 decimal places
114118
115119 std::cout << " Projectile Horizontal Range (double)" << std::endl;
116120 std::cout << " Input Initial Velocity: " << initial_velocity << std::endl;
117121 std::cout << " Input Angle: " << angle << std::endl;
118122 std::cout << " Input Time Of Flight: " << flight_time_output << std::endl;
119123 std::cout << " Expected Output: " << expected_horizontal_range << std::endl;
120124 std::cout << " Output: " << horizontal_range_output << std::endl;
121- assert (horizontal_range_output == expected_horizontal_range);
125+ assert (std::abs ( horizontal_range_output - expected_horizontal_range) < EPSILON );
122126 std::cout << " TEST PASSED" << std::endl << std::endl;
123127
124128 // 3rd test
125129 double expected_max_height = 0.526 ; // expected height output
126130 double max_height_output =
127- std::round (physics::ground_to_ground_projectile_motion::max_height (initial_velocity, angle) * 1000.0 ) /
128- 1000.0 ; // round output to 3 decimal places
131+ std::round (physics::ground_to_ground_projectile_motion::max_height (initial_velocity, angle) * ROUND_PRECISION_3 ) /
132+ ROUND_PRECISION_3 ; // round output to 3 decimal places
129133
130134 std::cout << " Projectile Max Height (double)" << std::endl;
131135 std::cout << " Input Initial Velocity: " << initial_velocity << std::endl;
132136 std::cout << " Input Angle: " << angle << std::endl;
133137 std::cout << " Expected Output: " << expected_max_height << std::endl;
134138 std::cout << " Output: " << max_height_output << std::endl;
135- assert (max_height_output == expected_max_height);
139+ assert (std::abs ( max_height_output - expected_max_height) < EPSILON );
136140 std::cout << " TEST PASSED" << std::endl << std::endl;
137141}
138142
0 commit comments