Group 1
def Rotate(v, theta):
s = sin(theta)
c = cos(theta)
return vec(v.x * c - v.y * s, v.x * s + v.y * c, 0)
Rotate v counterclockwise theta (rad)
class Ray:
def __init__(self, where, col, n):
self.ball = sphere(pos = where, color = col, radius = 1, make_trail=True)
self.v = c * -vec(cos(Ori_Ray_Angle), sin(Ori_Ray_Angle), 0)
self.collision_time = 0
self.in_water = False
self.n_water = n
class Beam:
# From Red to Purple
def __init__(self, where):
self.kind = 0
self.rays = []
self.target = 0
for i in range(6):
self.rays.append(Ray(where + 5 * Droplet_Radius * \
vec(cos(Ori_Ray_Angle), sin(Ori_Ray_Angle), 0), colors[i], N_WATER[i]))
nv = r.ball.pos - droplet.pos
if r.in_water == False:
# Refract into the droplet
if mag(nv) <= droplet.radius + EPS:
r.in_water = True
t1 = acos(dot(nv, r.v) / (mag(nv) * mag(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1) / r.n_water)
r.v = Rotate(-mag(r.v) * norm(nv), t2) / r.n_water
else:
if mag(nv) >= droplet.radius - EPS:
# Reflect in the droplet
if r.collision_time < 1:
r.collision_time += 1
t1 = acos(dot(nv, r.v) / (mag(nv) * mag(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1) / r.n_water)
r.v = Rotate(-mag(r.v) * norm(nv), t1)
# Refract out of the droplet
else:
r.in_water = False
t1 = acos(dot(norm(nv), norm(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1) * r.n_water)
r.v = Rotate(mag(r.v) * norm(nv), -t2) * r.n_water
This is what we expect to see
nv = r.ball.pos - droplet.pos
if r.in_water == False:
# Refract into the droplet
if mag(nv) <= droplet.radius + EPS:
r.in_water = True
t1 = acos(dot(nv, r.v) / (mag(nv) * mag(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1) / r.n_water)
r.v = rotate(-mag(r.v) * norm(nv), -t2) / r.n_water
else:
if mag(nv) >= droplet.radius - EPS:
# Reflect in the droplet
if r.collision_time < 2:
r.collision_time += 1
t1 = acos(dot(nv, r.v) / (mag(nv) * mag(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1))
t3 = asin(sin(t1) / r.n_water)
r.v = rotate(-mag(r.v) * norm(nv), -t2)
# Refract out of the droplet
else:
r.in_water = False
t1 = acos(dot(nv, r.v) / (mag(nv) * mag(r.v)))
t1 = pi - t1 if t1 >= pi / 2 else t1
t2 = asin(sin(t1) * r.n_water)
r.v = rotate(mag(r.v) * norm(nv), t2) * r.n_water
This is what we expect to see
Here we neglect the polarization of light and take the average of Rs and Rp.
The formula of reflectance
def weaken(t1, t2):
Rs = (sin(t2 - t1) / sin(t1 + t2))**2
Rp = (tan(t2 - t1) / tan(t1 + t2))**2
return (Rs + Rp) / 2
r.ball.opacity *= weaken(t1, t2) ** 0.3
Normally, the light rays become very dim compared to the incident sun rays.
To visualize the effect better,
we de-emphasized the weakening by a power of 0.3
r.ball.opacity *= (1-weaken(t1, t2)) ** 0.3
After we have the class Ray and Beam, we can expand the number of water droplets and beams more easily.
beams = []
droplets = []
for i in range (n_droplets):
dy=i*2.2*Droplet_Radius
droplets.append(sphere(pos=vector(2 * Droplet_Radius, 2 * Droplet_Radius+dy, 0),
radius = Droplet_Radius,opacity=0.3))
for i in range (n_beams):
beams.append(Beam(droplets[0].pos + vec(0, 3750 * (i + 1), 0)))
Rotate, Assign to Meow
for b in beams:
suc = 0
r = b.rays[0]
tmp_pos = r.ball.pos
while True:
tmp_pos += r.v * dt
for d in droplets:
nv = tmp_pos - d.pos
if mag(nv) <= d.radius + EPS:
b.target = d
suc = 1
break
if suc == 1:
break
Instead of brute-force in every time slot, this helps us to determine the droplet the ray is going to hit.
Red = 0.9243 (rad) = 52.96 (deg)
Purple = 0.8958 (rad) = 51.33 (deg)
0 (deg)
180 (deg)
Red = 1.20983 (rad) = 69.31 (deg)
Purple = 1.37293 (rad) = 78.66 (deg)
180 (deg)
0 (deg)
Secondary Rainbows
Red = 1.20983 (rad) = 69.31 (deg)
Purple = 1.37293 (rad) = 78.66 (deg)
Rainbows
Red = 0.9243 (rad) = 52.96 (deg)
Purple = 0.8958 (rad) = 51.33 (deg)
We can find that the formation angle of the secondary rainbow is usually higher than the rainbow.
0 (deg)
0 (deg)
180 (deg)
180 (deg)
42 degrees
matching scientific results
Rainbows not easy to form when sun is at high angle
(close to noon)
The secondary rainbow is harder to form and dimmer, so we seldom see them
Through our project, we investigated the formation of two kinds of rainbows, showed how human eye visualize rainbows, and examined the diagrams to compare with facts of rainbows we searched online.