def vector_to_coords(self, vector, integer_labels=True, clean_up=True): starting_mobjects = list(self.mobjects) show_creation = False if isinstance(vector, Arrow): arrow = vector vector = arrow.get_end()[:2] else: arrow = Vector(vector) show_creation = True array = vector_coordinate_label(arrow, integer_labels=integer_labels) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() x_coord_start = self.position_x_coordinate( x_coord.copy(), x_line, vector ) y_coord_start = self.position_y_coordinate( y_coord.copy(), y_line, vector ) brackets = array.get_brackets() if show_creation: self.play(ShowCreation(arrow)) self.play( ShowCreation(x_line), Write(x_coord_start), run_time=1 ) self.play( ShowCreation(y_line), Write(y_coord_start), run_time=1 ) self.wait() self.play( Transform(x_coord_start, x_coord, submobject_mode="all_at_once"), Transform(y_coord_start, y_coord, submobject_mode="all_at_once"), Write(brackets, run_time=1), ) self.wait() self.remove(x_coord_start, y_coord_start, brackets) self.add(array) if clean_up: self.clear() self.add(*starting_mobjects) return array, x_line, y_line
def tex(self, latex): eq = TextMobject(latex) anims = [] anims.append(Write(eq)) for mobject in self.mobjects: anims.append(ApplyMethod(mobject.shift, 2 * UP)) self.play(*anims)
def coords_to_vector(self, vector, coords_start=2 * RIGHT + 2 * UP, clean_up=True): starting_mobjects = list(self.mobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() self.play(Write(array, run_time=1)) self.wait() self.play( ApplyFunction( lambda x: self.position_x_coordinate(x, x_line, vector), x_coord)) self.play(ShowCreation(x_line)) self.play( ApplyFunction( lambda y: self.position_y_coordinate(y, y_line, vector), y_coord), FadeOut(array.get_brackets())) y_coord, brackets = self.get_mobjects_from_last_animation() self.play(ShowCreation(y_line)) self.play(ShowCreation(arrow)) self.wait() if clean_up: self.clear() self.add(*starting_mobjects)
def construct(self): # Generate transformation animations of the twin dragon curve anims = list() fractal = VMobject() fractal.shift(UP) for order in range(-1, self.max_order + 1): new_fractal = TwinDragon(order=order) new_fractal.shift(UP) run_time = 0.5 if order >= 0 else 0 anims.append( Transform( fractal, new_fractal, submobject_mode="all_at_once", run_time=run_time, )) fractal = new_fractal # Add the channel name text = TextMobject("Solara570") text.scale(2).to_edge(DOWN, buff=1.2) # Now sit back and watch self.play( Succession(*anims, rate_func=smooth), Write(text, lag_factor=2.5), run_time=4.5, )
def add_T_label(self, x_val, side=RIGHT, label=None, color=WHITE, animated=False, **kwargs): triangle = RegularPolygon(n=3, start_angle=np.pi / 2) triangle.scale_to_fit_height(MED_SMALL_BUFF) triangle.move_to(self.coords_to_point(x_val, 0), UP) triangle.set_fill(color, 1) triangle.set_stroke(width=0) if label == None: T_label = TexMobject(self.variable_point_label, fill_color=color) else: T_label = TexMobject(label, fill_color=color) T_label.next_to(triangle, DOWN) v_line = self.get_vertical_line_to_graph(x_val, self.v_graph, color=YELLOW) if animated: self.play(DrawBorderThenFill(triangle), ShowCreation(v_line), Write(T_label, run_time=1), **kwargs) if np.all(side == LEFT): self.left_T_label_group = VGroup(T_label, triangle) self.left_v_line = v_line self.add(self.left_T_label_group, self.left_v_line) elif np.all(side == RIGHT): self.right_T_label_group = VGroup(T_label, triangle) self.right_v_line = v_line self.add(self.right_T_label_group, self.right_v_line)
def construct(self): logo = self.logo name = self.channel_name self.play(Write(name, run_time=3, lag_factor=2.5), *self.get_logo_animations(logo)) self.wait()
def construct(self): self.quote = self.get_quote() self.author = self.get_author(self.quote) self.play(FadeIn(self.quote, **self.fade_in_kwargs)) self.wait(2) self.play(Write(self.author, run_time=3)) self.wait()
def solve_the_equations(self): rects = VGroup(*[ CoverRectangle( equation[0].get_exponent(), stroke_color = color, text = str(num), text_color = color ) for equation, color, num in zip(self.equations, self.colors, self.nums) ]) self.play(DrawBorderThenFill(rects)) self.wait() sps = VGroup() for equation, num, color in zip(self.equations, self.nums, self.colors): sp = TexMobject("x", "^{%d}" % num, "=", "%d" % num) sp[1::2].set_color(color) sp.scale(2) sp.next_to(equation, DOWN, buff = 1) sps.add(sp) rss = VGroup() for num, sp, color in zip(self.nums, sps, self.colors): rs = TexMobject("x", "=", "%d" % num , "^{{1}\\over{%d}}" % num, "=\\sqrt{2}") for tex in (rs[2], rs[3][2]): tex.set_color(color) rs.match_height(sp).move_to(sp) rss.add(rs) tf_anims = [] for sp, rs in zip(sps, rss): tf_anims.append(ReplacementTransform(sp[0], rs[0])) tf_anims.append(ReplacementTransform(sp[1], rs[3][2], path_arc = -TAU/4)) tf_anims.append(ReplacementTransform(sp[2], rs[1])) tf_anims.append(ReplacementTransform(sp[3], rs[2])) tf_anims.append(Write(rs[3][:2])) self.play(FadeIn(sps)) self.wait() self.play(AnimationGroup(*tf_anims), run_time = 2) self.wait() self.play(Write(VGroup(*[rs[4:] for rs in rss]), submobject_mode = "all_at_once")) self.wait() self.play(FadeOut(rects)) self.wait() self.rss = rss
def ask_to_solve(self): question = TextMobject("解", "方程($x>0$)", ":") solve = TextMobject("解", ":") for tex in (question, solve): tex.scale(1.2) tex.to_corner(LEFT+UP) self.play(Write(question), run_time = 1) self.wait() self.question = question self.solve = solve
def add_title(self, title, scale_factor=1.5, animate=False): if not isinstance(title, Mobject): title = TextMobject(title).scale(scale_factor) title.to_edge(UP) title.add_background_rectangle() if animate: self.play(Write(title)) self.add_foreground_mobject(title) self.title = title return self
def rhs_could_be_any_number(self): rhs_list = [ "2", # The journey starts here. "3", # The first number that pops into your head when you hear "2". "\\pi", # The good ol' pi. "\\sqrt{2}", # The (most) famous irrational number. "42", # The answer to everything. "17.29", # TAXI.CAB "-1", # A negative number, because why not? "e", # The (most) famous mathematical constant. "\\dfrac{3+\\sqrt{13}}{2}", # The bronze ratio... and a fraction. "570", # 1/3 of the author. "\\varphi", # The golden ratio. "g_{64}", # Gigigigigigigigantic... "0", # And... stop! "N", ] anything_text = TextMobject("等号右边似乎可以放任何数...") anything_text.set_color(YELLOW) anything_text.to_edge(UP) equations = [ VGroup(ExpTower(order = 5), TexMobject("=", rhs).scale(0.8)).scale(2.5) for rhs in rhs_list ] init_equation = equations[0] init_equation.arrange_submobjects(RIGHT, aligned_edge = DOWN) init_equation.next_to(anything_text, DOWN, buff = self.tower_edge_buff) init_equation.to_edge(LEFT, buff = self.tower_edge_buff) for equation in equations: equation[0].move_to(init_equation[0]) equation[1][0].move_to(init_equation[1][0]) equation[1][1].move_to(init_equation[1][1], aligned_edge = LEFT) self.play(FadeIn(init_equation)) self.wait() self.play(Write(anything_text), run_time = 1) self.play( ShowCreationThenDestruction(SurroundingRectangle(init_equation[1][1])), run_time = 2 ) self.wait() for k, equation in enumerate(equations): if k > 0 and k != len(equations)-1: equation[0].move_to(init_equation[0]) equation[1].move_to(init_equation[1], aligned_edge = LEFT) self.remove(equations[k-1]) self.add(equations[k]) self.wait(1./3) elif k == len(equations)-1: self.wait() self.play(ReplacementTransform(equations[k-1], equations[k])) self.wait() self.anything_text = anything_text self.equation = equations[-1]
def build_the_tower(self): highest_order = 6 towers = [ ExpTower(order = k, is_infinite = False) for k in range(1, highest_order + 1) ] towers.append(ExpTower(order = highest_order, is_infinite = True)) heights = list(np.linspace(3, 4.5, highest_order + 2)) for tower, height in zip(towers, heights): tower.set_height(height) init_tower = towers[0] final_tower = towers[-1] self.play(Write(init_tower)) self.wait() for k, tower in enumerate(towers): if k < len(towers) - 2: new_tower = towers[k+1] new_exponent = new_tower.get_exponent() new_base = new_tower.get_base() self.play( ReplacementTransform(tower, new_exponent), Write(new_base), ) self.wait() else: xs = final_tower.get_elements() expdots = final_tower.get_expdots() sur_rect = SurroundingRectangle(expdots) self.play( ReplacementTransform(tower, xs, run_time = 1), Write(expdots, run_time = 2), ) self.play( Indicate(expdots, run_time = 1), ShowCreationThenDestruction(sur_rect, run_time = 2), ) self.wait() break self.tower = final_tower self.highest_order = highest_order
def build_the_equation(self): l_part = self.tower.copy() r_part = TexMobject("=", "2") r_part.match_height(l_part.get_base()) equation = VGroup(l_part, r_part) equation.arrange_submobjects(RIGHT, aligned_edge = DOWN) self.play( ReplacementTransform(self.tower, l_part, run_time = 1), Write(r_part, run_time = 2), ) self.equation = equation
def rewind_and_play_again(self): watch_again = TextMobject("再看一遍...") watch_again.set_color(YELLOW) rewind, play = buttons = VGroup(*[ Button().get_symbol().set_color(YELLOW).set_height(1) for Button in (RewindButton, PlayButton) ]) group = VGroup(watch_again, rewind) group.arrange_submobjects(DOWN, aligned_edge = RIGHT) group.to_corner(DOWN+RIGHT) play.move_to(rewind, aligned_edge = RIGHT) self.play(Write(watch_again), run_time = 0.5) self.wait() self.add(rewind) self.words.reverse() for word in self.words: self.play(FadeOut(VGroup(word)), run_time = 0.2) self.wait(0.1) self.remove(rewind) self.add(play) self.play(FadeOut(watch_again), run_time = 0.5) self.wait(0.5) self.remove(play)
def reveal_2_is_4(self): sqrt2_towers = VGroup(*[ ExpTower(element = "\\sqrt{2}", order = 5).match_height(x_tower) \ .move_to(x_tower, aligned_edge = RIGHT) for x_tower in self.x_towers ]) self.play( Transform(self.x_towers, sqrt2_towers, submobject_mode = "lagged_start"), run_time = 2, ) self.wait() self.play(FadeOut(self.rss)) self.wait() two_equals_four = TexMobject("2", "=", "4") for tex, color in zip(two_equals_four, [GREEN, WHITE, RED]): tex.set_color(color) two_equals_four.scale(3) two_equals_four.to_edge(DOWN, buff = 1) sources = VGroup(*[ self.equations[i][j][k].copy() for i, j, k in [(0, 1, 1), (1, 1, 0), (1, 1, 1)] ]) for source, target in zip(sources, two_equals_four): self.play(Transform(source, target)) self.wait() fake_qed = FakeQEDSymbol(order = 2, jagged_percentage = 0.3) fake_qed.next_to(two_equals_four, RIGHT, aligned_edge = DOWN, buff = 1) self.play(FadeIn(fake_qed)) self.wait() issue = TextMobject("思考:\\\\问题在哪?") issue.set_color(YELLOW) issue.to_corner(RIGHT+DOWN) self.play(Write(issue), run_time = 1) self.wait(2)
def label_vector(self, vector, label, animate=True, **kwargs): label = self.get_vector_label(vector, label, **kwargs) if animate: self.play(Write(label, run_time=1)) self.add(label) return label
def setup_axes(self, animate=False): # TODO, once eoc is done, refactor this to be less redundant. x_num_range = float(self.x_max - self.x_min) self.space_unit_to_x = self.x_axis_width / x_num_range if self.x_labeled_nums is None: self.x_labeled_nums = [] if self.x_leftmost_tick is None: self.x_leftmost_tick = self.x_min x_axis = NumberLine(x_min=self.x_min, x_max=self.x_max, unit_size=self.space_unit_to_x, tick_frequency=self.x_tick_frequency, leftmost_tick=self.x_leftmost_tick, numbers_with_elongated_ticks=self.x_labeled_nums, color=self.axes_color) x_axis.shift(self.graph_origin - x_axis.number_to_point(0)) if len(self.x_labeled_nums) > 0: if self.exclude_zero_label: self.x_labeled_nums = filter(lambda x: x != 0, self.x_labeled_nums) x_axis.add_numbers(*self.x_labeled_nums) if self.x_axis_label: x_label = TextMobject(self.x_axis_label) x_label.next_to(x_axis.get_tick_marks(), UP + RIGHT, buff=SMALL_BUFF) x_label.shift_onto_screen() x_axis.add(x_label) self.x_axis_label_mob = x_label y_num_range = float(self.y_max - self.y_min) self.space_unit_to_y = self.y_axis_height / y_num_range if self.y_labeled_nums is None: self.y_labeled_nums = [] if self.y_bottom_tick is None: self.y_bottom_tick = self.y_min y_axis = NumberLine( x_min=self.y_min, x_max=self.y_max, unit_size=self.space_unit_to_y, tick_frequency=self.y_tick_frequency, leftmost_tick=self.y_bottom_tick, numbers_with_elongated_ticks=self.y_labeled_nums, color=self.axes_color, line_to_number_vect=LEFT, ) y_axis.shift(self.graph_origin - y_axis.number_to_point(0)) y_axis.rotate(np.pi / 2, about_point=y_axis.number_to_point(0)) if len(self.y_labeled_nums) > 0: if self.exclude_zero_label: self.y_labeled_nums = filter(lambda y: y != 0, self.y_labeled_nums) y_axis.add_numbers(*self.y_labeled_nums) if self.y_axis_label: y_label = TextMobject(self.y_axis_label) y_label.next_to(y_axis.get_tick_marks(), UP + RIGHT, buff=SMALL_BUFF) y_label.shift_onto_screen() y_axis.add(y_label) self.y_axis_label_mob = y_label if animate: self.play(Write(VGroup(x_axis, y_axis))) else: self.add(x_axis, y_axis) self.x_axis, self.y_axis = self.axes = VGroup(x_axis, y_axis) self.default_graph_colors = it.cycle(self.default_graph_colors)
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 write_vector_coordinates(self, vector, **kwargs): coords = vector_coordinate_label(vector, **kwargs) self.play(Write(coords)) return coords
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()