Skip to content

Commit fad3fe5

Browse files
Added GroundToGroundProjectileMotion
1 parent 4fe37c3 commit fad3fe5

File tree

2 files changed

+238
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)