From 316def4ea65f68ca8982148b97896c8bfef27e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20S=C3=A1nchez=20N=C3=BA=C3=B1ez?= Date: Sun, 7 Dec 2025 12:18:55 +0100 Subject: [PATCH] Add Snell's Law refraction algorithm (#7150) * Add Snell's Law implementation for refraction angle * Add tests for Snell's Law calculations * Update documentation with reference link to Snell's Law Added a reference link to Snell's Law in the documentation. * Prevent instantiation of SnellLaw class Make SnellLaw class non-instantiable by adding a private constructor. * Rename SnellsLawTest to SnellLawTest * Refactor SnellLawTest for clarity and accuracy * Rename SnellsLaw.java to SnellLaw.java * Refactor SnellLawTest with additional assertions * Refactor SnellLaw class constructor and error handling Refactor SnellLaw constructor and error message formatting. * Fix missing newline at end of SnellLawTest.java Ensure that the SnellLawTest class has a newline at the end of the file. * Simplify assertions in SnellLawTest * Simplify exception throwing for total internal reflection --- .../com/thealgorithms/physics/SnellLaw.java | 33 +++++++++++++++ .../thealgorithms/physics/SnellLawTest.java | 41 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/main/java/com/thealgorithms/physics/SnellLaw.java create mode 100644 src/test/java/com/thealgorithms/physics/SnellLawTest.java 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 000000000..273698481 --- /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 000000000..ddd5fb1d5 --- /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)); + } +}