def scroll_through_patrons(self): logo_box = Square(side_length=2.5) logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF) total_width = FRAME_X_RADIUS - logo_box.get_right()[0] black_rect = Rectangle( fill_color=BLACK, fill_opacity=1, stroke_width=0, width=FRAME_WIDTH, height=0.6 * FRAME_HEIGHT, ) black_rect.to_edge(UP, buff=0) line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT) line.move_to(ORIGIN) self.add(line) thanks = TextMobject("Funded by the community, with special thanks to:") thanks.scale(0.9) thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF) thanks.set_color(YELLOW) underline = Line(LEFT, RIGHT) underline.scale_to_fit_width(thanks.get_width() + MED_SMALL_BUFF) underline.next_to(thanks, DOWN, SMALL_BUFF) thanks.add(underline) self.add(thanks) patrons = VGroup(*map(TextMobject, self.specific_patrons)) patrons.scale(self.patron_scale_val) for patron in patrons: if patron.get_width() > self.max_patron_width: patron.scale_to_fit_width(self.max_patron_width) columns = VGroup(*[ VGroup(*patrons[i::self.n_patron_columns]) for i in range(self.n_patron_columns) ]) for column in columns: for n, name in enumerate(column): name.shift(n * self.name_y_spacing * DOWN) columns.arrange_submobjects( RIGHT, buff=LARGE_BUFF, aligned_edge=UP, ) columns.scale_to_fit_width(total_width - 1) columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF) columns.to_edge(RIGHT) thanks.align_to(columns, alignment_vect=RIGHT) self.play( columns.move_to, 2 * DOWN, DOWN, columns.to_edge, RIGHT, Animation(black_rect), Animation(line), Animation(thanks), rate_func=None, run_time=self.run_time, )
def add_words(self): # Wallis product product = TexMobject(*(["\\text{Wallis公式:}"] + [ "{%d \\over %d} \\," % (wallis_numer(n), wallis_denom(n)) for n in range(1, 8) ] + ["\\cdots = {\\pi \\over 2}"])).set_color(YELLOW) rect = SurroundingRectangle(product, color=YELLOW, buff=0.25) wallis_product = VGroup(product, rect) wallis_product.set_width(6) # All those steps nums = [TextMobject("%d. " % k) for k in [1, 2, 3, 4]] words = [ TextMobject(word) for word in [ "构造合适的矩形边长", "同种颜色的矩形的面积之和恒为1", "整个图形又像一个${1 \\over 4}$圆,半径是", "比较${1 \\over 4}$圆与矩形的面积", ] ] formulae = [ TextMobject(formula) for formula in [ "$a_0 = 1,\\, a_n = {1 \\over 2} \cdot {3 \\over 4} \cdots {2n-1 \\over 2n} (n \geq 1)$", "$a_0 a_n + a_1 a_{n-1} + \\cdots + a_n a_0 = 1$", "$\\begin{aligned} \ r_n & = a_0 + a_1 + \\cdots + a_{n-1} \\\\ \ & = \\textstyle{3 \\over 2} \cdot {5 \\over 4} \cdots {2n-1 \\over 2n-2} \ \\quad (n \geq 2) \ \\end{aligned}$", "${1 \\over 4} \\pi {r_n}^2 \\approx n \\quad \\Rightarrow \\quad \\text{Wallis公式}$" ] ] steps = VGroup() for num, word, formula in zip(nums, words, formulae): num.next_to(word, LEFT) formula.next_to(word, DOWN, aligned_edge=LEFT) steps.add(VGroup(num, word, formula)) steps.arrange_submobjects(DOWN, buff=0.6, aligned_edge=LEFT) steps.set_width(6) steps.next_to(wallis_product, DOWN) VGroup(wallis_product, steps).center().to_edge(RIGHT, buff=0.15) # Sep line and QED sep_line = DashedLine(2 * TOP, 2 * BOTTOM, color=GREY, buff=0.5) sep_line.next_to(steps, LEFT) qed = QEDSymbol(height=0.570 / 2) qed.next_to(steps[-1][-1][-1], RIGHT, aligned_edge=DOWN) # Add everything self.add(wallis_product, steps, sep_line, qed)
def scroll_through_patrons(self): logo_box = Square(side_length=2.5) logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF) total_width = FRAME_X_RADIUS - logo_box.get_right()[0] black_rect = Rectangle(fill_color=BLACK, fill_opacity=1, stroke_width=0, width=FRAME_WIDTH, height=1.1 * FRAME_Y_RADIUS) black_rect.to_edge(UP, buff=0) line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT) line.move_to(black_rect, DOWN) line.shift(SMALL_BUFF * SMALL_BUFF * DOWN) self.add(line) patrons = VGroup(*map(TextMobject, self.specific_patrons)) patrons.scale(self.patron_scale_val) for patron in patrons: if patron.get_width() > self.max_patron_width: patron.scale_to_fit_width(self.max_patron_width) columns = VGroup(*[ VGroup(*patrons[i::self.n_patron_columns]) for i in range(self.n_patron_columns) ]) for column in columns: for n, name in enumerate(column): name.shift(n * self.name_y_spacing * DOWN) columns.arrange_submobjects( RIGHT, buff=LARGE_BUFF, aligned_edge=UP, ) columns.scale_to_fit_width(total_width - 1) columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF) columns.to_edge(RIGHT) self.play( columns.move_to, 2 * DOWN, DOWN, columns.to_edge, RIGHT, Animation(black_rect), rate_func=None, run_time=self.run_time, )
def construct(self): # Setup axes_group = self.axes_group pos_axis, time_axis = axes_group[:2] title_pq = self.title_pq walk_q = self.walk_q parts_q = self.parts_q l_arrow = self.l_arrow self.add(axes_group, title_pq, walk_q, l_arrow) walk_q_copy = walk_q.copy() # Q_4 -> P_4 steps_qp = VGroup(*[ TextMobject(text) for text in [ "1. 找到路径终点的位置坐标$h$", "2. 找到最晚一次穿过$\\frac{h}{2}$的时刻", "3. 在这个时刻上进行分割", "4. 将第一段水平翻转", "5. 拼接两个片段" ] ]) for step in steps_qp: step.set_color(YELLOW) step.add_background_rectangle() step1_qp, step2_qp, step3_qp, step4_qp, step5_qp = steps_qp # 1. Find the endpoint step1_qp.next_to(time_axis.number_to_point(4.5), UP) end_horiz_line = DashedLine(LEFT_SIDE, RIGHT_SIDE, color=YELLOW) end_horiz_line.move_to(pos_axis.number_to_point(-4)) end_horiz_line.horizontally_center() end_brace_line = DashedLine(time_axis.number_to_point(8), walk_q.get_end_point()) end_brace = Brace(end_brace_line, direction=RIGHT, color=YELLOW) h = TexMobject("h").set_color(YELLOW) end_brace.put_at_tip(h) self.play(Write(step1_qp), ShowCreation(end_horiz_line), run_time=1) self.play(GrowFromCenter(end_brace), GrowFromCenter(h)) self.wait(1.5) self.play(FadeOut(step1_qp)) # 2. Find the last time it GOES THROUGH half its final value half_point = walk_q.get_arrow_end_point(3) step2_qp.next_to(time_axis.number_to_point(4.5), UP) half_horiz_line = end_horiz_line.copy().shift(2 * UP) half_brace_line = DashedLine(time_axis.number_to_point(4), half_point) half_brace = Brace(half_brace_line, direction=RIGHT, color=YELLOW) half_h = TexMobject("\\frac{h}{2}").set_color(YELLOW) half_brace.put_at_tip(half_h) half_dot = Dot(half_point, color=YELLOW) self.play(FadeIn(step2_qp), run_time=1) self.wait(0.5) self.play( ReplacementTransform(end_brace, half_brace), ReplacementTransform(end_horiz_line, half_horiz_line), ReplacementTransform(h, half_h[0]), Write(half_h[1:]), ) self.play(DrawBorderThenFill(half_dot)) self.wait(1.5) self.play( FadeOut(VGroup(step2_qp, half_horiz_line, half_brace, half_h))) # 3. Split vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW) vert_line.move_to(half_point) step3_qp.next_to(vert_line, UP) left_part_q, right_part_q = parts_q self.play(ShowCreation(vert_line), Write(step3_qp), run_time=1) self.play( FadeOut(half_dot), left_part_q.shift, 0.5 * DOWN + 0.5 * LEFT, right_part_q.shift, 0.5 * UP + 0.5 * RIGHT, ) self.wait(1.5) self.play(FadeOut(vert_line), FadeOut(step3_qp)) # 4. Flip the first segment horizontally flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY) flip_axis.move_to(left_part_q) step4_qp.next_to(flip_axis, DOWN) self.play( ShowCreation(flip_axis), Write(step4_qp), run_time=1, ) self.play( left_part_q.flip, Animation(flip_axis), ) self.wait(1.5) self.play(FadeOut(step4_qp), FadeOut(flip_axis)) # 5. Put the pieces together step5_qp.shift(2.5 * DOWN) flip_arrow_anims = walk_q.get_flip_arrows_animation(3, color=ORANGE) self.play(Write(step5_qp), run_time=1) self.wait(0.5) self.play(flip_arrow_anims, right_part_q.set_color, ORANGE) self.wait(0.5) self.play( left_part_q.shift, 2.5 * UP + 0.5 * RIGHT, right_part_q.shift, 3.5 * UP + 0.5 * LEFT, Animation(step5_qp), ) self.wait(0.5) self.play(FadeOut(step5_qp)) self.wait(1.5) # Now Reset self.play(FadeOut(walk_q)) self.play(FadeIn(walk_q_copy)) self.wait()
def construct(self): # Setup axes_group = self.axes_group title_pq = self.title_pq walk_p = self.walk_p parts_p = self.parts_p r_arrow = self.r_arrow self.add(axes_group, title_pq, walk_p, r_arrow) walk_p_copy = walk_p.copy() # P_4 -> Q_4 steps_pq = VGroup(*[ TextMobject(text) for text in [ "1. 第一步是沿着正方向走的", "2. 找到第一次到达最大值的时刻", "3. 在这个时刻上进行分割", "4. 将第一段水平翻转", "5. 拼接两个片段" ] ]) for step in steps_pq: step.set_color(YELLOW) step.add_background_rectangle() step1_pq, step2_pq, step3_pq, step4_pq, step5_pq = steps_pq # 1. Check the first step of the walk step1_circle = Circle(color=YELLOW) first_arrow = walk_p.get_arrow_by_number(0) step1_circle.surround(first_arrow) step1_pq.next_to(step1_circle, RIGHT + DOWN) self.play(ShowCreation(step1_circle), Write(step1_pq), run_time=1) self.wait(1.5) self.play(FadeOut(step1_circle), FadeOut(step1_pq)) # 2. Find the first time it reaches the maximum peak = walk_p.get_arrow_end_point(3) horiz_line = DashedLine(2.5 * LEFT, 2.5 * RIGHT, color=YELLOW) horiz_line.move_to(peak) dot = Dot(color=YELLOW) dot.move_to(peak) step2_pq.next_to(horiz_line, UP) self.play(ShowCreation(horiz_line), DrawBorderThenFill(dot), Write(step2_pq), run_time=1) self.wait(1.5) self.play(FadeOut(horiz_line), FadeOut(step2_pq)) # 3. Split vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW) vert_line.move_to(peak) step3_pq.next_to(vert_line, DOWN) left_part_p, right_part_p = parts_p self.play(ShowCreation(vert_line), Write(step3_pq), run_time=1) self.play( FadeOut(dot), left_part_p.shift, 0.5 * DOWN + 0.5 * LEFT, right_part_p.shift, DOWN + 0.5 * RIGHT, ) self.wait(1.5) self.play(FadeOut(vert_line), FadeOut(step3_pq)) # 4. Flip the first segment horizontally flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY) flip_axis.move_to(left_part_p) step4_pq.next_to(flip_axis, DOWN) self.play( ShowCreation(flip_axis), Write(step4_pq), run_time=1, ) self.play( left_part_p.flip, Animation(flip_axis), ) self.wait(1.5) self.play(FadeOut(step4_pq), FadeOut(flip_axis)) # 5. Put the pieces together step5_pq.move_to(dot) flip_arrow_anims = walk_p.get_flip_arrows_animation(3, color=GREEN) self.play(Write(step5_pq), run_time=1) self.wait(0.5) self.play(flip_arrow_anims, right_part_p.set_color, GREEN) self.wait(0.5) self.play( left_part_p.shift, 1.5 * DOWN + 0.5 * RIGHT, right_part_p.shift, 3 * DOWN + 0.5 * LEFT, Animation(step5_pq), ) self.wait(0.5) self.play(FadeOut(step5_pq)) self.wait(1.5) # Now Reset self.play(FadeOut(walk_p)) self.play(FadeIn(walk_p_copy)) self.wait()
def construct(self): # Setup pos_axis = NumberLine(x_min=-3.5, x_max=3.5, color=WHITE) pos_axis.rotate(np.pi / 2) pos_axis.add_tip() time_axis = NumberLine(x_min=0, x_max=9.5, color=WHITE) time_axis.add_tip() pos_text = TextMobject("位置") pos_text.next_to(pos_axis.number_to_point(3.5), LEFT) time_text = TextMobject("时间") time_text.next_to(time_axis.number_to_point(9.5), DOWN) group = VGroup(pos_axis, time_axis, pos_text, time_text) group.to_edge(LEFT, buff=2) self.add(group) # Some preparations sequences = [ "UDDDUDUD", "DUUDDDUD", "DDUUUDUD", "UUUDDUDU", "UDDDUDUD" ] nums = [1, 3, 7, -1, 1] walks = [ RandomWalk1DArrow(sequence).move_start_to( pos_axis.number_to_point(0)) for sequence in sequences ] parts = [walk.split_at(num) for walk, num in zip(walks, nums)] split_lines = [ DashedLine(TOP, BOTTOM, color = GREY) \ .move_to(time_axis.number_to_point(num+1)) for num in nums ] zero_words = [ TextMobject("“正点到家” \\\\ $P_%s$" % str((num+1)//2)) \ .next_to(line, LEFT).shift(2.8 * DOWN).set_color(ORANGE) for num, line in zip(nums, split_lines) ] nocross_words = [ TextMobject("“不经过家门” \\\\ $Q_%s$" % str(4-(num+1)//2)) \ .next_to(line, RIGHT).shift(2.8 * DOWN).set_color(GREEN) for num, line in zip(nums, split_lines) ] for words, direction in zip([zero_words, nocross_words], [RIGHT, LEFT]): for word in words: text, symbol = VGroup(word[:-2]), VGroup(word[-2:]) symbol.scale(1.5) symbol.next_to(text, DOWN, aligned_edge=direction) word.add_background_rectangle() # Demonstrate how to split self.add(walks[0], split_lines[0], zero_words[0], nocross_words[0]) l = len(walks) for k in range(l - 1): cur_walk = walks[k] cur_line = split_lines[k] cur_zero_word = zero_words[k] cur_nocross_word = nocross_words[k] next_walk = walks[k + 1] next_line = split_lines[k + 1] next_zero_word = zero_words[k + 1] next_nocross_word = nocross_words[k + 1] part1, part2 = parts[k] cur_walk.save_state() self.play( part1.set_color, ORANGE, part2.set_color, GREEN, ) self.wait() self.play(cur_walk.restore) self.wait() self.play( ReplacementTransform(cur_walk, next_walk), ReplacementTransform(cur_line, next_line), ReplacementTransform(cur_zero_word, next_zero_word), ReplacementTransform(cur_nocross_word, next_nocross_word), ) self.wait()