from manim import *
frame_width = config["frame_width"]
frame_height = config["frame_height"]
def narrator(a):
for i in a:
globals()[f't{str(i)}']=Text(a[i], font = "STZhongsong").to_edge(DOWN).scale(0.6)
class OneDimensionalBox(VGroup):
def __init__(self, n: int = None, **kwargs):
super().__init__(**kwargs)
left_infinite_rec = Rectangle(width=frame_width/6+1, height=frame_height+1, fill_opacity=0.5, fill_color=RED, stroke_opacity=0.0)
right_infinite_rec = Rectangle(width=frame_width/6+1, height=frame_height+1, fill_opacity=0.5, fill_color=RED, stroke_opacity=0.0)
finite_rec = Rectangle(width=frame_width*2/3, height=frame_height+1, fill_opacity=0.5, fill_color=BLUE, stroke_opacity=0.0)
finite_line = Line(frame_width * LEFT / 3, frame_width * RIGHT / 3).set_color(BLUE)
VGroup(left_infinite_rec, finite_line, right_infinite_rec).arrange(buff=0)
self.n = n
self.infinite_rec = VGroup(left_infinite_rec, right_infinite_rec).set_z_index(-1)
self.finite_rec = finite_rec.set_z_index(-1)
self.finite_line = finite_line
self.func = self.mob_wave_func_graph()
self.dots = self.mob_wave_func_to_dots()
self.dots2 = self.mob_dots_equally_distribute()
self.dot = self.mob_origin_dot()
self.tex = self.mob_explain_n_tex()
self.bounce = self.anim_bounce_to_wall()
self.show_dots = self.anim_show_dots()
def tool_change_n(self, n):
self.n = n
self.func = self.mob_wave_func_graph()
self.dots = self.mob_wave_func_to_dots()
self.dots2 = self.mob_dots_equally_distribute()
self.dot = self.mob_origin_dot()
self.tex = self.mob_explain_n_tex()
def tool_wave_func(self):
n = self.n
scale = 10
box_length = self.finite_line.width
func = lambda x : scale * 2/box_length*np.sin(n*PI*(x + box_length/2)/box_length)**2
return func
def mob_wave_func_graph(self):
box_length = self.finite_line.width
func_graph = FunctionGraph(self.tool_wave_func(), x_range=[-box_length/2, box_length/2], color=BLUE)
tagging = Text('概率分布如曲线所示', font = "STZhongsong").to_edge(DOWN).scale(0.6)
annotation = Text(f'n = {str(self.n)}').scale(0.8).shift(2*DOWN)
return VGroup(func_graph, tagging, annotation)
def mob_wave_func_to_dots(self, segments_num=50):
box_length = self.finite_line.width
dots = VGroup()
dx = box_length/segments_num
for i in range(segments_num):
x = -box_length/2 + dx*i
for j in range(int(4*self.tool_wave_func()(x))+1):
dots.add(Dot(radius=0.04, fill_opacity=0.6, color=BLUE).move_to([x,0,0]).shift((np.random.rand() - 0.5)*2*0.06 * RIGHT))
dots.save_state()
dots.shuffle_submobjects()
return dots
def mob_dots_equally_distribute(self, segments_num=50):
box_length = self.finite_line.width
dots = VGroup()
dx = box_length/segments_num
for i in range(segments_num):
x = -box_length/2 + dx*i
for j in range(10):
dots.add(Dot(radius=0.04, fill_opacity=0.6, color=BLUE).move_to([x,0,0]).shift((np.random.rand() - 0.5)*2*0.06 * RIGHT))
dots.shuffle_submobjects()
return dots
def mob_origin_dot(self):
dot = Dot(radius=0.08, fill_opacity=0.8, color=BLUE)
return dot
def mob_explain_n_tex(self):
tex1 = MathTex(r'\sin \left ( \frac{2\pi l}{h} \sqrt{2mE} \right ) = 0')
tex2 = MathTex(r'\Downarrow')
tex3 = MathTex(r'\frac{2\pi l}{h} \sqrt{2mE} = \pm {{n}} \pi')
tex3.set_color_by_tex('n', BLUE)
tex4 = MathTex(r'E = {{{n}}^{2} h^{2} \over 8ml^{2}}')
tex4.set_color_by_tex('n', BLUE)
tex_vg1 = VGroup(tex1, tex2, tex3).arrange(direction=DOWN)
tex_vg2 = VGroup(tex_vg1, tex4).arrange(buff=2)
return tex_vg2
def anim_bounce_to_wall(self):
dot = self.dot
box_length = self.finite_line.width
anim1 = ApplyMethod(dot.shift, box_length/2*LEFT, rate_func=rate_functions.rush_into, run_time=2)
anim2 = ApplyMethod(dot.shift, box_length/2*RIGHT, rate_func=rate_functions.rush_from, run_time=2)
return Succession(anim1, anim2)
def anim_show_dots(self):
dot = self.dot
dots = self.dots
dots.shuffle_submobjects()
ag = [FadeOut(dot, run_time=1)]
for i in dots:
ag.append(FadeIn(i, run_time=0.1))
return Succession(*ag)
class z1(Scene):
narrator({1:'首先我们来认识一下微观粒子的特征', 2:'我们将一个电子放进一个一维势箱中', 3:'这个势箱内部的势能为 0, 外部的势能为无穷大', 4:'这意味着电子无法逃离势箱内部,因为它没有足够的能量克服外部的势能',
5:'接下来我们将观察电子在一维势箱中的分布', 6:'n 产生于解方程的过程中,其决定了电子的能量', 7:'如果用经典力学预测,电子出现在每一处的概率都应该相等', 8:'电子的波动性质使得它在不同的地方出现的概率不同'})
def play_with_narrator(self, text, *anims, start=False, end=False):
def text_duration(text, *anims):
time = len(text)/10
if anims != ():
time += 1 # 基础时间为 1s
anim_run_time_list = []
for anim in anims:
anim_run_time_list.append(anim.get_run_time())
anim_run_time = max(anim_run_time_list)
if anim_run_time >= time:
time = 1
else:
time -= anim_run_time
return time
if start:
self.play(FadeIn(text), *anims)
self.wait(text_duration(text, *anims))
self.current_narrator = text
elif end:
origin_text = self.current_narrator
self.play(Transform(origin_text, text), *anims)
self.wait(text_duration(text, *anims))
self.play(FadeOut(origin_text))
self.current_narrator = None
elif not start and not end:
origin_text = self.current_narrator
self.play(Transform(origin_text, text), *anims)
self.wait(text_duration(text, *anims))
def construct(self):
box = OneDimensionalBox(n = 1)
self.play_with_narrator(t1, start=True)
self.play_with_narrator(t2, FadeIn(box.finite_line, box.dot))
self.play_with_narrator(t3, FadeIn(box.finite_rec))
self.play(FadeIn(box.infinite_rec), FadeOut(box.finite_line))
self.play_with_narrator(t4, box.bounce)
self.play_with_narrator(t5, FadeOut(box.infinite_rec, box.finite_rec), end=True)
self.play(box.show_dots)
self.play(FadeIn(box.func));self.wait(2)
self.play(FadeOut(box.dots, box.func))
self.play(FadeIn(t6), Write(box.tex), run_time=3);self.wait(3)
self.play(FadeOut(t6, box.tex))
box.tool_change_n(2)
self.play(Write(box.dots), run_time=3)
self.play(FadeIn(box.func));self.wait(2)
self.play(FadeOut(box.dots, box.func))
box.tool_change_n(3)
self.play(Write(box.dots), run_time=3)
self.play(FadeIn(box.func));self.wait(2)
self.play(FadeOut(box.dots, box.func))
box.tool_change_n(4)
self.play(Write(box.dots), run_time=3)
self.play(FadeIn(box.func));self.wait(2)
self.play(FadeOut(box.func))
self.play_with_narrator(t7, Transform(box.dots, box.dots2), start=True)
self.play_with_narrator(t8, Restore(box.dots), end=True)
self.play(FadeOut(box.dots))