-
-
Notifications
You must be signed in to change notification settings - Fork 50.5k
feat: add Snell's Law refraction angle calculation #14623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import math | ||
|
|
||
|
|
||
| def calculate_refraction_angle( | ||
| index_of_refraction_1: float, | ||
| index_of_refraction_2: float, | ||
| incident_angle_degrees: float, | ||
| ) -> float: | ||
| """ | ||
| Calculates the refraction angle of light passing from one medium to another. | ||
| The law states that, for a given pair of media, the ratio of the sines | ||
| of angle of incidence and angle of refraction s equal to the refractive | ||
| index of the second medium with regard to the first which is equal to the | ||
| ratio of the refractive indices of the two media, or equivalently, to the | ||
| ratio of the phase velocities in the two media. | ||
|
|
||
|
|
||
| Formula: n1 * sin(theta1) = n2 * sin(theta2) | ||
| or : (sin(theta1) / sin(theta2)) = (n2 / n1) | ||
| Where: | ||
| n1 = refractive index of the first medium | ||
| n2 = refractive index of the second medium | ||
| theta1 = angle of incidence | ||
| theta2 = angle of refraction | ||
|
|
||
| Note: Total Internal Reflection (TIR) occurs when light travels from a | ||
| denser medium to a rarer medium and the incident angle exceeds the | ||
| critical angle, making refraction impossible. | ||
|
|
||
| Sources: | ||
| - https://en.wikipedia.org/wiki/Snell%27s_law | ||
|
|
||
| ----------------------------------------------------------------------------- | ||
|
|
||
| >>> calculate_refraction_angle(1.0, 1.33, 60.0) | ||
| 40.63 | ||
| >>> calculate_refraction_angle(2.0, 1.0, 30.0) | ||
| 90.0 | ||
| >>> calculate_refraction_angle(1.33, 1.0, 60.0) | ||
| Traceback (most recent call last): | ||
| ... | ||
| ValueError: Total Internal Reflection occurred. | ||
| >>> calculate_refraction_angle(-1.33, 1.0, 60.0) | ||
| Traceback (most recent call last): | ||
| ... | ||
| ValueError: Invalid physical inputs: ratio cannot be less than -1. | ||
|
|
||
| """ | ||
|
|
||
| incident_angle_radians = math.radians(incident_angle_degrees) | ||
| refraction_sine = (index_of_refraction_1 / index_of_refraction_2) * math.sin( | ||
| incident_angle_radians | ||
| ) | ||
|
|
||
| if refraction_sine > 1: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good check for Total Internal Reflection — this correctly catches However the check on line 57 (refraction_sine < -1) will never if not -1 <= refraction_sine <= 1: |
||
| raise ValueError("Total Internal Reflection occurred.") | ||
| if refraction_sine < -1: | ||
| raise ValueError("Invalid physical inputs: ratio cannot be less than -1.") | ||
|
|
||
| # If the sine value is approximately 1.0, it's at the critical angle | ||
| # We use math.isclose to account for floating-point precision errors | ||
| if math.isclose(refraction_sine, 1.0): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Smart use of math.isclose() here to handle floating-point precision Suggestion: consider also handling the case where refraction_sine |
||
| return 90.0 | ||
|
|
||
| refraction_angle = round(math.degrees(math.asin(refraction_sine)), 2) | ||
| return refraction_angle | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file is missing a module-level docstring. The repo's convention
is to have a module docstring before imports. Consider adding:
"""
Snell's Law — Refraction Angle Calculation.
Calculates the angle of refraction when light passes between two
media using Snell's Law: n1 * sin(theta1) = n2 * sin(theta2).
Reference: https://en.wikipedia.org/wiki/Snell%27s_law
"""