diff --git a/src/main/java/com/thealgorithms/physics/SnellLaw.java b/src/main/java/com/thealgorithms/physics/SnellLaw.java new file mode 100644 index 000000000000..2736984814fd --- /dev/null +++ b/src/main/java/com/thealgorithms/physics/SnellLaw.java @@ -0,0 +1,33 @@ +package com.thealgorithms.physics; + +/** + * Calculates refraction angle using Snell's Law: + * n1 * sin(theta1) = n2 * sin(theta2) + * @see Snell's Law + */ +public final class SnellLaw { + + private SnellLaw() { + throw new AssertionError("No instances."); + } + + /** + * Computes the refracted angle (theta2) in radians. + * + * @param n1 index of refraction of medium 1 + * @param n2 index of refraction of medium 2 + * @param theta1 incident angle in radians + * @return refracted angle (theta2) in radians + * @throws IllegalArgumentException if total internal reflection occurs + */ + public static double refractedAngle(double n1, double n2, double theta1) { + double ratio = n1 / n2; + double sinTheta2 = ratio * Math.sin(theta1); + + if (Math.abs(sinTheta2) > 1.0) { + throw new IllegalArgumentException("Total internal reflection: no refraction possible."); + } + + return Math.asin(sinTheta2); + } +} diff --git a/src/test/java/com/thealgorithms/physics/SnellLawTest.java b/src/test/java/com/thealgorithms/physics/SnellLawTest.java new file mode 100644 index 000000000000..ddd5fb1d5af7 --- /dev/null +++ b/src/test/java/com/thealgorithms/physics/SnellLawTest.java @@ -0,0 +1,41 @@ +package com.thealgorithms.physics; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class SnellLawTest { + + @Test + public void testRefractedAngle() { + double n1 = 1.0; // air + double n2 = 1.5; // glass + double theta1 = Math.toRadians(30); + + double theta2 = SnellLaw.refractedAngle(n1, n2, theta1); + + double expected = Math.asin(n1 / n2 * Math.sin(theta1)); + + assertEquals(expected, theta2, 1e-12); + } + + @Test + public void testTotalInternalReflection() { + double n1 = 1.5; + double n2 = 1.0; + double theta1 = Math.toRadians(60); // large angle + + assertThrows(IllegalArgumentException.class, () -> SnellLaw.refractedAngle(n1, n2, theta1)); + } + + @Test + public void testNoTotalInternalReflectionAtLowAngles() { + double n1 = 1.5; + double n2 = 1.0; + double theta1 = Math.toRadians(10); + + assertDoesNotThrow(() -> SnellLaw.refractedAngle(n1, n2, theta1)); + } +}