Calculating refraction
3 minutes read
Python modules
We will need the following Python modules :
Angle calculation
In a refraction problem, you are usually given an incident ray, the IORs of both materials, and you want to calculate the refracted ray angle.
Refraction is described by the Snell-Descartes law : $$ n_i \sin i = n_r \sin r $$ With :
- $i$ the angle of the incident ray (measured from the normal to the interface) ;
- $r$ the angle of the refracted ray ;
- $n_i$ and $n_r$ the respective IORs of the materials.
There will also be a reflected ray of angle $-i$.
Another expression of the Snell’s-Descartes law, better suited to our usage, is : $$ r = \arcsin(\frac{n_i}{n_r}\sin i)$$
Which can be expressed as the following function in Python :
=
=
return
This function assumes that $i$ is in degrees, but the numpy functions work in radians, hence the need to convert it into $i_{rad} = \frac{\pi}{180}i$.
This function can give a RuntimeWarning in certain situations, but it can be ignored. It corresponds to a total internal reflection, in which no ray is refracted. It’s actually very convenient, because the Matplotlib figure will still work, and the refracted ray will not be displayed.
Ray calculation
We need to plot 3 straight lines, each defined by two points : an incident ray, a refracted ray and a reflected ray. The first point is where they intersect : the origin $(0,0)$. The other extremity of each line can simply be defined by trigonometric functions, in this case they will be placed on a circle of radius 1 :
In Python these coordinates are calculated in returned as a [ [x1,x2], [y1,y2] ] list :
=
=
= # incoming ray
= # refracted ray
= # reflected ray
return , , ,
The angle of the refracted ray r_rad is also returned, as it will be useful later for the interactive figure. This function uses the previous one to calculate it. Plotting the figure
The figure is created with the following function :
, , , =
# square figure
, =
, =
, =
# boundary between media
#ax.legend() # uncomment to display legend
# color for second medium
return , , ,
This function uses the previous one to calculate the coordinates of the lines, then plots a line for each ray. Once again, this function returns variables that will be useful for the interactive plot : the refracted angle in radians r_rad, and the line objects corresponding to the lines that were plotted on the graph l_i, l_r and l_rx. Usually, you might use ax.plot without saving it into a variable, but this will be essential for the next part !
All that’s left to do is use this function :
= 30 # degrees
= 1 # IOR of air
= 1.5 # IOR of glass
=
=
With these values, the result is the following plot : 
Now we can move on to the interactive part !