Up to CircularlyPolarizedLight in waves

This commit is contained in:
Grant Sanderson
2017-09-01 18:57:38 -07:00
parent 43c07680cb
commit 1966864d20
4 changed files with 366 additions and 22 deletions

View File

@ -98,14 +98,18 @@ class CyclicReplace(Transform):
class Swap(CyclicReplace): class Swap(CyclicReplace):
pass #Renaming, more understandable for two entries pass #Renaming, more understandable for two entries
class GrowFromCenter(Transform): class GrowFromPoint(Transform):
def __init__(self, mobject, **kwargs): def __init__(self, mobject, point, **kwargs):
target = mobject.copy() target = mobject.copy()
point = Point(mobject.get_center()) point_mob = Point(point)
mobject.replace(point) mobject.replace(point_mob)
mobject.highlight(point.get_color()) mobject.highlight(point_mob.get_color())
Transform.__init__(self, mobject, target, **kwargs) Transform.__init__(self, mobject, target, **kwargs)
class GrowFromCenter(GrowFromPoint):
def __init__(self, mobject, **kwargs):
GrowFromPoint.__init__(self, mobject, mobject.get_center(), **kwargs)
class SpinInFromNothing(GrowFromCenter): class SpinInFromNothing(GrowFromCenter):
CONFIG = { CONFIG = {
"path_func" : counterclockwise_path() "path_func" : counterclockwise_path()

View File

@ -141,10 +141,37 @@ class Line(VMobject):
start, end = self.get_start_and_end() start, end = self.get_start_and_end()
return angle_of_vector(end-start) return angle_of_vector(end-start)
# def put_start_and_end_on(self, new_start, new_end):
# self.set_start_and_end(new_start, new_end)
# self.buff = 0
# self.generate_points()
def put_start_and_end_on(self, new_start, new_end): def put_start_and_end_on(self, new_start, new_end):
self.set_start_and_end(new_start, new_end) target_vect = np.array(new_end) - np.array(new_start)
self.buff = 0 curr_vect = self.get_vector()
self.generate_points() target_norm = np.linalg.norm(target_vect)
##TODO, what if current length is 0?
curr_norm = np.linalg.norm(curr_vect)
if target_norm == 0:
epsilon = 0.001
self.scale(epsilon/curr_norm)
self.move_to(new_start)
return
unit_target = target_vect / target_norm
unit_curr = curr_vect / curr_norm
normal = np.cross(unit_target, unit_curr)
if np.linalg.norm(normal) == 0:
if unit_curr[0] == 0 and unit_curr[1] == 0:
normal = UP
else:
normal = OUT
angle_diff = np.arccos(
np.clip(np.dot(unit_target, unit_curr), -1, 1)
)
self.scale(target_norm/curr_norm)
self.rotate(-angle_diff, normal)
self.shift(new_start - self.get_start())
return self
class DashedLine(Line): class DashedLine(Line):
CONFIG = { CONFIG = {

View File

@ -117,7 +117,7 @@ class NumberLine(VMobject):
def add_tip(self): def add_tip(self):
start, end = self.main_line.get_start_and_end() start, end = self.main_line.get_start_and_end()
vect = (end - start)/np.linalg.norm(end-start) vect = (end - start)/np.linalg.norm(end-start)
arrow = Arrow(start, end + MED_LARGE_BUFF*vect) arrow = Arrow(start, end + MED_SMALL_BUFF*vect, buff = 0)
tip = arrow.tip tip = arrow.tip
tip.highlight(self.color) tip.highlight(self.color)
self.tip = tip self.tip = tip
@ -147,6 +147,7 @@ class Axes(VGroup):
"y_max" : SPACE_HEIGHT, "y_max" : SPACE_HEIGHT,
"z_min" : -3.5, "z_min" : -3.5,
"z_max" : 3.5, "z_max" : 3.5,
"z_normal" : DOWN,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
VGroup.__init__(self, **kwargs) VGroup.__init__(self, **kwargs)
@ -169,7 +170,7 @@ class Axes(VGroup):
**self.number_line_config **self.number_line_config
) )
self.z_axis.rotate(-np.pi/2, UP) self.z_axis.rotate(-np.pi/2, UP)
self.z_axis.rotate(np.pi/2, OUT) self.z_axis.rotate(angle_of_vector(self.z_normal), OUT)
self.add(self.z_axis) self.add(self.z_axis)
class ThreeDAxes(Axes): class ThreeDAxes(Axes):

336
waves.py
View File

@ -304,12 +304,13 @@ class FilterScene(ThreeDScene):
"EMWave_config" : { "EMWave_config" : {
"start_point" : SPACE_WIDTH*LEFT + DOWN+OUT "start_point" : SPACE_WIDTH*LEFT + DOWN+OUT
}, },
"axes_config" : {},
"start_phi" : 0.8*np.pi/2, "start_phi" : 0.8*np.pi/2,
"start_theta" : -0.6*np.pi, "start_theta" : -0.6*np.pi,
"ambient_rotation_rate" : 0.01, "ambient_rotation_rate" : 0.01,
} }
def setup(self): def setup(self):
self.axes = ThreeDAxes() self.axes = ThreeDAxes(**self.axes_config)
self.add(self.axes) self.add(self.axes)
for x in range(len(self.filter_x_coordinates) - len(self.pol_filter_configs)): for x in range(len(self.filter_x_coordinates) - len(self.pol_filter_configs)):
self.pol_filter_configs.append({}) self.pol_filter_configs.append({})
@ -1376,18 +1377,329 @@ class ShowVectorEquation(Scene):
self.play(*map(MoveToTarget, movers)) self.play(*map(MoveToTarget, movers))
self.dither(5) self.dither(5)
class ChangeFromHorizontalToVerticallyPolarized(Scene): class ChangeFromHorizontalToVerticallyPolarized(DirectionOfPolarizationScene):
CONFIG = {
"filter_x_coordinates" : [],
"EMWave_config" : {
"start_point" : SPACE_WIDTH*LEFT,
"A_vect" : [0, 2, 0],
}
}
def setup(self):
DirectionOfPolarizationScene.setup(self)
self.axes.z_axis.rotate(np.pi/2, OUT)
self.axes.y_axis.rotate(np.pi/2, UP)
self.remove(self.pol_filter)
self.em_wave.M_vects.set_fill(opacity = 0)
for vect in self.em_wave.E_vects:
vect.normal_vector = RIGHT
vect.set_fill(opacity = 0.5)
self.em_wave.E_vects[-1].set_fill(opacity = 1)
self.set_camera_position(0.9*np.pi/2, -0.05*np.pi)
def construct(self): def construct(self):
pass self.dither(3)
self.change_polarization_direction(np.pi/2)
self.dither(10)
class SumOfTwoWaves(ChangeFromHorizontalToVerticallyPolarized):
CONFIG = {
"axes_config" : {
"y_max" : 1.5,
"y_min" : -1.5,
"z_max" : 1.5,
"z_min" : -1.5,
},
"EMWave_config" : {
"A_vect" : [0, 0, 1],
}
}
def setup(self):
ChangeFromHorizontalToVerticallyPolarized.setup(self)
for vect in self.em_wave.E_vects[:-1]:
vect.set_fill(opacity = 0.3)
self.side_em_waves = []
for shift_vect, A_vect in (5*DOWN, [0, 1, 0]), (5*UP, [0, 1, 1]):
axes = self.axes.copy()
em_wave = copy.deepcopy(self.em_wave)
axes.shift(shift_vect)
em_wave.mobject.shift(shift_vect)
em_wave.start_point += shift_vect
for ov in em_wave.continual_animations:
ov.A_vect = np.array(A_vect)
self.add(axes, em_wave)
self.side_em_waves.append(em_wave)
self.set_camera_position(0.95*np.pi/2, -0.03*np.pi)
def construct(self):
plus, equals = pe = VGroup(*map(TexMobject, "+="))
pe.scale(2)
pe.rotate(np.pi/2, RIGHT)
pe.rotate(np.pi/2, OUT)
plus.shift(2.5*DOWN)
equals.shift(2.5*UP)
self.add(pe)
self.dither(32)
class ShowTipToTailSum(ShowVectorEquation):
def construct(self):
self.force_skipping()
self.add_vector()
self.add_plane()
self.add_vertial_vector()
self.revert_to_original_skipping_status()
self.add_kets()
self.show_vector_sum()
self.write_superposition()
self.add_amplitudes()
self.add_phase_shift()
def add_vertial_vector(self):
self.h_vector = self.vector
self.h_oscillating_vector = self.oscillating_vector
self.h_oscillating_vector.start_up_time = 0
self.v_oscillating_vector = self.h_oscillating_vector.copy()
self.v_vector = self.v_oscillating_vector.vector
self.v_oscillating_vector.A_vect = [0, 2, 0]
self.v_oscillating_vector.update(0)
self.d_oscillating_vector = ContinualUpdateFromFunc(
Vector(UP+RIGHT, color = E_COLOR),
lambda v : v.put_start_and_end_on(
ORIGIN,
self.v_vector.get_end()+ self.h_vector.get_end(),
)
)
self.d_vector = self.d_oscillating_vector.mobject
self.d_oscillating_vector.update(0)
self.add(self.v_oscillating_vector)
self.add_foreground_mobject(self.v_vector)
def add_kets(self):
h_ket, v_ket = kets = VGroup(*[
TexMobject(
"\\cos(", "2\\pi", "f", "t", ")",
"|\\!\\%sarrow\\rangle"%s
)
for s in "right", "up"
])
for ket in kets:
ket.highlight_by_tex_to_color_map({
"f" : self.f_color,
"rangle" : YELLOW,
})
ket.add_background_rectangle(opacity = 1)
ket.scale(0.8)
h_ket.next_to(2*RIGHT, UP, SMALL_BUFF)
v_ket.next_to(2*UP, UP, SMALL_BUFF)
self.add_foreground_mobject(kets)
self.kets = kets
def show_vector_sum(self):
h_line = DashedLine(ORIGIN, 2*RIGHT)
v_line = DashedLine(ORIGIN, 2*UP)
def generate_update_func(v1, v2):
def update_line(line):
line.put_start_and_end_on(
*v1.get_start_and_end()
)
line.shift(v2.get_end())
return update_line
h_line.update = generate_update_func(self.h_vector, self.v_vector)
v_line.update = generate_update_func(self.v_vector, self.h_vector)
h_ket, v_ket = self.kets
for ket in self.kets:
ket.generate_target()
plus = TexMobject("+")
ket_sum = VGroup(h_ket.target, plus, v_ket.target)
ket_sum.arrange_submobjects(RIGHT)
ket_sum.next_to(3*RIGHT + 2*UP, UP, SMALL_BUFF)
self.dither(4)
self.remove(self.h_oscillating_vector, self.v_oscillating_vector)
self.add(self.h_vector, self.v_vector)
h_line.update(h_line)
v_line.update(v_line)
self.play(*it.chain(
map(MoveToTarget, self.kets),
[Write(plus)],
map(ShowCreation, [h_line, v_line]),
))
blue_black = average_color(BLUE, BLACK)
self.play(
GrowFromPoint(self.d_vector, ORIGIN),
self.h_vector.set_fill, blue_black,
self.v_vector.set_fill, blue_black,
)
self.dither()
self.add(
self.h_oscillating_vector,
self.v_oscillating_vector,
self.d_oscillating_vector,
ContinualUpdateFromFunc(h_line, h_line.update),
ContinualUpdateFromFunc(v_line, v_line.update),
)
self.dither(4)
self.ket_sum = VGroup(h_ket, plus, v_ket)
def write_superposition(self):
superposition_words = TextMobject(
"``Superposition''", "of",
"$|\\!\\rightarrow\\rangle$", "and",
"$|\\!\\uparrow\\rangle$",
)
superposition_words.scale(0.8)
superposition_words.highlight_by_tex("rangle", YELLOW)
superposition_words.add_background_rectangle()
superposition_words.to_corner(UP+LEFT)
ket_sum = self.ket_sum
ket_sum.generate_target()
ket_sum.target.move_to(superposition_words)
ket_sum.target.align_to(ket_sum, UP)
sum_word = TextMobject("", "Sum")
weighted_sum_word = TextMobject("Weighted", "sum")
for word in sum_word, weighted_sum_word:
word.scale(0.8)
word.highlight(GREEN)
word.add_background_rectangle()
word.move_to(superposition_words.get_part_by_tex("Super"))
self.play(
Write(superposition_words, run_time = 2),
MoveToTarget(ket_sum)
)
self.dither(2)
self.play(
FadeIn(sum_word),
superposition_words.shift, MED_LARGE_BUFF*DOWN,
ket_sum.shift, MED_LARGE_BUFF*DOWN,
)
self.dither()
self.play(ReplacementTransform(
sum_word, weighted_sum_word
))
self.dither(2)
def add_amplitudes(self):
h_ket, plus, r_ket = self.ket_sum
for mob in self.ket_sum:
mob.generate_target()
h_A, v_A = 2, 0.5
h_A_mob, v_A_mob = A_mobs = VGroup(*[
TexMobject(str(A)).add_background_rectangle()
for A in [h_A, v_A]
])
A_mobs.scale(0.8)
A_mobs.highlight(GREEN)
h_A_mob.move_to(h_ket, LEFT)
VGroup(h_ket.target, plus.target).next_to(
h_A_mob, RIGHT, SMALL_BUFF
)
v_A_mob.next_to(plus.target, RIGHT, SMALL_BUFF)
r_ket.target.next_to(v_A_mob, RIGHT, SMALL_BUFF)
A_mobs.shift(0.4*SMALL_BUFF*UP)
h_ov = self.h_oscillating_vector
v_ov = self.v_oscillating_vector
def generate_update(ov, A, prev_A_vect):
def update(vect, alpha):
ov.A_vect = interpolate(
np.array(prev_A_vect),
A * np.array(prev_A_vect),
alpha
)
return vect
return update
self.play(*it.chain(
map(MoveToTarget, self.ket_sum),
map(Write, A_mobs),
[
UpdateFromAlphaFunc(
ov.vector,
generate_update(ov, A, np.array(ov.A_vect))
)
for ov, A in (h_ov, h_A), (v_ov, v_A)
]
))
self.dither(4)
self.A_mobs = A_mobs
self.generate_A_update = generate_update
def add_phase_shift(self):
h_ket, plus, v_ket = self.ket_sum
plus_phi = TexMobject("+", "\\pi/2")
plus_phi.highlight_by_tex("pi", self.phi_color)
plus_phi.scale(0.8)
plus_phi.next_to(v_ket.get_part_by_tex("t"), RIGHT, SMALL_BUFF)
v_ket.generate_target()
VGroup(*v_ket.target[1][-2:]).next_to(plus_phi, RIGHT, SMALL_BUFF)
v_ket.target[0].replace(v_ket.target[1])
h_ov = self.h_oscillating_vector
v_ov = self.v_oscillating_vector
def generate_update(ov, phi_vect, prev_phi_vect):
def update(vect, alpha):
ov.phi_vect = interpolate(
prev_phi_vect, phi_vect, alpha
)
return vect
return update
ellipse = Circle()
ellipse.stretch_to_fit_height(2)
ellipse.stretch_to_fit_width(8)
ellipse.highlight(self.phi_color)
self.add_foreground_mobject(plus_phi)
self.play(
MoveToTarget(v_ket),
Write(plus_phi),
UpdateFromAlphaFunc(
v_ov.vector,
generate_update(
v_ov,
np.array([0, np.pi/2, 0]),
np.array(v_ov.phi_vect)
)
)
)
self.play(FadeIn(ellipse))
self.dither(5)
self.play(
UpdateFromAlphaFunc(
h_ov.vector,
self.generate_A_update(
h_ov, 0.25, np.array(h_ov.A_vect)
)
),
ellipse.stretch, 0.25, 0
)
self.dither(8)
class CircularlyPolarizedLight(SumOfTwoWaves):
CONFIG = {
"EMWave_config" : {
"phi_vect" : [0, np.pi/2, 0],
}
}