Skip to content

Commit 6d65697

Browse files
committed
feat: add Snell's Law refraction angle calculation
1 parent 791deb4 commit 6d65697

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

physics/snells_law.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
Snell's Law — Refraction Angle Calculation.
3+
4+
Calculates the angle of refraction when light passes between two
5+
media using Snell's Law: n1 * sin(theta1) = n2 * sin(theta2).
6+
7+
Reference: https://en.wikipedia.org/wiki/Snell%27s_law
8+
"""
9+
10+
import math
11+
12+
13+
def calculate_refraction_angle(
14+
index_of_refraction_1: float,
15+
index_of_refraction_2: float,
16+
incident_angle_degrees: float,
17+
) -> float:
18+
"""
19+
Calculates the refraction angle of light passing from one medium to another.
20+
The law states that, for a given pair of media, the ratio of the sines
21+
of angle of incidence and angle of refraction s equal to the refractive
22+
index of the second medium with regard to the first which is equal to the
23+
ratio of the refractive indices of the two media, or equivalently, to the
24+
ratio of the phase velocities in the two media.
25+
26+
27+
Formula: n1 * sin(theta1) = n2 * sin(theta2)
28+
or : (sin(theta1) / sin(theta2)) = (n2 / n1)
29+
Where:
30+
n1 = refractive index of the first medium
31+
n2 = refractive index of the second medium
32+
theta1 = angle of incidence
33+
theta2 = angle of refraction
34+
35+
Note: Total Internal Reflection (TIR) occurs when light travels from a
36+
denser medium to a rarer medium and the incident angle exceeds the
37+
critical angle, making refraction impossible.
38+
39+
Sources:
40+
- https://en.wikipedia.org/wiki/Snell%27s_law
41+
42+
-----------------------------------------------------------------------------
43+
44+
>>> calculate_refraction_angle(1.0, 1.33, 60.0)
45+
40.63
46+
>>> calculate_refraction_angle(2.0, 1.0, 30.0)
47+
90.0
48+
>>> calculate_refraction_angle(1.33, 1.0, 60.0)
49+
Traceback (most recent call last):
50+
...
51+
ValueError: Invalid physical inputs: ratio cannot be outside [-1, 1].
52+
>>> calculate_refraction_angle(-1.33, 1.0, 60.0)
53+
Traceback (most recent call last):
54+
...
55+
ValueError: Invalid physical inputs: ratio cannot be outside [-1, 1].
56+
>>>
57+
"""
58+
59+
incident_angle_radians = math.radians(incident_angle_degrees)
60+
refraction_sine = (index_of_refraction_1 / index_of_refraction_2) * math.sin(
61+
incident_angle_radians
62+
)
63+
64+
# If the sine value is approximately 1.0 or -1.0, it's at the critical angle
65+
# We use math.isclose to account for floating-point precision errors
66+
if math.isclose(refraction_sine, 1.0):
67+
return 90.0
68+
if math.isclose(refraction_sine, -1.0):
69+
return -90.0
70+
71+
if not -1 <= refraction_sine <= 1:
72+
raise ValueError("Invalid physical inputs: ratio cannot be outside [-1, 1].")
73+
74+
refraction_angle = round(math.degrees(math.asin(refraction_sine)), 2)
75+
return refraction_angle

0 commit comments

Comments
 (0)