mirror of
https://github.com/3b1b/manim.git
synced 2025-09-19 04:41:56 +00:00
Fixed some issues with how EM waves worked. Quite possibly a few remain
This commit is contained in:
parent
80c433820c
commit
151914c1a2
5 changed files with 396 additions and 149 deletions
406
bell.py
406
bell.py
|
@ -73,64 +73,6 @@ class FilterScene(ThreeDScene):
|
|||
rate_func = squish_rate_func(there_and_back, alpha - 0.1, alpha + 0.1)
|
||||
)
|
||||
|
||||
class PhotonPassesCompletelyOrNotAtAll(FilterScene):
|
||||
CONFIG = {
|
||||
"pol_filter_configs" : [{
|
||||
"include_arrow_label" : False,
|
||||
"label_tex" : "\\text{Filter}",
|
||||
}],
|
||||
"start_theta" : -0.9*np.pi,
|
||||
"target_theta" : -0.6*np.pi,
|
||||
}
|
||||
def construct(self):
|
||||
pol_filter = self.pol_filter
|
||||
label = pol_filter.label
|
||||
pol_filter.remove(label)
|
||||
label.shift(SMALL_BUFF*IN)
|
||||
|
||||
passing_words = TextMobject("Photon", "passes through")
|
||||
passing_words.highlight(GREEN)
|
||||
filtered_words = TextMobject("Photon", "is blocked")
|
||||
filtered_words.highlight(RED)
|
||||
for words in passing_words, filtered_words:
|
||||
words.next_to(ORIGIN, UP+LEFT)
|
||||
words.shift(2*UP)
|
||||
words.add_background_rectangle()
|
||||
words.rotate(np.pi/2, RIGHT)
|
||||
|
||||
passing_photon = WavePacket(
|
||||
run_time = 3,
|
||||
get_filtered = False,
|
||||
EMWave_config = self.EMWave_config
|
||||
)
|
||||
new_em_wave_config = dict(self.EMWave_config)
|
||||
new_em_wave_config["A_x"] = 0
|
||||
new_em_wave_config["A_y"] = 1
|
||||
filtered_photon = WavePacket(
|
||||
run_time = 3,
|
||||
get_filtered = True,
|
||||
EMWave_config = new_em_wave_config
|
||||
)
|
||||
|
||||
|
||||
self.play(
|
||||
DrawBorderThenFill(pol_filter),
|
||||
Write(label, run_time = 2)
|
||||
)
|
||||
self.move_camera(theta = self.target_theta)
|
||||
self.play(Write(passing_words, run_time = 1))
|
||||
self.play(passing_photon)
|
||||
self.play(Transform(passing_words, filtered_words))
|
||||
self.play(
|
||||
filtered_photon,
|
||||
ApplyMethod(
|
||||
pol_filter.set_fill, RED,
|
||||
rate_func = squish_rate_func(there_and_back, 0.4, 0.6),
|
||||
run_time = filtered_photon.run_time
|
||||
)
|
||||
)
|
||||
self.dither(3)
|
||||
|
||||
class DirectionOfPolarization(FilterScene):
|
||||
CONFIG = {
|
||||
"pol_filter_configs" : [{
|
||||
|
@ -201,7 +143,7 @@ class DirectionOfPolarization(FilterScene):
|
|||
)
|
||||
for pol_filter in filters:
|
||||
filter_x = pol_filter.get_center()[0]
|
||||
for vect_group, angle in (self.em_wave.E_vects, 0), (self.em_wave.M_vects, np.pi/2):
|
||||
for vect_group, angle in (self.em_wave.E_vects, 0), (self.em_wave.M_vects, -np.pi/2):
|
||||
proj_vect = rotate_vector(
|
||||
OUT, pol_filter.filter_angle + angle, RIGHT,
|
||||
)
|
||||
|
@ -215,7 +157,74 @@ class DirectionOfPolarization(FilterScene):
|
|||
vect.apply_matrix(proj_matrix)
|
||||
vect.shift(start - vect.get_start())
|
||||
|
||||
class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
||||
class PhotonPassesCompletelyOrNotAtAll(DirectionOfPolarization):
|
||||
CONFIG = {
|
||||
"pol_filter_configs" : [{
|
||||
"include_arrow_label" : False,
|
||||
"label_tex" : "\\text{Filter}",
|
||||
}],
|
||||
"EMWave_config" : {
|
||||
"wave_number" : 0,
|
||||
"A_vect" : [0, 1, 1],
|
||||
},
|
||||
"start_theta" : -0.9*np.pi,
|
||||
"target_theta" : -0.6*np.pi,
|
||||
}
|
||||
def setup(self):
|
||||
DirectionOfPolarization.setup(self)
|
||||
self.continual_update()
|
||||
for vect in it.chain(self.em_wave.E_vects, self.em_wave.M_vects):
|
||||
vect.reset_normal_vector()
|
||||
self.remove(self.em_wave)
|
||||
|
||||
def construct(self):
|
||||
|
||||
pol_filter = self.pol_filter
|
||||
label = pol_filter.label
|
||||
pol_filter.remove(label)
|
||||
label.shift(SMALL_BUFF*IN)
|
||||
|
||||
passing_words = TextMobject("Photon", "passes through")
|
||||
passing_words.highlight(GREEN)
|
||||
filtered_words = TextMobject("Photon", "is blocked")
|
||||
filtered_words.highlight(RED)
|
||||
for words in passing_words, filtered_words:
|
||||
words.next_to(ORIGIN, UP+LEFT)
|
||||
words.shift(2*UP)
|
||||
words.add_background_rectangle()
|
||||
words.rotate(np.pi/2, RIGHT)
|
||||
self.continual_update()
|
||||
|
||||
passing_photon = WavePacket(
|
||||
run_time = 2,
|
||||
get_filtered = False,
|
||||
em_wave = self.em_wave.copy()
|
||||
)
|
||||
filtered_photon = WavePacket(
|
||||
run_time = 2,
|
||||
get_filtered = True,
|
||||
em_wave = self.em_wave.copy()
|
||||
)
|
||||
|
||||
self.play(
|
||||
DrawBorderThenFill(pol_filter),
|
||||
Write(label, run_time = 2)
|
||||
)
|
||||
self.move_camera(theta = self.target_theta)
|
||||
self.play(Write(passing_words, run_time = 1))
|
||||
self.play(passing_photon)
|
||||
self.play(Transform(passing_words, filtered_words))
|
||||
self.play(
|
||||
filtered_photon,
|
||||
ApplyMethod(
|
||||
pol_filter.set_fill, RED,
|
||||
rate_func = squish_rate_func(there_and_back, 0.4, 0.6),
|
||||
run_time = filtered_photon.run_time
|
||||
)
|
||||
)
|
||||
self.dither(3)
|
||||
|
||||
class PhotonsThroughPerpendicularFilters(PhotonPassesCompletelyOrNotAtAll):
|
||||
CONFIG = {
|
||||
"filter_x_coordinates" : [-2, 2],
|
||||
"pol_filter_configs" : [
|
||||
|
@ -225,13 +234,9 @@ class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
|||
"start_theta" : -0.9*np.pi,
|
||||
"target_theta" : -0.6*np.pi,
|
||||
"EMWave_config" : {
|
||||
"wave_number" : 0,
|
||||
"A_vect" : [0, 0, 1],
|
||||
}
|
||||
}
|
||||
def setup(self):
|
||||
DirectionOfPolarization.setup(self)
|
||||
self.remove(self.em_wave)
|
||||
|
||||
def construct(self):
|
||||
photons = self.get_photons()[:2]
|
||||
prob_text = self.get_probability_text()
|
||||
|
@ -245,7 +250,7 @@ class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
|||
]
|
||||
)
|
||||
for x in range(4):
|
||||
pairs = zip(photons, self.pol_filters)
|
||||
pairs = zip(photons, reversed(self.pol_filters))
|
||||
random.shuffle(pairs)
|
||||
for photon, pol_filter in pairs:
|
||||
self.play(
|
||||
|
@ -263,7 +268,7 @@ class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
|||
filter_distance = SPACE_WIDTH + x,
|
||||
get_filtered = True,
|
||||
em_wave = self.em_wave.copy(),
|
||||
run_time = 1.5,
|
||||
run_time = 1,
|
||||
)
|
||||
for x in -2, 2, 10
|
||||
]
|
||||
|
@ -457,8 +462,7 @@ class BasicsOfPolarization(DirectionOfPolarization):
|
|||
config = dict(self.EMWave_config)
|
||||
config.update({
|
||||
"wave_number" : 0,
|
||||
"A_x" : -1,
|
||||
"A_y" : 1,
|
||||
"A_vect" : [0, 1, -1],
|
||||
})
|
||||
self.em_wave = EMWave(**config)
|
||||
self.continual_update()
|
||||
|
@ -507,12 +511,15 @@ class ShowVariousFilterPairs(PhotonsThroughPerpendicularFilters):
|
|||
}
|
||||
def construct(self):
|
||||
self.photons = self.get_photons()
|
||||
new_filters = self.new_filters = self.pol_filters[2:]
|
||||
self.remove(*new_filters)
|
||||
self.pol_filters = self.pol_filters[:2]
|
||||
|
||||
self.add_filters()
|
||||
self.add_probability_text()
|
||||
self.show_photons()
|
||||
self.revert_to_original_skipping_status()
|
||||
for pol_filter in self.pol_filters[2:]:
|
||||
for pol_filter in new_filters:
|
||||
self.change_to_new_filter(pol_filter)
|
||||
self.show_photons()
|
||||
|
||||
|
@ -533,7 +540,7 @@ class ShowVariousFilterPairs(PhotonsThroughPerpendicularFilters):
|
|||
for pf in self.pol_filters[:2]
|
||||
]))
|
||||
)
|
||||
for pf in self.pol_filters[2:]:
|
||||
for pf in self.new_filters:
|
||||
pf.arrow_label.rotate_in_place(np.pi/2, OUT)
|
||||
pf.arrow_label.next_to(pf.arrow, RIGHT)
|
||||
|
||||
|
@ -547,17 +554,40 @@ class ShowVariousFilterPairs(PhotonsThroughPerpendicularFilters):
|
|||
|
||||
def show_photons(self, n_photons = 5):
|
||||
p = self.get_prob()
|
||||
blocked_photon = copy.deepcopy(self.photons[0])
|
||||
blocked_photon.rate_func = squish_rate_func(
|
||||
lambda x : x, 0, 0.5,
|
||||
)
|
||||
first_absorbtion = self.get_filter_absorbtion_animation(
|
||||
self.pol_filters[0], blocked_photon
|
||||
)
|
||||
first_absorbtion.rate_func = squish_rate_func(
|
||||
first_absorbtion.rate_func, 0, 0.5,
|
||||
)
|
||||
|
||||
photons = [
|
||||
copy.deepcopy(self.photons[2 if random.random() < p else 1])
|
||||
for x in range(n_photons)
|
||||
]
|
||||
for photon in photons:
|
||||
photon.rate_func = squish_rate_func(
|
||||
lambda x : x, 0.5, 1
|
||||
)
|
||||
added_anims = []
|
||||
if photon.filter_distance == 2:
|
||||
added_anims.append(self.get_filter_absorbtion_animation(
|
||||
if photon.filter_distance == SPACE_WIDTH + 2:
|
||||
absorbtion = self.get_filter_absorbtion_animation(
|
||||
self.second_filter, photon
|
||||
))
|
||||
self.play(photon, *added_anims, run_time = 1.5)
|
||||
)
|
||||
absorbtion.rate_func = squish_rate_func(
|
||||
absorbtion.rate_func, 0.5, 1
|
||||
)
|
||||
added_anims.append(absorbtion)
|
||||
self.play(
|
||||
blocked_photon,
|
||||
first_absorbtion,
|
||||
photon,
|
||||
*added_anims
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def change_to_new_filter(self, pol_filter):
|
||||
|
@ -603,8 +633,8 @@ class ForgetPreviousActions(PhotonsThroughPerpendicularFilters):
|
|||
|
||||
self.add(rect1)
|
||||
self.play(Write(prob_words))
|
||||
for x in range(2):
|
||||
self.shoot_photon()
|
||||
# for x in range(2):
|
||||
# self.shoot_photon()
|
||||
|
||||
rect2 = SurroundingRectangle(self.pol_filter, color = RED)
|
||||
rect2.rotate_in_place(np.pi/2, RIGHT)
|
||||
|
@ -619,8 +649,10 @@ class ForgetPreviousActions(PhotonsThroughPerpendicularFilters):
|
|||
ShowCreation(rect2),
|
||||
Write(ignore_words, run_time = 1)
|
||||
)
|
||||
for x in range(4):
|
||||
self.shoot_photon()
|
||||
self.shoot_photon()
|
||||
self.dither(2)
|
||||
# for x in range(4):
|
||||
# self.shoot_photon()
|
||||
|
||||
|
||||
def shoot_photon(self):
|
||||
|
@ -646,8 +678,6 @@ class VennDiagramProofByContradiction(Scene):
|
|||
"circle_colors" : [RED, GREEN, BLUE]
|
||||
}
|
||||
def construct(self):
|
||||
# self.force_skipping()
|
||||
|
||||
self.draw_venn_diagram()
|
||||
self.show_100_photons()
|
||||
self.show_one_photon_answering_questions()
|
||||
|
@ -655,8 +685,6 @@ class VennDiagramProofByContradiction(Scene):
|
|||
self.separate_by_B()
|
||||
self.separate_by_C()
|
||||
self.show_two_relevant_subsets()
|
||||
self.show_real_value()
|
||||
self.contradiction()
|
||||
|
||||
def draw_venn_diagram(self):
|
||||
venn_diagrom = VGroup(*[
|
||||
|
@ -714,7 +742,8 @@ class VennDiagramProofByContradiction(Scene):
|
|||
lambda x : -np.cos(3*np.pi*x)*np.exp(-x*x),
|
||||
x_min = -2,
|
||||
x_max = 2,
|
||||
color = YELLOW
|
||||
color = YELLOW,
|
||||
stroke_width = 2,
|
||||
)
|
||||
photon.shift(LEFT + 2*UP)
|
||||
eyes = Eyes(photon)
|
||||
|
@ -790,7 +819,11 @@ class VennDiagramProofByContradiction(Scene):
|
|||
|
||||
A_group.generate_target()
|
||||
A_group.target.scale(4)
|
||||
A_group.target.center().to_edge(UP)
|
||||
A_group.target.shift(
|
||||
(SPACE_HEIGHT-MED_LARGE_BUFF)*UP - \
|
||||
A_group.target[0].get_top()
|
||||
)
|
||||
A_group.target[1].scale_in_place(0.8)
|
||||
|
||||
self.play(
|
||||
B_group.fade, 1,
|
||||
|
@ -808,19 +841,203 @@ class VennDiagramProofByContradiction(Scene):
|
|||
self.C_group = C_group
|
||||
|
||||
def separate_by_B(self):
|
||||
pass
|
||||
A_group = self.A_group
|
||||
B_group = self.B_group
|
||||
photons = self.photons
|
||||
B_circle = B_group[0]
|
||||
|
||||
B_group.target = B_group.saved_state
|
||||
B_group.target.scale(4)
|
||||
B_group.target.move_to(A_group)
|
||||
B_group.target.shift(1.25*DOWN+3.25*LEFT)
|
||||
B_group.target[1].shift(DOWN)
|
||||
B_group.target[1].scale_in_place(0.8)
|
||||
B_center = B_group.target[0].get_center()
|
||||
photons.sort_submobjects(
|
||||
lambda p : np.linalg.norm(p-B_center)
|
||||
)
|
||||
in_B = VGroup(*photons[:85])
|
||||
out_of_B = VGroup(*photons[85:])
|
||||
out_of_B.sort_submobjects(lambda p : np.dot(p, 2*UP+LEFT))
|
||||
|
||||
words = TextMobject("15 blocked \\\\ by ", "B")
|
||||
words.highlight_by_tex("B", GREEN)
|
||||
words.scale(0.8)
|
||||
words.next_to(A_group, LEFT, LARGE_BUFF, UP)
|
||||
arrow = Arrow(words.get_right(), out_of_B[-1])
|
||||
arrow.highlight(RED)
|
||||
|
||||
self.play(
|
||||
MoveToTarget(B_group),
|
||||
in_B.space_out_submobjects, 0.8,
|
||||
in_B.shift, MED_SMALL_BUFF*(DOWN+LEFT),
|
||||
)
|
||||
self.play(
|
||||
Write(words, run_time = 1),
|
||||
ShowCreation(arrow)
|
||||
)
|
||||
self.play(LaggedStart(
|
||||
Indicate, out_of_B,
|
||||
rate_func = there_and_back,
|
||||
color = RED,
|
||||
scale_factor = 2,
|
||||
))
|
||||
self.dither()
|
||||
|
||||
self.in_B = in_B
|
||||
self.out_of_B = out_of_B
|
||||
self.out_of_B_words = words
|
||||
self.out_of_B_arrow = arrow
|
||||
|
||||
def separate_by_C(self):
|
||||
pass
|
||||
B_group = self.B_group
|
||||
C_group = self.C_group
|
||||
in_B = self.in_B
|
||||
|
||||
C_group.target = C_group.saved_state
|
||||
C_group.target.scale(4)
|
||||
C_group.target.move_to(B_group, DOWN)
|
||||
C_group.target.shift(4.5*RIGHT)
|
||||
C_center = C_group.target[0].get_center()
|
||||
C_group.target[1].scale_in_place(0.8)
|
||||
|
||||
in_B.sort_submobjects(
|
||||
lambda p : np.linalg.norm(p - C_center)
|
||||
)
|
||||
in_C = VGroup(*in_B[:-11])
|
||||
out_of_C = VGroup(*in_B[-11:])
|
||||
|
||||
words = TextMobject(
|
||||
"$<$ 15 passing", "B \\\\",
|
||||
"get blocked by ", "C",
|
||||
)
|
||||
words.scale(0.8)
|
||||
words.highlight_by_tex_to_color_map({
|
||||
"B" : GREEN,
|
||||
"C" : BLUE,
|
||||
})
|
||||
words.next_to(self.out_of_B_words, DOWN, LARGE_BUFF)
|
||||
words.to_edge(LEFT)
|
||||
arrow = Arrow(words.get_right(), out_of_C)
|
||||
arrow.highlight(GREEN)
|
||||
|
||||
self.play(
|
||||
MoveToTarget(C_group),
|
||||
in_C.shift, MED_SMALL_BUFF*(DOWN+RIGHT),
|
||||
out_of_C.shift, SMALL_BUFF*(UP+LEFT),
|
||||
)
|
||||
self.play(
|
||||
Write(words, run_time = 1),
|
||||
ShowCreation(arrow)
|
||||
)
|
||||
self.dither()
|
||||
self.play(LaggedStart(
|
||||
Indicate, out_of_C,
|
||||
rate_func = there_and_back,
|
||||
color = GREEN,
|
||||
scale_factor = 2,
|
||||
))
|
||||
self.dither()
|
||||
|
||||
self.in_C = in_C
|
||||
self.out_of_C = out_of_C
|
||||
self.out_of_C_words = words
|
||||
self.out_of_C_arrow = arrow
|
||||
|
||||
def show_two_relevant_subsets(self):
|
||||
pass
|
||||
terms = VGroup(
|
||||
TexMobject("N(", "A+", ",", "B-", ")"),
|
||||
TexMobject("+ N(", "A+", ",", "B+", ",", "C-", ")"),
|
||||
TexMobject("\\ge", "N(", "A+", ",", "C-", ")"),
|
||||
)
|
||||
terms.arrange_submobjects(RIGHT)
|
||||
terms.to_edge(UP)
|
||||
for term in terms:
|
||||
term.highlight_by_tex_to_color_map({
|
||||
"A" : RED,
|
||||
"B" : GREEN,
|
||||
"C" : BLUE,
|
||||
})
|
||||
|
||||
def show_real_value(self):
|
||||
pass
|
||||
all_out_of_C = VGroup(*it.chain(
|
||||
self.out_of_B[6:],
|
||||
self.out_of_C,
|
||||
))
|
||||
|
||||
self.play(*[
|
||||
ApplyMethod(
|
||||
m.scale, 0.8,
|
||||
method_kwargs = {
|
||||
"about_point" : SPACE_HEIGHT*DOWN
|
||||
}
|
||||
)
|
||||
for m in self.get_top_level_mobjects()
|
||||
])
|
||||
self.dither()
|
||||
for term, group in zip(terms[:2], [self.out_of_B, self.out_of_C]):
|
||||
self.play(LaggedStart(
|
||||
Indicate, group,
|
||||
color = WHITE,
|
||||
scale_factor = 1.5,
|
||||
run_time = 1,
|
||||
))
|
||||
self.play(Write(term, run_time = 1))
|
||||
self.play(
|
||||
LaggedStart(
|
||||
ApplyMethod, group,
|
||||
lambda m : (m.scale_in_place, 1/1.5)
|
||||
),
|
||||
self.in_C.fade,
|
||||
)
|
||||
self.dither()
|
||||
self.play(Write(terms[2], run_time = 1))
|
||||
self.play(LaggedStart(
|
||||
Indicate, all_out_of_C,
|
||||
color = MAROON_B,
|
||||
run_time = 2,
|
||||
rate_func = smooth,
|
||||
))
|
||||
self.dither()
|
||||
|
||||
words = [self.out_of_B_words, self.out_of_C_words]
|
||||
arrows = [self.out_of_B_arrow, self.out_of_C_arrow]
|
||||
indices = [2, 3]
|
||||
for word, arrow, index, term in zip(words, arrows, indices, terms):
|
||||
num = VGroup(*word[0][:index])
|
||||
word[0].remove(*num)
|
||||
|
||||
self.play(
|
||||
FadeOut(word),
|
||||
FadeOut(arrow),
|
||||
num.scale, 2,
|
||||
num.next_to, term, DOWN
|
||||
)
|
||||
self.dither()
|
||||
|
||||
rect = SurroundingRectangle(VGroup(*terms[2][1:]))
|
||||
should_be_50 = TextMobject("Should be 50...somehow")
|
||||
should_be_50.scale(0.8)
|
||||
should_be_50.next_to(rect, DOWN, MED_SMALL_BUFF, LEFT)
|
||||
|
||||
self.play(
|
||||
ShowCreation(rect),
|
||||
Write(should_be_50, run_time = 1)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
morty = Mortimer()
|
||||
morty.to_corner(DOWN+RIGHT)
|
||||
contradiction = TextMobject("Contradiction!")
|
||||
contradiction.next_to(morty, UP, aligned_edge = RIGHT)
|
||||
contradiction.highlight(RED)
|
||||
self.play(FadeIn(morty))
|
||||
self.play(
|
||||
morty.change, "hooray",
|
||||
Write(contradiction, run_time = 1)
|
||||
)
|
||||
self.play(Blink(morty))
|
||||
self.dither()
|
||||
|
||||
def contradiction(self):
|
||||
pass
|
||||
|
||||
#######
|
||||
|
||||
|
@ -862,6 +1079,11 @@ class VennDiagramProofByContradiction(Scene):
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ FILE_DIR = os.path.join(THIS_DIR, "files")
|
|||
IMAGE_DIR = os.path.join(FILE_DIR, "images")
|
||||
GIF_DIR = os.path.join(FILE_DIR, "gifs")
|
||||
# MOVIE_DIR = os.path.join(FILE_DIR, "movies")
|
||||
MOVIE_DIR = os.path.join("/Users/grant/Dropbox/Bell's Project/", "movies")
|
||||
MOVIE_DIR = os.path.join("/Users/grant/Dropbox/Bell's Project/", "manimations")
|
||||
STAGED_SCENES_DIR = os.path.join(FILE_DIR, "staged_scenes")
|
||||
TEX_DIR = os.path.join(FILE_DIR, "Tex")
|
||||
TEX_IMAGE_DIR = os.path.join(IMAGE_DIR, "Tex")
|
||||
|
|
|
@ -184,7 +184,7 @@ class Arrow(Line):
|
|||
"tip_width_to_length_ratio" : 1,
|
||||
"max_tip_length_to_length_ratio" : 0.35,
|
||||
"max_stem_width_to_tip_width_ratio" : 0.3,
|
||||
"buff" : MED_SMALL_BUFF,
|
||||
"buff" : MED_SMALL_BUFF,
|
||||
"propogate_style_to_family" : False,
|
||||
"preserve_tip_size_when_scaling" : True,
|
||||
"normal_vector" : OUT,
|
||||
|
@ -208,7 +208,7 @@ class Arrow(Line):
|
|||
fill_opacity = 1,
|
||||
stroke_color = self.color,
|
||||
)
|
||||
self.set_tip_points(tip, add_at_end)
|
||||
self.set_tip_points(tip, add_at_end, preserve_normal = False)
|
||||
self.tip = tip
|
||||
self.add(self.tip)
|
||||
self.init_colors()
|
||||
|
@ -244,9 +244,18 @@ class Arrow(Line):
|
|||
])
|
||||
return self
|
||||
|
||||
def set_tip_points(self, tip, add_at_end = True, tip_length = None):
|
||||
def set_tip_points(
|
||||
self, tip,
|
||||
add_at_end = True,
|
||||
tip_length = None,
|
||||
preserve_normal = True,
|
||||
):
|
||||
if tip_length is None:
|
||||
tip_length = self.tip_length
|
||||
if preserve_normal:
|
||||
normal_vector = self.get_normal_vector()
|
||||
else:
|
||||
normal_vector = self.normal_vector
|
||||
line_length = np.linalg.norm(self.points[-1]-self.points[0])
|
||||
tip_length = min(
|
||||
tip_length, self.max_tip_length_to_length_ratio*line_length
|
||||
|
@ -258,7 +267,7 @@ class Arrow(Line):
|
|||
for index in indices
|
||||
]
|
||||
vect = end_point - pre_end_point
|
||||
perp_vect = np.cross(vect, self.normal_vector)
|
||||
perp_vect = np.cross(vect, normal_vector)
|
||||
for v in vect, perp_vect:
|
||||
if np.linalg.norm(v) == 0:
|
||||
v[0] = 1
|
||||
|
@ -270,10 +279,22 @@ class Arrow(Line):
|
|||
end_point-vect+perp_vect*ratio/2,
|
||||
end_point-vect-perp_vect*ratio/2,
|
||||
])
|
||||
# tip.scale(tip_length, about_point = end_point)
|
||||
|
||||
return self
|
||||
|
||||
def get_normal_vector(self):
|
||||
p1, p2, p3 = self.tip.get_anchors()
|
||||
result = np.cross(p2 - p1, p3 - p2)
|
||||
norm = np.linalg.norm(result)
|
||||
if norm == 0:
|
||||
return self.normal_vector
|
||||
else:
|
||||
return result/norm
|
||||
|
||||
def reset_normal_vector(self):
|
||||
self.normal_vector = self.get_normal_vector()
|
||||
return self
|
||||
|
||||
def get_end(self):
|
||||
if hasattr(self, "tip"):
|
||||
return self.tip.get_anchors()[0]
|
||||
|
@ -290,9 +311,9 @@ class Arrow(Line):
|
|||
|
||||
def scale(self, scale_factor, **kwargs):
|
||||
Line.scale(self, scale_factor, **kwargs)
|
||||
self.set_rectangular_stem_points()
|
||||
if self.preserve_tip_size_when_scaling:
|
||||
self.set_tip_points(self.tip)
|
||||
self.set_rectangular_stem_points()
|
||||
return self
|
||||
|
||||
class Vector(Arrow):
|
||||
|
|
|
@ -161,11 +161,11 @@ class Axes(VGroup):
|
|||
self.add(self.x_axis, self.y_axis)
|
||||
if self.three_d:
|
||||
self.z_axis = NumberLine(
|
||||
x_min = -self.y_axis_radius,
|
||||
x_max = self.y_axis_radius,
|
||||
x_min = -self.z_axis_radius,
|
||||
x_max = self.z_axis_radius,
|
||||
**self.number_line_config
|
||||
)
|
||||
self.z_axis.rotate(np.pi/2, UP)
|
||||
self.z_axis.rotate(-np.pi/2, UP)
|
||||
self.add(self.z_axis)
|
||||
|
||||
class ThreeDAxes(Axes):
|
||||
|
|
98
waves.py
98
waves.py
|
@ -35,10 +35,8 @@ class OscillatingVector(ContinualAnimation):
|
|||
CONFIG = {
|
||||
"tail" : ORIGIN,
|
||||
"frequency" : 1,
|
||||
"A_x" : 1,
|
||||
"A_y" : 0,
|
||||
"phi_x" : 0,
|
||||
"phi_y" : 0,
|
||||
"A_vect" : [1, 0, 0],
|
||||
"phi_vect" : [0, 0, 0],
|
||||
"vector_to_be_added_to" : None,
|
||||
}
|
||||
def setup(self):
|
||||
|
@ -49,9 +47,8 @@ class OscillatingVector(ContinualAnimation):
|
|||
t = self.internal_time
|
||||
angle = 2*np.pi*f*t
|
||||
vect = np.array([
|
||||
self.A_x*np.exp(complex(0, angle + self.phi_x)),
|
||||
self.A_y*np.exp(complex(0, angle + self.phi_y)),
|
||||
0,
|
||||
A*np.exp(complex(0, angle + phi))
|
||||
for A, phi in zip(self.A_vect, self.phi_vect)
|
||||
]).real
|
||||
self.update_tail()
|
||||
self.vector.put_start_and_end_on(self.tail, self.tail+vect)
|
||||
|
@ -115,55 +112,55 @@ class EMWave(ContinualAnimationGroup):
|
|||
"length" : 2*SPACE_WIDTH,
|
||||
"amplitude" : 1,
|
||||
"rotation" : 0,
|
||||
"A_x" : 1,
|
||||
"A_y" : 0,
|
||||
"phi_x" : 0,
|
||||
"phi_y" : 0,
|
||||
"A_vect" : [0, 0, 1],
|
||||
"phi_vect" : [0, 0, 0],
|
||||
}
|
||||
def __init__(self, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
self.matrix_transform = z_to_vector(self.propogation_direction)
|
||||
self.matrix_transform = np.dot(
|
||||
z_to_vector(self.propogation_direction),
|
||||
np.linalg.inv(z_to_vector(RIGHT)),
|
||||
)
|
||||
|
||||
vector_oscillations = []
|
||||
self.E_vects = VGroup()
|
||||
self.M_vects = VGroup()
|
||||
|
||||
A_multiplier = float(self.amplitude) / (self.A_x**2 + self.A_y**2)
|
||||
self.A_x *= A_multiplier
|
||||
self.A_y *= A_multiplier
|
||||
self.A_vect = np.array(self.A_vect)/np.linalg.norm(self.A_vect)
|
||||
self.A_vect *= self.amplitude
|
||||
|
||||
for alpha in np.linspace(0, 1, self.n_vectors):
|
||||
tail = interpolate(ORIGIN, self.length*OUT, alpha)
|
||||
tail = interpolate(ORIGIN, self.length*RIGHT, alpha)
|
||||
phase = -alpha*self.length*self.wave_number
|
||||
kwargs = {
|
||||
"phi_vect" : np.array(self.phi_vect) + phase,
|
||||
"frequency" : self.frequency,
|
||||
"tail" : np.array(tail),
|
||||
}
|
||||
E_ov = OscillatingVector(
|
||||
Vector(UP, color = E_COLOR),
|
||||
tail = np.array(tail),
|
||||
A_x = self.A_x,
|
||||
A_y = self.A_y,
|
||||
phi_x = self.phi_x + phase,
|
||||
phi_y = self.phi_y + phase,
|
||||
frequency = self.frequency
|
||||
Vector(
|
||||
OUT, color = E_COLOR,
|
||||
normal_vector = UP,
|
||||
),
|
||||
A_vect = self.A_vect,
|
||||
**kwargs
|
||||
)
|
||||
M_ov = OscillatingVector(
|
||||
Vector(UP, color = M_COLOR),
|
||||
tail = np.array(tail),
|
||||
A_x = -self.A_y,
|
||||
A_y = self.A_x,
|
||||
phi_x = self.phi_y + phase,
|
||||
phi_y = self.phi_x + phase,
|
||||
frequency = self.frequency
|
||||
Vector(
|
||||
UP, color = M_COLOR,
|
||||
normal_vector = OUT,
|
||||
),
|
||||
A_vect = rotate_vector(self.A_vect, np.pi/2, RIGHT),
|
||||
**kwargs
|
||||
)
|
||||
vector_oscillations += [E_ov, M_ov]
|
||||
E_ov.vector.normal_vector = UP
|
||||
M_ov.vector.normal_vector = RIGHT
|
||||
self.E_vects.add(E_ov.vector)
|
||||
self.M_vects.add(M_ov.vector)
|
||||
ContinualAnimationGroup.__init__(self, *vector_oscillations)
|
||||
# make_3d(self.mobject)
|
||||
|
||||
def update_mobject(self, dt):
|
||||
ContinualAnimationGroup.update_mobject(self, dt)
|
||||
self.mobject.rotate(self.rotation, OUT)
|
||||
self.mobject.rotate(self.rotation, RIGHT)
|
||||
self.mobject.apply_matrix(self.matrix_transform)
|
||||
self.mobject.shift(self.start_point)
|
||||
|
||||
|
@ -172,8 +169,7 @@ class WavePacket(Animation):
|
|||
"EMWave_config" : {
|
||||
"wave_number" : 0,
|
||||
"start_point" : SPACE_WIDTH*LEFT,
|
||||
"phi_x" : np.pi/4,
|
||||
"phi_y" : np.pi/4,
|
||||
"phi_vect" : np.ones(3)*np.pi/4,
|
||||
},
|
||||
"em_wave" : None,
|
||||
"run_time" : 4,
|
||||
|
@ -229,7 +225,7 @@ class WavePacket(Animation):
|
|||
vect.scale(A/vect.get_length(), about_point = tail)
|
||||
|
||||
def E_func(self, x):
|
||||
return np.sin(2*x)*np.exp(-0.25*x*x)
|
||||
return np.sin(x)*np.exp(-0.25*x*x)
|
||||
|
||||
class FilterLabel(TexMobject):
|
||||
def __init__(self, tex, degrees, **kwargs):
|
||||
|
@ -277,12 +273,16 @@ class EMScene(Scene):
|
|||
def construct(self):
|
||||
pass
|
||||
|
||||
class TestPhoton(ThreeDScene):
|
||||
class Test(ThreeDScene):
|
||||
def construct(self):
|
||||
self.add(ThreeDAxes())
|
||||
|
||||
self.set_camera_position(0.8*np.pi/2, -0.6*np.pi)
|
||||
self.begin_ambient_camera_rotation(rate = 0.01)
|
||||
self.add(EMWave(A_vect = [0, 1, 1]))
|
||||
self.dither(2)
|
||||
self.move_camera(theta = -1.1*np.pi)
|
||||
self.dither(2)
|
||||
|
||||
# pol_filter = PolarizingFilter(
|
||||
# label_tex = "C",
|
||||
|
@ -295,15 +295,19 @@ class TestPhoton(ThreeDScene):
|
|||
# shade_in_3d(pol_filter)
|
||||
# self.add(pol_filter)
|
||||
|
||||
self.move_camera(theta = -1.2*np.pi/2)
|
||||
self.play(WavePacket(
|
||||
run_time = 2,
|
||||
# get_filtered = True,
|
||||
EMWave_config = {
|
||||
"start_point" : SPACE_WIDTH*LEFT + DOWN+OUT
|
||||
}
|
||||
))
|
||||
self.dither()
|
||||
# photon = WavePacket(
|
||||
# run_time = 2,
|
||||
# # get_filtered = True,
|
||||
# EMWave_config = {
|
||||
# "start_point" : SPACE_WIDTH*LEFT + DOWN+OUT,
|
||||
# "A_vect" : [0, 1, 0],
|
||||
# },
|
||||
# )
|
||||
# photon.update(0.5)
|
||||
# photon.mobject.show(self.camera)
|
||||
|
||||
# self.move_camera(theta = -1.2*np.pi/2)
|
||||
# self.play(photon)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue