def construct(self): formula = TexMobject(*([ "{%d \\over %d} \\cdot" % (wallis_numer(n), wallis_denom(n)) for n in range(1, self.n_terms + 1) ] + ["\\cdots"])) result = TexMobject("=", "{\\pi \\over 2}") result.scale(2) pi = result[-1][0] pi.set_color(YELLOW) circle = Circle(color=YELLOW) circle.surround(pi) question = TexMobject("?", color=YELLOW) question.scale(2).next_to(circle, RIGHT, buff=0.4) result_group = VGroup(result, circle, question) result_group.next_to(formula, DOWN) group = VGroup(formula, result_group) group.center().set_width(10) bg_rect = BackgroundRectangle(group, fill_opacity=0.5, buff=0.2) random_walks = VGroup(*[ RandomWalk1DArrow(random_walk_string(30), step_size=0.5) for k in range(self.n_walks) ]) for k, walk in enumerate(random_walks): walk.shift(random.randrange(-5, 5) * 2 * walk.step_size * UP) random_walks.center() text = TextMobject(self.part).scale(3).set_color(YELLOW) text.to_corner(RIGHT + DOWN) self.add(random_walks) self.add(FullScreenFadeRectangle()) self.add(bg_rect, group, text)
def get_subdivision_braces_and_labels( self, parts, labels, direction, buff=SMALL_BUFF, min_num_quads=1 ): label_mobs = VGroup() braces = VGroup() for label, part in zip(labels, parts): brace = Brace( part, direction, min_num_quads=min_num_quads, buff=buff ) if isinstance(label, Mobject): label_mob = label else: label_mob = TexMobject(label) label_mob.scale(self.default_label_scale_val) label_mob.next_to(brace, direction, buff) braces.add(brace) label_mobs.add(label_mob) parts.braces = braces parts.labels = label_mobs parts.label_kwargs = { "labels": label_mobs.copy(), "direction": direction, "buff": buff, } return VGroup(parts.braces, parts.labels)
def get_vector_label(self, vector, label, at_tip=False, direction="left", rotate=False, color=None, label_scale_factor=VECTOR_LABEL_SCALE_FACTOR): if not isinstance(label, TexMobject): if len(label) == 1: label = "\\vec{\\textbf{%s}}" % label label = TexMobject(label) if color is None: color = vector.get_color() label.set_color(color) label.scale(label_scale_factor) label.add_background_rectangle() if at_tip: vect = vector.get_vector() vect /= np.linalg.norm(vect) label.next_to(vector.get_end(), vect, buff=SMALL_BUFF) else: angle = vector.get_angle() if not rotate: label.rotate(-angle, about_point=ORIGIN) if direction is "left": label.shift(-label.get_bottom() + 0.1 * UP) else: label.shift(-label.get_top() + 0.1 * DOWN) label.rotate(angle, about_point=ORIGIN) label.shift((vector.get_end() - vector.get_start()) / 2) return label
def get_vector_label(self, vector, label, direction="left", rotate=False, color=None, label_scale_factor=VECTOR_LABEL_SCALE_FACTOR): if not isinstance(label, TexMobject): if len(label) == 1: label = "\\vec{\\textbf{%s}}" % label label = TexMobject(label) if color is None: color = vector.get_color() label.set_color(color) label.scale(label_scale_factor) label.add_background_rectangle() angle = vector.get_angle() if not rotate: label.rotate(-angle, about_point=ORIGIN) if direction is "left": label.shift(-label.get_bottom() + 0.1 * UP) else: label.shift(-label.get_top() + 0.1 * DOWN) label.rotate(angle, about_point=ORIGIN) label.shift((vector.get_end() - vector.get_start()) / 2) return label
def countdown(self): for k in range(5, -1, -1): countdown_text = TexMobject(str(k)) countdown_text.scale(1.5) countdown_text.set_color(YELLOW) countdown_text.to_corner(RIGHT+UP) self.add(countdown_text) self.wait() self.remove(countdown_text)
def add_brackets(self): bracket_pair = TexMobject("\\big[ \\big]") bracket_pair.scale(2) bracket_pair.stretch_to_fit_height(self.get_height() + 0.5) l_bracket, r_bracket = bracket_pair.split() l_bracket.next_to(self, LEFT) r_bracket.next_to(self, RIGHT) self.add(l_bracket, r_bracket) self.brackets = VGroup(l_bracket, r_bracket) return self
def add_brackets(self): bracket_pair = TexMobject("\\big[ \\big]") bracket_pair.scale(2) bracket_pair.stretch_to_fit_height(self.get_height() + 0.5) l_bracket, r_bracket = bracket_pair.split() l_bracket.next_to(self, LEFT) r_bracket.next_to(self, RIGHT) self.add(l_bracket, r_bracket) self.brackets = VGroup(l_bracket, r_bracket) return self
def construct(self): wallis_rects_570 = WallisRectangles(order=570) quarter_circle = Sector( outer_radius=wallis_rects_570.get_height(), stroke_color=GREY, stroke_width=5.70, fill_opacity=0, ) quarter_circle.move_arc_center_to(wallis_rects_570.get_bottom_left()) text = TexMobject("n = 570") text.scale(1.5) text.move_to(wallis_rects_570.get_top_right()) self.add(wallis_rects_570, quarter_circle, text) self.wait()
def get_number_mob(self, num): result = VGroup() place = 0 max_place = self.max_place while place < max_place: digit = TexMobject(str(self.get_place_num(num, place))) if place >= len(self.digit_place_colors): self.digit_place_colors += self.digit_place_colors digit.set_color(self.digit_place_colors[place]) digit.scale(self.num_scale_factor) digit.next_to(result, LEFT, buff=SMALL_BUFF, aligned_edge=DOWN) result.add(digit) place += 1 return result
def get_number_mobjects(self, *numbers, **kwargs): # TODO, handle decimals if len(numbers) == 0: numbers = self.default_numbers_to_display() if "force_integers" in kwargs and kwargs["force_integers"]: numbers = list(map(int, numbers)) result = VGroup() for number in numbers: mob = TexMobject(str(number)) mob.scale(self.number_scale_val) mob.next_to( self.number_to_point(number), self.label_direction, self.line_to_number_buff, ) result.add(mob) return result
def construct(self): wallis_rects_5 = WallisRectangles(rect_colors=[ "#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#0080FF" ], order=5) quarter_circle = Sector( outer_radius=wallis_rects_5.get_height(), stroke_color=GREY, stroke_width=5.70, fill_opacity=0, ) quarter_circle.move_arc_center_to(wallis_rects_5.get_bottom_left()) text = TexMobject("n = 5") text.scale(1.5) text.move_to(wallis_rects_5.get_top_right()) self.add(wallis_rects_5, quarter_circle, text) 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 get_det_text(matrix, determinant=None, background_rect=True, initial_scale_factor=2): parens = TexMobject(["(", ")"]) parens.scale(initial_scale_factor) parens.stretch_to_fit_height(matrix.get_height()) l_paren, r_paren = parens.split() l_paren.next_to(matrix, LEFT, buff=0.1) r_paren.next_to(matrix, RIGHT, buff=0.1) det = TextMobject("det").next_to(l_paren, LEFT, buff=0.1) if background_rect: det.add_background_rectangle() det_text = VMobject(det, l_paren, r_paren) if determinant is not None: eq = TexMobject("=") eq.next_to(r_paren, RIGHT, buff=0.1) result = TexMobject(str(determinant)) result.next_to(eq, RIGHT, buff=0.2) det_text.add(eq, result) return det_text
def setup(self): pos_axis = NumberLine(x_min=-4.5, x_max=2.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() vec = pos_axis.number_to_point(0) - time_axis.number_to_point(0) time_axis.shift(vec) pos_text = TextMobject("位置") pos_text.next_to(pos_axis.number_to_point(2.5), LEFT) time_text = TextMobject("时间") time_text.next_to(time_axis.number_to_point(9.5), DOWN) axes_group = VGroup(pos_axis, time_axis, pos_text, time_text) axes_group.center() title_pq = TexMobject("P_4", "570", "Q_4") title_pq.scale(1.5) title_pq.to_corner(UP + RIGHT) for part, color in zip(title_pq, [ORANGE, BLACK, GREEN]): part.set_color(color) r_arrow = TexMobject("\\rightarrow") l_arrow = TexMobject("\\leftarrow") for arrow in (r_arrow, l_arrow): arrow.scale(1.5) arrow.move_to(title_pq[1]) sequence_p, sequence_q = sequences = ["UDUUDUDD", "DDUDDUDD"] colors = [ORANGE, GREEN] walk_p, walk_q = walks = [ RandomWalk1DArrow(sequence, up_color = color, down_color = color) \ .move_start_to(pos_axis.number_to_point(0)) for sequence, color in zip(sequences, colors) ] parts_p, parts_q = [walk.split_at(3) for walk in walks] self.axes_group = axes_group self.title_pq = title_pq self.walk_p = walk_p self.walk_q = walk_q self.parts_p = parts_p self.parts_q = parts_q self.r_arrow = r_arrow self.l_arrow = l_arrow
def get_det_text(matrix, determinant=None, background_rect=True, initial_scale_factor=2): parens = TexMobject(["(", ")"]) parens.scale(initial_scale_factor) parens.stretch_to_fit_height(matrix.get_height()) l_paren, r_paren = parens.split() l_paren.next_to(matrix, LEFT, buff=0.1) r_paren.next_to(matrix, RIGHT, buff=0.1) det = TextMobject("det") det.scale(initial_scale_factor) det.next_to(l_paren, LEFT, buff=0.1) if background_rect: det.add_background_rectangle() det_text = VMobject(det, l_paren, r_paren) if determinant is not None: eq = TexMobject("=") eq.next_to(r_paren, RIGHT, buff=0.1) result = TexMobject(str(determinant)) result.next_to(eq, RIGHT, buff=0.2) det_text.add(eq, result) return det_text
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 add_bars(self, values): buff = float(self.width) / (2 * len(values) + 1) bars = VGroup() for i, value in enumerate(values): bar = Rectangle( height=(value / self.max_value) * self.height, width=buff, stroke_width=self.bar_stroke_width, fill_opacity=self.bar_fill_opacity, ) bar.move_to((2 * i + 1) * buff * RIGHT, DOWN + LEFT) bars.add(bar) bars.set_color_by_gradient(*self.bar_colors) bar_labels = VGroup() for bar, name in zip(bars, self.bar_names): label = TexMobject(str(name)) label.scale(self.bar_label_scale_val) label.next_to(bar, DOWN, SMALL_BUFF) bar_labels.add(label) self.add(bars, bar_labels) self.bars = bars self.bar_labels = bar_labels
def add_figure(self): # Main figure wallis_rects = WallisRectangles(order=10) order = wallis_rects.get_order() # Variables and braces on the left left_rects = [ wallis_rects.get_rectangle(k, 0) for k in [0, 1, 2, 3, -1] ] left_braces = [ Brace(rect, direction=LEFT, buff=0.1) for rect in left_rects ] left_lengths = [ TexMobject(symbol) for symbol in ["a_0", "a_1", "a_2", "a_3", "a_{n-1}"] ] left_lengths[-1].scale(0.7) for brace, length in zip(left_braces, left_lengths): brace.put_at_tip(length, buff=0.15) left_vdots = TexMobject("\\vdots") left_vdots.scale(2) left_vdots.move_to( (left_braces[-1].get_center() + left_braces[-2].get_center()) / 2) # Variables and braces on the bottom down_rects = [ wallis_rects.get_rectangle(0, k) for k in [0, 1, 2, 3, -1] ] down_braces = [ Brace(rect, direction=DOWN, buff=0.1) for rect in down_rects ] down_lengths = [ TexMobject(symbol) for symbol in ["a_0", "a_1", "a_2", "a_3", "a_{n-1}"] ] down_lengths[-1].scale(0.7) for brace, length in zip(down_braces, down_lengths): brace.put_at_tip(length, buff=0.15) down_cdots = TexMobject("\\cdots") down_cdots.scale(2) down_cdots.move_to( (down_braces[-1].get_center() + down_braces[-2].get_center()) / 2) # The quarter circle quarter_circle = Sector( outer_radius=wallis_rects.get_height(), stroke_color=GREY, stroke_width=5.70, fill_opacity=0, ) quarter_circle.move_arc_center_to(wallis_rects.get_bottom_left()) # Add everthing figure_group = VGroup( wallis_rects, VGroup(*left_braces), VGroup(*left_lengths), left_vdots, VGroup(*down_braces), VGroup(*down_lengths), down_cdots, quarter_circle, ) figure_group.center().to_edge(LEFT, buff=0.15) self.add(figure_group)
def show_the_solution(self): # Prepare for the solution pre_solve = VGroup(*self.question[::2]) self.play( ReplacementTransform(pre_solve, self.solve), FadeOut(self.question[1]), run_time = 1, ) self.wait() # Manipulate LHS old_l_part, r_part = self.equation new_l_part = ExpTower(order = self.highest_order+1, is_infinite = True) new_l_part.match_height(old_l_part) new_l_part.next_to(r_part, LEFT, aligned_edge = DOWN) old_rect, new_rect = rects = [ CoverRectangle(part, text = "2") for part in (old_l_part, new_l_part.get_exponent()) ] old_two, new_two = twos = [ rect.get_text_mob() for rect in rects ] self.play(DrawBorderThenFill(old_rect, run_time = 1)) self.wait() self.play( ReplacementTransform(old_l_part, new_l_part), ReplacementTransform(old_rect, new_rect), ) self.wait() new_equation = VGroup(new_l_part, r_part, new_rect) new_equation.generate_target() new_equation.target.scale(0.8) new_equation.target.shift(UP) self.play(MoveToTarget(new_equation)) self.wait() # A little bit clean-up source_eq = VGroup(*[ mob.copy() for mob in (new_l_part.get_base(), new_two, r_part[0], r_part[1]) ]) source_eq.generate_target() target_eq = TexMobject("x", "^2", "=", "2") target_eq.scale(3).next_to(source_eq, DOWN, buff = 1) for k, (old_part, new_part) in enumerate(zip(source_eq.target, target_eq)): old_part.move_to(new_part) if k == 1: old_part.scale(0.5) old_part.shift(RIGHT/4) self.play( FadeOut(new_rect), MoveToTarget(source_eq), ) self.wait() # Reveal the final answer result = TexMobject("x", "=", "\\sqrt", "2") result.set_height(source_eq.get_height() * 0.7) result.move_to(source_eq) self.play(*[ ReplacementTransform(source_eq[m], result[n], path_arc = angle) for m, n, angle in [(0, 0, 0), (1, 2, -TAU/3), (2, 1, 0), (3, 3, 0)] ]) self.wait() qed = QEDSymbol() qed.next_to(result, RIGHT, aligned_edge = DOWN, buff = 1.5) self.play(FadeIn(qed)) self.wait()
def construct(self): colors = ["#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#0080FF"] wallis_rects_4 = WallisRectangles( order=5, rect_colors=colors, ) vert_lines = VGroup(*[ Line(3.5*UP, 3.5*DOWN, color = GREY, stroke_width = 3) \ .next_to(wallis_rects_4.get_rectangle(0, k), direction, buff = 0) for k, direction in zip(list(range(5))+[4], [LEFT]*5+[RIGHT]) ]) horiz_lines = VGroup(*[ Line(3.5*LEFT, 3.5*RIGHT, color = GREY, stroke_width = 3) \ .next_to(wallis_rects_4.get_rectangle(k, 0), direction, buff = 0) for k, direction in zip(list(range(5))+[4], [DOWN]*5+[UP]) ]) for vert_line in vert_lines: vert_line.vertically_center() for horiz_line in horiz_lines: horiz_line.horizontally_center() vert_labels = VGroup(*[ TexMobject("a_%d" % k) \ .move_to((vert_lines[k].get_center() + vert_lines[k+1].get_center())/2) \ .shift(3.5*DOWN) for k in range(5) ]) horiz_labels = VGroup(*[ TexMobject("a_%d" % k) \ .move_to((horiz_lines[k].get_center() + horiz_lines[k+1].get_center())/2) \ .shift(3.5*LEFT) for k in range(5) ]) area_texs = VGroup() factors = [1.25, 1, 0.9, 0.7, 0.6] for p in range(5): for q in range(5 - p): rect = wallis_rects_4.get_rectangle(p, q) tex = TexMobject("{a_%d} {a_%d}" % (q, p)) tex.scale(factors[p + q]) tex.move_to(rect) area_texs.add(tex) figure = VGroup() figure.add(wallis_rects_4, vert_lines, horiz_lines, vert_labels, horiz_labels, area_texs) figure.to_edge(LEFT) self.add(figure) tex_list = VGroup() for p in range(5): formula_string = ( " + ".join(["a_%d a_%d" % (q, p - q) for q in range(p + 1)]) + "=1") formula = TexMobject(formula_string) tex_list.add(formula) # tex_list.add(TexMobject("\\vdots")) tex_factors = np.linspace(1, 0.7, 5) for tex, color, factor in zip(tex_list, colors, tex_factors): tex.set_color(color) tex.scale(factor) tex_list.arrange_submobjects(DOWN, aligned_edge=LEFT) tex_list.to_edge(RIGHT) self.add(tex_list) self.wait()
def construct(self): # Chart on the left colors = [WHITE, ORANGE, GREEN] titles = VGroup(*[ TexMobject(text).set_color(color) for text, color in zip(["n", "p_n", "q_n"], colors) ]) contents = VGroup(*[ VGroup(*[ TexMobject("%d" % num) for num in [k, central_binomial_coeff(k), central_binomial_coeff(k)] ]) for k in range(8) ]) titles.arrange_submobjects(RIGHT, buff=1) for num, line in enumerate(contents): for k, element in enumerate(line): buff = 0.6 + 0.8 * num element.next_to(titles[k], DOWN, aligned_edge=LEFT, buff=buff) element.set_color(colors[k]) sep_line = Line(ORIGIN, 4.5 * RIGHT, stroke_width=5) sep_line.next_to(titles, DOWN) chart = VGroup(titles, contents, sep_line) chart.set_height(7) chart.center().to_edge(LEFT) self.add(chart) # Figures on the right std_zero_pos_axis = NumberLine(x_min=-2, x_max=2, color=GREY, unit_size=0.25, tick_size=0.05) std_zero_pos_axis.rotate(np.pi / 2) std_nocross_pos_axis = NumberLine(x_min=-4, x_max=4, color=GREY, unit_size=0.25, tick_size=0.05) std_nocross_pos_axis.rotate(np.pi / 2) std_time_axis = NumberLine(x_min=0, x_max=5.5, color=GREY, unit_size=0.25, tick_size=0.05) std_zero_axes = VGroup(std_zero_pos_axis, std_time_axis) std_nocross_axes = VGroup(std_nocross_pos_axis, std_time_axis) zero_walks = VGroup() for sequence in ["UUDD", "UDUD", "UDDU", "DDUU", "DUDU", "DUUD"]: axes = std_zero_axes.copy() zero_walk = RandomWalk1DArrow(sequence, step_size=0.25) zero_walk.move_start_to(axes[0].number_to_point(0)) zero_walks.add(VGroup(axes, zero_walk)) zero_walks.arrange_submobjects_in_grid(2, 3, buff=0.5) zero_rect = SurroundingRectangle(zero_walks, color=ORANGE, buff=0.4) zero_walks.add(zero_rect) nocross_walks = VGroup() for sequence in ["DDDD", "DDUD", "DDDU", "UUUU", "UUDU", "UUUD"]: axes = std_nocross_axes.copy() nocross_walk = RandomWalk1DArrow(sequence, step_size=0.25) nocross_walk.move_start_to(axes[0].number_to_point(0)) nocross_walks.add(VGroup(axes, nocross_walk)) nocross_walks.arrange_submobjects_in_grid(2, 3, buff=0.5) nocross_rect = SurroundingRectangle(nocross_walks, color=GREEN, buff=0.4) nocross_walks.add(nocross_rect) relation = TexMobject("p_2", "=", "q_2", "=", "6") relation[0].set_color(ORANGE) relation[2].set_color(GREEN) relation.scale(1.5) figure = VGroup(zero_walks, relation, nocross_walks) figure.arrange_submobjects(DOWN) figure.set_height(7) figure.center().to_edge(RIGHT) self.add(figure) self.wait()
def generate_points(self): dots = TexMobject(*list("...")) dots.arrange_submobjects(RIGHT, buff = self.gap_buff) dots.rotate(self.angle) dots.scale(1.5) self.add(dots)