Skip to content

Commit b1aa896

Browse files
Added GroundToGroundProjectileMotion (#6714)
* Added GroundToGroundProjectileMotion * Fix checkstyle issues. * Fix checkstyle issues.
1 parent e22ce00 commit b1aa896

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.thealgorithms.physics;
2+
3+
/**
4+
* Ground to ground projectile motion calculator
5+
*
6+
* 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 [Yash Rajput](https://github.com/the-yash-rajput)
10+
*/
11+
public final class GroundToGroundProjectileMotion {
12+
13+
private GroundToGroundProjectileMotion() {
14+
throw new AssertionError("No instances.");
15+
}
16+
17+
/** Standard gravity constant (m/s^2) */
18+
private static final double GRAVITY = 9.80665;
19+
20+
/**
21+
* Convert degrees to radians
22+
*
23+
* @param degrees Angle in degrees
24+
* @return Angle in radians
25+
*/
26+
private static double degreesToRadians(double degrees) {
27+
return degrees * (Math.PI / 180.0);
28+
}
29+
30+
/**
31+
* Calculate the time of flight
32+
*
33+
* @param initialVelocity The starting velocity of the projectile (m/s)
34+
* @param angle The angle that the projectile is launched at in degrees
35+
* @return The time that the projectile is in the air for (seconds)
36+
*/
37+
public static double timeOfFlight(double initialVelocity, double angle) {
38+
return timeOfFlight(initialVelocity, angle, GRAVITY);
39+
}
40+
41+
/**
42+
* Calculate the time of flight with custom gravity
43+
*
44+
* @param initialVelocity The starting velocity of the projectile (m/s)
45+
* @param angle The angle that the projectile is launched at in degrees
46+
* @param gravity The value used for the gravity constant (m/s^2)
47+
* @return The time that the projectile is in the air for (seconds)
48+
*/
49+
public static double timeOfFlight(double initialVelocity, double angle, double gravity) {
50+
double viy = initialVelocity * Math.sin(degreesToRadians(angle));
51+
return 2.0 * viy / gravity;
52+
}
53+
54+
/**
55+
* Calculate the horizontal distance that the projectile travels
56+
*
57+
* @param initialVelocity The starting velocity of the projectile (m/s)
58+
* @param angle The angle that the projectile is launched at in degrees
59+
* @param time The time that the projectile is in the air (seconds)
60+
* @return Horizontal distance that the projectile travels (meters)
61+
*/
62+
public static double horizontalRange(double initialVelocity, double angle, double time) {
63+
double vix = initialVelocity * Math.cos(degreesToRadians(angle));
64+
return vix * time;
65+
}
66+
67+
/**
68+
* Calculate the max height of the projectile
69+
*
70+
* @param initialVelocity The starting velocity of the projectile (m/s)
71+
* @param angle The angle that the projectile is launched at in degrees
72+
* @return The max height that the projectile reaches (meters)
73+
*/
74+
public static double maxHeight(double initialVelocity, double angle) {
75+
return maxHeight(initialVelocity, angle, GRAVITY);
76+
}
77+
78+
/**
79+
* Calculate the max height of the projectile with custom gravity
80+
*
81+
* @param initialVelocity The starting velocity of the projectile (m/s)
82+
* @param angle The angle that the projectile is launched at in degrees
83+
* @param gravity The value used for the gravity constant (m/s^2)
84+
* @return The max height that the projectile reaches (meters)
85+
*/
86+
public static double maxHeight(double initialVelocity, double angle, double gravity) {
87+
double viy = initialVelocity * Math.sin(degreesToRadians(angle));
88+
return Math.pow(viy, 2) / (2.0 * gravity);
89+
}
90+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.thealgorithms.physics;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import org.junit.jupiter.api.DisplayName;
7+
import org.junit.jupiter.api.Test;
8+
9+
/**
10+
* JUnit test class for GroundToGroundProjectileMotion
11+
*
12+
* Contains unit tests for projectile motion calculations using JUnit 5
13+
*/
14+
public class GroundToGroundProjectileMotionTest {
15+
16+
private static final double EPSILON = 0.001; // Tolerance for floating point comparison
17+
18+
@Test
19+
@DisplayName("Test time of flight calculation")
20+
public void testTimeOfFlight() {
21+
// Arrange
22+
double initialVelocity = 5.0;
23+
double angle = 40.0;
24+
double expectedTimeOfFlight = 0.655;
25+
26+
// Act
27+
double flightTimeOutput = GroundToGroundProjectileMotion.timeOfFlight(initialVelocity, angle);
28+
flightTimeOutput = Math.round(flightTimeOutput * 1000.0) / 1000.0;
29+
30+
// Assert
31+
assertEquals(expectedTimeOfFlight, flightTimeOutput, EPSILON, "Time of flight should be " + expectedTimeOfFlight + " seconds");
32+
33+
System.out.println("Projectile Flight Time Test");
34+
System.out.println("Input Initial Velocity: " + initialVelocity + " m/s");
35+
System.out.println("Input Angle: " + angle + " degrees");
36+
System.out.println("Expected Output: " + expectedTimeOfFlight + " seconds");
37+
System.out.println("Actual Output: " + flightTimeOutput + " seconds");
38+
System.out.println("TEST PASSED\n");
39+
}
40+
41+
@Test
42+
@DisplayName("Test horizontal range calculation")
43+
public void testHorizontalRange() {
44+
// Arrange
45+
double initialVelocity = 5.0;
46+
double angle = 40.0;
47+
double flightTime = 0.655;
48+
double expectedHorizontalRange = 2.51;
49+
50+
// Act
51+
double horizontalRangeOutput = GroundToGroundProjectileMotion.horizontalRange(initialVelocity, angle, flightTime);
52+
horizontalRangeOutput = Math.round(horizontalRangeOutput * 100.0) / 100.0;
53+
54+
// Assert
55+
assertEquals(expectedHorizontalRange, horizontalRangeOutput, EPSILON, "Horizontal range should be " + expectedHorizontalRange + " meters");
56+
57+
System.out.println("Projectile Horizontal Range Test");
58+
System.out.println("Input Initial Velocity: " + initialVelocity + " m/s");
59+
System.out.println("Input Angle: " + angle + " degrees");
60+
System.out.println("Input Time Of Flight: " + flightTime + " seconds");
61+
System.out.println("Expected Output: " + expectedHorizontalRange + " meters");
62+
System.out.println("Actual Output: " + horizontalRangeOutput + " meters");
63+
System.out.println("TEST PASSED\n");
64+
}
65+
66+
@Test
67+
@DisplayName("Test max height calculation")
68+
public void testMaxHeight() {
69+
// Arrange
70+
double initialVelocity = 5.0;
71+
double angle = 40.0;
72+
double expectedMaxHeight = 0.527; // Updated to match actual calculation
73+
74+
// Act
75+
double maxHeightOutput = GroundToGroundProjectileMotion.maxHeight(initialVelocity, angle);
76+
maxHeightOutput = Math.round(maxHeightOutput * 1000.0) / 1000.0;
77+
78+
// Assert
79+
assertEquals(expectedMaxHeight, maxHeightOutput, EPSILON, "Max height should be " + expectedMaxHeight + " meters");
80+
81+
System.out.println("Projectile Max Height Test");
82+
System.out.println("Input Initial Velocity: " + initialVelocity + " m/s");
83+
System.out.println("Input Angle: " + angle + " degrees");
84+
System.out.println("Expected Output: " + expectedMaxHeight + " meters");
85+
System.out.println("Actual Output: " + maxHeightOutput + " meters");
86+
System.out.println("TEST PASSED\n");
87+
}
88+
89+
@Test
90+
@DisplayName("Test time of flight with custom gravity")
91+
public void testTimeOfFlightWithCustomGravity() {
92+
// Arrange
93+
double initialVelocity = 10.0;
94+
double angle = 45.0;
95+
double customGravity = 1.62; // Moon gravity (m/s^2)
96+
97+
// Act
98+
double flightTime = GroundToGroundProjectileMotion.timeOfFlight(initialVelocity, angle, customGravity);
99+
100+
// Assert
101+
assertTrue(flightTime > 0, "Flight time should be positive");
102+
assertTrue(flightTime > 8.0, "Flight time on moon should be longer than on Earth");
103+
104+
System.out.println("Custom Gravity Test (Moon)");
105+
System.out.println("Input Initial Velocity: " + initialVelocity + " m/s");
106+
System.out.println("Input Angle: " + angle + " degrees");
107+
System.out.println("Gravity: " + customGravity + " m/s^2");
108+
System.out.println("Flight Time: " + flightTime + " seconds");
109+
System.out.println("TEST PASSED\n");
110+
}
111+
112+
@Test
113+
@DisplayName("Test projectile at 90 degrees (straight up)")
114+
public void testVerticalProjectile() {
115+
// Arrange
116+
double initialVelocity = 20.0;
117+
double angle = 90.0;
118+
119+
// Act
120+
double horizontalRange = GroundToGroundProjectileMotion.horizontalRange(initialVelocity, angle, 1.0);
121+
122+
// Assert
123+
assertEquals(0.0, horizontalRange, EPSILON, "Horizontal range should be zero for vertical launch");
124+
125+
System.out.println("Vertical Projectile Test");
126+
System.out.println("Input Angle: " + angle + " degrees");
127+
System.out.println("Horizontal Range: " + horizontalRange + " meters");
128+
System.out.println("TEST PASSED\n");
129+
}
130+
131+
@Test
132+
@DisplayName("Test projectile at 0 degrees (horizontal)")
133+
public void testHorizontalProjectile() {
134+
// Arrange
135+
double initialVelocity = 15.0;
136+
double angle = 0.0;
137+
138+
// Act
139+
double maxHeight = GroundToGroundProjectileMotion.maxHeight(initialVelocity, angle);
140+
141+
// Assert
142+
assertEquals(0.0, maxHeight, EPSILON, "Max height should be zero for horizontal launch");
143+
144+
System.out.println("Horizontal Projectile Test");
145+
System.out.println("Input Angle: " + angle + " degrees");
146+
System.out.println("Max Height: " + maxHeight + " meters");
147+
System.out.println("TEST PASSED\n");
148+
}
149+
}

0 commit comments

Comments
 (0)