Exemple #1
0
    def construct(self):
        two_dot = TexMobject("2\\cdot")
        equals = TexMobject("=")
        self.add_axes()
        v = self.add_vector([3, 1])
        v_coords, vx_line, vy_line = self.vector_to_coords(v, cleanup = False)
        self.play(ApplyMethod(v_coords.to_edge, UP))
        two_dot.next_to(v_coords, LEFT)
        equals.next_to(v_coords, RIGHT)
        two_v = self.add_vector([6, 2], animate = False)
        self.remove(two_v)
        self.play(
            Transform(v.copy(), two_v), 
            Write(two_dot, run_time = 1)
        )
        two_v_coords, two_v_x_line, two_v_y_line = self.vector_to_coords(
            two_v, cleanup = False
        )
        self.play(
            ApplyMethod(two_v_coords.next_to, equals, RIGHT),
            Write(equals, run_time = 1)
        )
        self.dither(2)

        x, y = v_coords.get_mob_matrix().flatten()
        two_v_elems = two_v_coords.get_mob_matrix().flatten()
        x_sym, y_sym = map(TexMobject, ["x", "y"])
        two_x_sym, two_y_sym = map(TexMobject, ["2x", "2y"])
        VMobject(x_sym, two_x_sym).highlight(X_COLOR)
        VMobject(y_sym, two_y_sym).highlight(Y_COLOR)
        syms = [x_sym, y_sym, two_x_sym, two_y_sym]
        VMobject(*syms).scale(VECTOR_LABEL_SCALE_VAL)
        for sym, num in zip(syms, [x, y] + list(two_v_elems)):
            sym.move_to(num)
        self.play(
            Transform(x, x_sym),
            Transform(y, y_sym),
            FadeOut(VMobject(*two_v_elems))
        )
        self.dither()
        self.play(
            Transform(
                VMobject(two_dot.copy(), x.copy()),
                two_x_sym
            ),
            Transform(
                VMobject(two_dot.copy(), y.copy() ),
                two_y_sym
            )
        )
        self.dither(2)
Exemple #2
0
    def construct(self):
        v_mob = TexMobject(get_vect_tex("v"))
        v_mob.highlight(V_COLOR)

        matrix = Matrix([self.vect_coords])
        vector = Matrix(self.vect_coords)
        matrix.highlight_columns(X_COLOR, Y_COLOR)
        vector.highlight_columns(YELLOW)
        _input = Matrix(["x", "y"])
        _input.get_entries().gradient_highlight(X_COLOR, Y_COLOR)
        left_input, right_input = [_input.copy() for x in range(2)]
        dot, equals = map(TexMobject, ["\\cdot", "="])
        equation = Group(
            vector, dot, left_input, equals,
            matrix, right_input
        )
        equation.arrange_submobjects()
        left_brace = Brace(Group(vector, left_input))
        right_brace = Brace(matrix, UP)
        left_words = left_brace.get_text("Dot product")
        right_words = right_brace.get_text("Transform")
        right_words.scale_to_fit_width(right_brace.get_width())

        right_v_brace = Brace(right_input, UP)
        right_v_mob = v_mob.copy()
        right_v_brace.put_at_tip(right_v_mob)
        right_input.add(right_v_brace, right_v_mob)
        left_v_brace = Brace(left_input, UP)
        left_v_mob = v_mob.copy()
        left_v_brace.put_at_tip(left_v_mob)
        left_input.add(left_v_brace, left_v_mob)        


        self.add(matrix, right_input)
        self.play(
            GrowFromCenter(right_brace),
            Write(right_words, run_time = 1)
        )
        self.dither()
        self.play(
            Write(equals),
            Write(dot),
            Transform(matrix.copy(), vector),
            Transform(right_input.copy(), left_input)
        )
        self.play(
            GrowFromCenter(left_brace),
            Write(left_words, run_time = 1)
        )
        self.dither()
Exemple #3
0
 def construct(self):
     l_m1, l_m2, eq, r_m2, r_m1 = TexMobject([
         "M_1",  "M_2", "=", "M_2", "M_1"
     ]).scale(1.5).split()
     VMobject(l_m1, r_m1).highlight(YELLOW)
     VMobject(l_m2, r_m2).highlight(PINK)
     q_marks = TextMobject("???")
     q_marks.highlight(TEAL)
     q_marks.next_to(eq, UP)
     neq = TexMobject("\\neq")
     neq.move_to(eq)
     
     self.play(*map(Write, [l_m1, l_m2, eq]))
     self.play(
         Transform(l_m1.copy(), r_m1),
         Transform(l_m2.copy(), r_m2),
         path_arc = -np.pi,
         run_time = 2
     )
     self.play(Write(q_marks))
     self.dither()
     self.play(Transform(
         VMobject(eq, q_marks),
         VMobject(neq),
         submobject_mode = "lagged_start"
     ))
     self.dither()
Exemple #4
0
    def show_snells(self, index, frame):
        left_text, right_text = [
            "\\dfrac{\\sin(\\theta_%d)}{\\phantom{\\sqrt{y_1}}}"%x
            for x in index, index+1
        ]
        left, equals, right = TexMobject(
            [left_text, "=", right_text]
        ).split()
        vs = []
        sqrt_ys = []
        for x, numerator in [(index, left), (index+1, right)]:
            v, sqrt_y = [
                TexMobject(
                    text, size = "\\Large"
                ).next_to(numerator, DOWN)
                for text in "v_%d"%x, "\\sqrt{y_%d}"%x
            ]
            vs.append(v)
            sqrt_ys.append(sqrt_y)
        start, end = [
            Mobject(
                left.copy(), mobs[0], equals.copy(), right.copy(), mobs[1]
            ).replace(frame)
            for mobs in vs, sqrt_ys
        ]

        self.add(start)
        self.dither(2)
        self.play(Transform(
            start, end, 
            path_func = counterclockwise_path()
        ))
        self.dither(2)
        self.remove(start, end)
Exemple #5
0
    def construct(self):
        self.setup()
        matrix = Matrix(np.array(self.transposed_matrix).transpose())
        matrix.highlight_columns(X_COLOR, Y_COLOR)
        matrix.next_to(ORIGIN, LEFT).to_edge(UP)
        matrix_background = BackgroundRectangle(matrix)
        self.play(ShowCreation(matrix_background), Write(matrix))
        if self.show_square:
            self.add_unit_square(animate = True)
        self.add_foreground_mobject(matrix_background, matrix)
        self.dither()
        self.apply_transposed_matrix([self.transposed_matrix[0], [0, 1]])
        self.apply_transposed_matrix([[1, 0], self.transposed_matrix[1]])
        self.dither()
        if self.show_square:


            bottom_brace = Brace(self.i_hat, DOWN)
            right_brace = Brace(self.square, RIGHT)
            width = TexMobject(str(self.transposed_matrix[0][0]))
            height = TexMobject(str(self.transposed_matrix[1][1]))
            width.next_to(bottom_brace, DOWN)
            height.next_to(right_brace, RIGHT)
            for mob in bottom_brace, width, right_brace, height:
                mob.add_background_rectangle()
                self.play(Write(mob, run_time = 0.5))
            self.dither()

            width_target, height_target = width.copy(), height.copy()
            det = np.linalg.det(self.transposed_matrix)
            times, eq_det = map(TexMobject, ["\\times", "=%d"%det])
            words = TextMobject("New area $=$")
            equation = VMobject(
                words, width_target, times, height_target, eq_det
            )
            equation.arrange_submobjects(RIGHT, buff = 0.2)
            equation.next_to(self.square, UP, aligned_edge = LEFT)
            equation.shift(0.5*RIGHT)
            background_rect = BackgroundRectangle(equation)

            self.play(
                ShowCreation(background_rect),                
                Transform(width.copy(), width_target),
                Transform(height.copy(), height_target),
                *map(Write, [words, times, eq_det])
            )
            self.dither()
Exemple #6
0
    def rearrange(self):
        sqrt_nudge = 0.2*LEFT        
        y, equals = self.y_equals.split()
        d, sin, squared, theta = self.y_expression.split()
        y_sqrt = TexMobject("\\sqrt{\\phantom{y}}")
        d_sqrt = y_sqrt.copy()
        y_sqrt.shift(y.get_center()+sqrt_nudge)
        d_sqrt.shift(d.get_center()+sqrt_nudge)

        self.play(
            ShimmerIn(y_sqrt),
            ShimmerIn(d_sqrt),
            ApplyMethod(squared.shift, 4*UP),
            ApplyMethod(theta.shift, 1.5* squared.get_width()*LEFT)
        )
        self.dither()
        y_sqrt.add(y)
        d_sqrt.add(d)
        sin.add(theta)

        sin_over = TexMobject("\\dfrac{\\phantom{\\sin(\\theta)}}{\\quad}")
        sin_over.next_to(sin, DOWN, 0.15)
        new_eq = equals.copy()
        new_eq.next_to(sin_over, LEFT)
        one_over = TexMobject("\\dfrac{1}{\\quad}")
        one_over.next_to(new_eq, LEFT)
        one_over.shift(
            (sin_over.get_bottom()[1]-one_over.get_bottom()[1])*UP
        )

        self.play(
            Transform(equals, new_eq),
            ShimmerIn(sin_over),
            ShimmerIn(one_over),
            ApplyMethod(
                d_sqrt.next_to, one_over, DOWN,
                path_func = path_along_arc(-np.pi)
            ),
            ApplyMethod(
                y_sqrt.next_to, sin_over, DOWN,
                path_func = path_along_arc(-np.pi)
            ),
            run_time = 2
        )
        self.dither()

        brace = Brace(d_sqrt, DOWN)
        constant = TextMobject("Constant")
        constant.next_to(brace, DOWN)

        self.play(
            GrowFromCenter(brace),
            ShimmerIn(constant)
        )
Exemple #7
0
 def generate_sea_of_zeros(self):
     zero = TexMobject("0")
     self.sea_of_zeros = []
     for n in range(self.nrows):
         for a in range((self.nrows - n)/2 + 1):
             for k in (n + a + 1, -a -1):
                 self.coords.append((n, k))
                 mob = zero.copy()
                 mob.shift(self.coords_to_center(n, k))
                 self.coords_to_mobs[n][k] = mob
                 self.add(mob)
     return self
Exemple #8
0
    def construct(self):
        v = TexMobject(self.v_str)
        v.highlight(YELLOW)
        eq = TexMobject("=")
        coords = Matrix(["x", "y", "z"])
        eq2 = eq.copy()
        if self.post_transform:
            L, l_paren, r_paren = map(TexMobject, "L()")
            parens = VMobject(l_paren, r_paren)
            parens.scale(2)
            parens.stretch_to_fit_height(
                coords.get_height()
            )
            VMobject(L, l_paren, coords, r_paren).arrange_submobjects(buff = 0.1)
            coords.submobjects = [L, l_paren] + coords.submobjects + [r_paren]

        lin_comb = VMobject(*map(TexMobject, [
            "x", self.i_str, "+",
            "y", self.j_str, "+",
            "z", self.k_str,
        ]))
        lin_comb.arrange_submobjects(
            RIGHT, buff = 0.1, 
            aligned_edge = ORIGIN if self.post_transform else DOWN
        )
        lin_comb_parts = np.array(lin_comb.split())
        new_x, new_y, new_z = lin_comb_parts[[0, 3, 6]]
        i, j, k = lin_comb_parts[[1, 4, 7]]
        plusses = lin_comb_parts[[2, 5]]
        i.highlight(X_COLOR)
        j.highlight(Y_COLOR)
        k.highlight(Z_COLOR)

        everything = VMobject(v, eq, coords, eq2, lin_comb)
        everything.arrange_submobjects(buff = 0.2)
        everything.scale_to_fit_width(2*SPACE_WIDTH - 1)
        everything.to_edge(DOWN)
        if not self.post_transform:
            lin_comb.shift(0.35*UP)

        self.play(*map(Write, [v, eq, coords]))
        self.dither()
        self.play(
            Transform(
                coords.get_entries().copy(),
                VMobject(new_x, new_y, new_z),
                path_arc = -np.pi,
                submobject_mode = "lagged_start"
            ),
            Write(VMobject(*[eq2, i, j, k] + list(plusses))),
            run_time = 3
        )
        self.dither()
Exemple #9
0
    def construct(self):
        self.setup()
        self.plane.fade(0.3)
        self.add_unit_square(color = YELLOW_E, opacity = 0.5)
        self.add_title(
            ["The", "``determinant''", "of a transformation"],
            scale_factor = 1
        )
        self.title.split()[1].split()[1].highlight(YELLOW)

        matrix_background, matrix, det_text = self.get_matrix()
        self.add_foreground_mobject(matrix_background, matrix)

        A = TexMobject("A")
        area_label = VMobject(A.copy(), A.copy(), A)
        area_label.move_to(self.square)
        det = np.linalg.det(self.t_matrix)
        if np.round(det) == det:
            det = int(det)
        area_label_target = VMobject(
            TexMobject(str(det)), TexMobject("\\cdot"), A.copy()
        )
        if det < 1 and det > 0:
            area_label_target.scale(det)
        area_label_target.arrange_submobjects(RIGHT, buff = 0.1)
        self.add_moving_mobject(area_label, area_label_target)
        
        self.dither()
        self.apply_transposed_matrix(self.t_matrix)
        self.dither()
        det_mob_copy = area_label.split()[0].copy()
        new_det_mob = det_mob_copy.copy().scale_to_fit_height(
            det_text.split()[0].get_height()
        )
        new_det_mob.next_to(det_text, RIGHT, buff = 0.2)
        new_det_mob.add_background_rectangle()
        det_mob_copy.add_background_rectangle(opacity = 0)
        self.play(Write(det_text))
        self.play(Transform(det_mob_copy, new_det_mob))
        self.dither()
Exemple #10
0
 def get_log_anim(self, center):
     O_log_n = TexMobject(["O(", "\\log(n)", ")"])
     O_log_n.shift(center)
     log_n = O_log_n.split()[1]
     #super hacky
     g = log_n.split()[2]
     for mob in g.submobjects:
         mob.is_subpath = False 
         mob.set_fill(BLACK, 1.0)
         log_n.add(mob)
     g.submobjects = []
     #end hack
     top = TOP(2, None, "n", radius = 0.75)
     top.scale_to_fit_width(log_n.get_width())
     top.shift(log_n.get_center())
     new_O_log_n = O_log_n.copy()
     new_O_log_n.submobjects[1] = top
     return Transform(O_log_n, new_O_log_n)
Exemple #11
0
    def take_third_derivative_of_cubic(self):
        polynomial = self.polynomial
        plus_cubic_term = TexMobject("+\\,", "c_3", "x^3")
        plus_cubic_term.next_to(polynomial, RIGHT)
        plus_cubic_term.to_edge(RIGHT, buff = LARGE_BUFF)
        plus_cubic_term.highlight_by_tex("c_3", self.colors[3])
        plus_cubic_copy = plus_cubic_term.copy()

        polynomial.generate_target()
        polynomial.target.next_to(plus_cubic_term, LEFT)

        self.play(FocusOn(polynomial))
        self.play(
            MoveToTarget(polynomial),
            GrowFromCenter(plus_cubic_term)
        )
        self.dither()

        brace = Brace(polynomial.quadratic_part, DOWN)
        third_derivative = TexMobject(
            "\\frac{d^3 P}{dx^3}(x) = ", "0"
        )
        third_derivative.shift(
            brace.get_bottom() + MED_SMALL_BUFF*DOWN -\
            third_derivative.get_part_by_tex("0").get_top()
        )        

        self.play(Write(third_derivative[0]))
        self.play(GrowFromCenter(brace))
        self.play(ReplacementTransform(
            polynomial.quadratic_part.copy(),
            VGroup(third_derivative[1])
        ))
        self.dither(2)
        self.play(plus_cubic_copy.next_to, third_derivative, RIGHT)
        derivative_term = self.take_derivatives_of_monomial(
            VGroup(*plus_cubic_copy[1:])
        )
        third_derivative.add(derivative_term)

        self.polynomial_third_derivative = third_derivative
Exemple #12
0
 def write_old_style_rules(self):
     start = TexMobject("a^x a^y = a^{x+y}")
     end = TexMobject("\\log_a(xy) = \\log_a(x) + \\log_a(y)")
     start.shift(UP)
     end.shift(DOWN)
     a1, x1, a2, y1, eq1, a3, p1, x2, y2 = start.split()
     a4, x3, y3, eq2, a5, x4, p2, a6, y4 = np.array(end.split())[
         [3, 5, 6, 8, 12, 14, 16, 20, 22]
     ]
     start_copy = start.copy()
     self.play(Write(start_copy))
     self.wait()
     self.play(Transform(
         VMobject(a1, x1, a2, y1, eq1, a3, p1, x2, a3.copy(), y2),
         VMobject(a4, x3, a4.copy(), y3, eq2, a5, p2, x4, a6, y4)
     ))
     self.play(Write(end))
     self.clear()
     self.add(start_copy, end)
     self.wait()
     return start_copy, end
Exemple #13
0
 def write_old_style_rules(self):
     start = TexMobject("a^x a^y = a^{x+y}")
     end = TexMobject("\\log_a(xy) = \\log_a(x) + \\log_a(y)")
     start.shift(UP)
     end.shift(DOWN)
     a1, x1, a2, y1, eq1, a3, p1, x2, y2 = start.split()
     a4, x3, y3, eq2, a5, x4, p2, a6, y4 = np.array(end.split())[
         [3, 5, 6, 8, 12, 14, 16, 20, 22]
     ]
     start_copy = start.copy()
     self.play(Write(start_copy))
     self.dither()
     self.play(Transform(
         VMobject(a1, x1, a2, y1, eq1, a3, p1, x2, a3.copy(), y2),
         VMobject(a4, x3, a4.copy(), y3, eq2, a5, p2, x4, a6, y4)
     ))
     self.play(Write(end))
     self.clear()
     self.add(start_copy, end)
     self.dither()
     return start_copy, end
Exemple #14
0
    def construct(self):
        CycloidScene.construct(self)

        equation = TexMobject([
            "\\dfrac{\\sin(\\theta)}{\\sqrt{y}}",
            "= \\text{constant}"
        ])
        sin_sqrt, const = equation.split()
        new_eq = equation.copy()
        new_eq.to_edge(UP, buff = 1.3)
        cycloid_word = TextMobject("Cycloid")
        arrow = Arrow(2*UP, cycloid_word)
        arrow.reverse_points()
        q_mark = TextMobject("?")

        self.play(*map(ShimmerIn, equation.split()))
        self.dither()
        self.play(
            ApplyMethod(equation.shift, 2.2*UP),
            ShowCreation(arrow)
        )
        q_mark.next_to(sin_sqrt)
        self.play(ShimmerIn(cycloid_word))
        self.dither()
        self.grow_parts()
        self.draw_cycloid()
        self.dither()
        extra_terms = [const, arrow, cycloid_word]
        self.play(*[
            Transform(mob, q_mark)
            for mob in extra_terms
        ])
        self.remove(*extra_terms)
        self.roll_back()
        q_marks, arrows = self.get_q_marks_and_arrows(sin_sqrt)
        self.draw_cycloid(3, 
            ShowCreation(q_marks),
            ShowCreation(arrows)
        )
        self.dither()
Exemple #15
0
    def construct(self):
        CycloidScene.construct(self)

        equation = TexMobject([
            "\\dfrac{\\sin(\\theta)}{\\sqrt{y}}",
            "= \\text{constant}"
        ])
        sin_sqrt, const = equation.split()
        new_eq = equation.copy()
        new_eq.to_edge(UP, buff = 1.3)
        cycloid_word = TextMobject("Cycloid")
        arrow = Arrow(2*UP, cycloid_word)
        arrow.reverse_points()
        q_mark = TextMobject("?")

        self.play(*map(ShimmerIn, equation.split()))
        self.wait()
        self.play(
            ApplyMethod(equation.shift, 2.2*UP),
            ShowCreation(arrow)
        )
        q_mark.next_to(sin_sqrt)
        self.play(ShimmerIn(cycloid_word))
        self.wait()
        self.grow_parts()
        self.draw_cycloid()
        self.wait()
        extra_terms = [const, arrow, cycloid_word]
        self.play(*[
            Transform(mob, q_mark)
            for mob in extra_terms
        ])
        self.remove(*extra_terms)
        self.roll_back()
        q_marks, arrows = self.get_q_marks_and_arrows(sin_sqrt)
        self.draw_cycloid(3, 
            ShowCreation(q_marks),
            ShowCreation(arrows)
        )
        self.wait()
Exemple #16
0
    def construct(self):
        l_m1, l_m2, eq, r_m2, r_m1 = TexMobject(
            ["M_1", "M_2", "=", "M_2", "M_1"]).scale(1.5).split()
        VMobject(l_m1, r_m1).highlight(YELLOW)
        VMobject(l_m2, r_m2).highlight(PINK)
        q_marks = TextMobject("???")
        q_marks.highlight(TEAL)
        q_marks.next_to(eq, UP)
        neq = TexMobject("\\neq")
        neq.move_to(eq)

        self.play(*map(Write, [l_m1, l_m2, eq]))
        self.play(Transform(l_m1.copy(), r_m1),
                  Transform(l_m2.copy(), r_m2),
                  path_arc=-np.pi,
                  run_time=2)
        self.play(Write(q_marks))
        self.wait()
        self.play(
            Transform(VMobject(eq, q_marks),
                      VMobject(neq),
                      submobject_mode="lagged_start"))
        self.wait()
Exemple #17
0
    def show_layer_variables(self):
        layer_top_pairs = zip(
            self.layer_tops[:self.num_variables], 
            self.layer_tops[1:]
        )
        v_equations = []
        start_ys = []
        end_ys = []
        center_paths = []
        braces = []
        for (top1, top2), x in zip(layer_top_pairs, it.count(1)):
            eq_mob = TexMobject(
                ["v_%d"%x, "=", "\sqrt{\phantom{y_1}}"],
                size = "\\Large"
            )
            midpoint = UP*(top1+top2)/2
            eq_mob.shift(midpoint)
            v_eq = eq_mob.split()
            center_paths.append(Line(
                midpoint+SPACE_WIDTH*LEFT, 
                midpoint+SPACE_WIDTH*RIGHT
            ))            
            brace_endpoints = Mobject(
                Point(self.top*UP+x*RIGHT),
                Point(top2*UP+x*RIGHT)
            )
            brace = Brace(brace_endpoints, RIGHT)

            start_y = TexMobject("y_%d"%x, size = "\\Large")
            end_y = start_y.copy()            
            start_y.next_to(brace, RIGHT)
            end_y.shift(v_eq[-1].get_center())
            end_y.shift(0.2*RIGHT)

            v_equations.append(v_eq)
            start_ys.append(start_y)
            end_ys.append(end_y)
            braces.append(brace)

        for v_eq, path, time in zip(v_equations, center_paths, [2, 1, 0.5]):
            photon_run = self.photon_run_along_path(
                path,
                rate_func = None
            )
            self.play(
                ShimmerIn(v_eq[0]),
                photon_run,
                run_time = time
            )
        self.wait()
        for start_y, brace in zip(start_ys, braces):
            self.add(start_y)            
            self.play(GrowFromCenter(brace))
        self.wait()
        quads = zip(v_equations, start_ys, end_ys, braces)
        self.equations = []
        for v_eq, start_y, end_y, brace in quads:
            self.remove(brace)
            self.play(
                ShowCreation(v_eq[1]),
                ShowCreation(v_eq[2]),
                Transform(start_y, end_y)
            )

            v_eq.append(start_y)
            self.equations.append(Mobject(*v_eq))
Exemple #18
0
    def contrast_big_and_small_concavity(self):
        colors = color_gradient([GREEN, WHITE], 3)
        x0, y0 = 4, 2
        graphs = [
            self.get_graph(func, color = color)
            for color, func in zip(colors, [
                lambda x : 5*(x - x0)**2 + y0,
                lambda x : 0.2*(x - x0)**2 + y0,
                lambda x : (x-x0) + y0,
            ])
        ]
        arg_rhs_list = [
            TexMobject("(", str(x0), ")", "=", str(rhs))
            for rhs in 10, 0.4, 0
        ]
        for graph, arg_rhs in zip(graphs, arg_rhs_list):
            graph.ss_group = self.get_secant_slope_group(
                x0-1, graph, 
                dx = 0.001,
                secant_line_color = YELLOW
            )
            arg_rhs.move_to(self.second_deriv.get_center(), LEFT)
            graph.arg_rhs = arg_rhs
        graph = graphs[0]

        v_line = DashedLine(*[
            self.coords_to_point(x0, 0),
            self.coords_to_point(x0, y0),
        ])
        input_label = TexMobject(str(x0))
        input_label.next_to(v_line, DOWN)

        self.play(ShowCreation(graph, run_time = 2))
        self.play(
            Write(input_label),
            ShowCreation(v_line)
        )
        self.play(
            ReplacementTransform(
                input_label.copy(),
                graph.arg_rhs.get_part_by_tex(str(x0))
            ),
            self.second_deriv.next_to, graph.arg_rhs.copy(), LEFT, SMALL_BUFF,
            Write(VGroup(*[
                submob
                for submob in graph.arg_rhs
                if submob is not graph.arg_rhs.get_part_by_tex(str(x0))
            ]))
        )
        self.dither()
        self.play(FadeIn(graph.ss_group))
        self.animate_secant_slope_group_change(
            graph.ss_group, target_x = x0 + 1,
            run_time = 3,
        )
        self.play(FadeOut(graph.ss_group))
        self.dither()
        for new_graph in graphs[1:]:
            self.play(Transform(graph, new_graph))
            self.play(Transform(
                graph.arg_rhs,
                new_graph.arg_rhs,
            ))
            self.play(FadeIn(new_graph.ss_group))
            self.animate_secant_slope_group_change(
                new_graph.ss_group, target_x = x0 + 1,
                run_time = 3,
            )
            self.play(FadeOut(new_graph.ss_group))
Exemple #19
0
    def construct(self):

        title = TextMobject("Russellův paradox").to_edge(UP)
        self.add(title)

        set_inside = TextMobject("Množiny, které neobsahují samu sebe")
        set_rect = SurroundingRectangle(set_inside, buff = 0.8, color = RED) 
        self.play(FadeIn(set_inside), ShowCreation(set_rect))

        X_label = TexMobject('X').next_to(set_rect, UP, aligned_edge = LEFT)
        self.wait_to(5.5)
        self.play(Write(X_label))

        bubble_q = ChatBubble("Obsahuje $X$ samu sebe?", True)
        bubble_q.save_state()
        bubble_q.stretch_about_point(0,1,SPACE_HEIGHT*DOWN)
        bubble_q.highlight(BLACK)
        self.wait_to(7.5)
        self.play(ApplyMethod(bubble_q.restore, rate_func = rush_from))

        self.wait_to(13.5)

        bubble_a = ChatBubble("Že by neobsahuje?", False)
        bubble_a.save_state()
        bubble_a.stretch_about_point(0,1,SPACE_HEIGHT*DOWN)
        bubble_a.highlight(BLACK)
        self.play(ApplyMethod(bubble_a.restore, rate_func = rush_from))
        self.wait_to(17)

        X_label2 = X_label.copy()
        X_label2.shift(
            set_rect.get_corner(UP+RIGHT)
            - X_label2.get_corner(UP+RIGHT)
        )
        X_label2.shift(0.2*(DOWN+LEFT))

        X_label2.save_state()
        X_label2.shift(UP)
        X_label2.set_fill(opacity = 0)
        self.play(X_label2.restore)
        self.wait_to(25)

        self.play(FadeOut(bubble_a))

        bubble_a = ChatBubble("Tak obsahuje?", False)
        bubble_a.save_state()
        bubble_a.stretch_about_point(0,1,SPACE_HEIGHT*DOWN)
        bubble_a.highlight(BLACK)
        self.play(ApplyMethod(bubble_a.restore, rate_func = rush_from))
        self.wait_to(27.5)

        X_label2.save_state()
        X_label2.shift(UP)
        X_label2.set_fill(opacity = 0)
        self.play(MoveFromSaved(X_label2, remover = True))
        self.wait_to(61.5)

        self.play(FadeOut(VGroup(
            bubble_q, bubble_a, title, X_label,
            set_rect, set_inside,
        )))
Exemple #20
0
class Notation(Scene):
    def construct(self):
        self.introduce_notation()
        self.shift_to_good_and_back()
        self.shift_to_visuals()
        self.swipe_left()


    def introduce_notation(self):
        notation = TextMobject("Notation")
        notation.to_edge(UP)

        self.sum1 = TexMobject("\\sum_{n=1}^\\infty \\dfrac{1}{n}")
        self.prod1 = TexMobject("\\prod_{p\\text{ prime}}\\left(1-p^{-s}\\right)")
        self.trigs1 = TexMobject([
            ["\\sin", "(x)"],
            ["\\cos", "(x)"],
            ["\\tan", "(x)"],
        ], next_to_direction = DOWN)
        self.func1 = TexMobject("f(x) = y")
        symbols = [self.sum1, self.prod1, self.trigs1, self.func1]
        for sym, vect in zip(symbols, compass_directions(4, UP+LEFT)):
            sym.scale(0.5)
            vect[0] *= 2
            sym.shift(vect)
        self.symbols = VMobject(*symbols)

        self.play(Write(notation))
        self.play(Write(self.symbols))
        self.dither()
        self.add(notation, self.symbols)



    def shift_to_good_and_back(self):
        sum2 = self.sum1.copy()
        sigma = sum2.submobjects[1]
        plus = TexMobject("+").replace(sigma)
        sum2.submobjects[1] = plus

        prod2 = self.prod1.copy()
        pi = prod2.submobjects[0]
        times = TexMobject("\\times").replace(pi)
        prod2.submobjects[0] = times

        new_sin, new_cos, new_tan = [
            VMobject().set_anchor_points(
                corners, mode = "corners"
            ).replace(trig_part.split()[0])
            for corners, trig_part in zip(
                [
                    [RIGHT, RIGHT+UP, LEFT],
                    [RIGHT+UP, LEFT, RIGHT],
                    [RIGHT+UP, RIGHT, LEFT],
                ],
                self.trigs1.split()
            )
        ]
        x1, x2, x3 = [
            trig_part.split()[1]
            for trig_part in self.trigs1.split()
        ]
        trigs2 = VMobject(
            VMobject(new_sin, x1),
            VMobject(new_cos, x2),
            VMobject(new_tan, x3),
        )

        x, arrow, y = TexMobject("x \\rightarrow y").split()
        f = TexMobject("f")
        f.next_to(arrow, UP)
        func2 = VMobject(f, VMobject(), x, VMobject(), arrow, y)
        func2.scale(0.5)
        func2.shift(self.func1.get_center())

        good_symbols = VMobject(sum2, prod2, trigs2, func2)
        bad_symbols = self.symbols.copy()
        self.play(Transform(
            self.symbols, good_symbols, 
            path_arc = np.pi
        ))
        self.dither(3)
        self.play(Transform(
            self.symbols, bad_symbols,
            path_arc = np.pi
        ))
        self.dither()


    def shift_to_visuals(self):
        sigma, prod, trig, func = self.symbols.split()
        new_trig = trig.copy()        
        sin, cos, tan = [
            trig_part.split()[0]
            for trig_part in new_trig.split()
        ]
        trig_anim = TrigAnimation()
        sin.highlight(trig_anim.sin_color)
        cos.highlight(trig_anim.cos_color)
        tan.highlight(trig_anim.tan_color)
        new_trig.to_corner(UP+RIGHT)
        sum_lines = self.get_harmonic_sum_lines()

        self.play(
            Transform(trig, new_trig),
            *it.starmap(ApplyMethod, [
                (sigma.to_corner, UP+LEFT),
                (prod.shift, 15*LEFT),
                (func.shift, 5*UP),
            ])
        )
        sum_lines.next_to(sigma, DOWN)        
        self.remove(prod, func)
        self.play(
            trig_anim,
            Write(sum_lines)
        )
        self.play(trig_anim)
        self.dither()

    def get_harmonic_sum_lines(self):
        result = VMobject()
        for n in range(1, 8):
            big_line = NumberLine(
                x_min = 0,
                x_max = 1.01,
                tick_frequency = 1./n,
                numbers_with_elongated_ticks = [],
                color = WHITE
            )
            little_line = Line(
                big_line.number_to_point(0),
                big_line.number_to_point(1./n),
                color = RED
            )
            big_line.add(little_line)
            big_line.shift(0.5*n*DOWN)
            result.add(big_line)
        return result


    def swipe_left(self):
        everyone = VMobject(*self.mobjects)
        self.play(ApplyMethod(everyone.shift, 20*LEFT))
Exemple #21
0
    def construct(self):
        title = TextMobject("``Linearly dependent'' ")
        title.highlight(YELLOW)
        title.scale(2)
        title.to_edge(UP)
        self.add(title)

        equation1 = TexMobject([
            "\\vec{\\textbf{w}}",
            "=",
            "a",
            "\\vec{\\textbf{v}}",
        ])
        w, eq, a, v = equation1.split()
        w.highlight(BLUE)
        v.highlight(MAROON_C)
        equation1.scale(2)
        eq1_copy = equation1.copy()

        low_words1 = TextMobject("For some value of $a$")
        low_words1.scale(2)
        low_words1.to_edge(DOWN)
        arrow = Arrow(low_words1, a)
        arrow_copy = arrow.copy()

        equation2 = TexMobject([
            "\\vec{\\textbf{u}}",
            "=",
            "a",
            "\\vec{\\textbf{v}}",
            "+",
            "b",
            "\\vec{\\textbf{w}}",
        ])
        u, eq, a, v, plus, b, w = equation2.split()
        u.highlight(RED)
        w.highlight(BLUE)
        v.highlight(MAROON_C)
        equation2.scale(2)
        eq2_copy = equation2.copy()

        low_words2 = TextMobject("For some values of a and b")
        low_words2.scale(2)
        low_words2.to_edge(DOWN)
        arrows = VMobject(*[Arrow(low_words2, var) for var in a, b])

        self.play(Write(equation1))
        self.play(ShowCreation(arrow), Write(low_words1))
        self.wait()

        self.play(Transform(equation1, equation2),
                  Transform(low_words1, low_words2), Transform(arrow, arrows))
        self.wait(2)

        new_title = TextMobject("``Linearly independent'' ")
        new_title.highlight(GREEN)
        new_title.replace(title)

        for eq_copy in eq1_copy, eq2_copy:
            neq = TexMobject("\\neq")
            neq.replace(eq_copy.submobjects[1])
            eq_copy.submobjects[1] = neq

        new_low_words1 = TextMobject(["For", "all", "values of a"])
        new_low_words2 = TextMobject(["For", "all", "values of a and b"])
        for low_words in new_low_words1, new_low_words2:
            low_words.split()[1].highlight(GREEN)
            low_words.scale(2)
            low_words.to_edge(DOWN)

        self.play(Transform(title, new_title), Transform(equation1, eq1_copy),
                  Transform(arrow, arrow_copy),
                  Transform(low_words1, new_low_words1))
        self.wait()
        self.play(Transform(equation1, eq2_copy), Transform(arrow, arrows),
                  Transform(low_words1, new_low_words2))
        self.wait()
Exemple #22
0
    def show_layer_variables(self):
        layer_top_pairs = zip(
            self.layer_tops[:self.num_variables], 
            self.layer_tops[1:]
        )
        v_equations = []
        start_ys = []
        end_ys = []
        center_paths = []
        braces = []
        for (top1, top2), x in zip(layer_top_pairs, it.count(1)):
            eq_mob = TexMobject(
                ["v_%d"%x, "=", "\sqrt{\phantom{y_1}}"],
                size = "\\Large"
            )
            midpoint = UP*(top1+top2)/2
            eq_mob.shift(midpoint)
            v_eq = eq_mob.split()
            center_paths.append(Line(
                midpoint+SPACE_WIDTH*LEFT, 
                midpoint+SPACE_WIDTH*RIGHT
            ))            
            brace_endpoints = Mobject(
                Point(self.top*UP+x*RIGHT),
                Point(top2*UP+x*RIGHT)
            )
            brace = Brace(brace_endpoints, RIGHT)

            start_y = TexMobject("y_%d"%x, size = "\\Large")
            end_y = start_y.copy()            
            start_y.next_to(brace, RIGHT)
            end_y.shift(v_eq[-1].get_center())
            end_y.shift(0.2*RIGHT)

            v_equations.append(v_eq)
            start_ys.append(start_y)
            end_ys.append(end_y)
            braces.append(brace)

        for v_eq, path, time in zip(v_equations, center_paths, [2, 1, 0.5]):
            photon_run = self.photon_run_along_path(
                path,
                rate_func = None
            )
            self.play(
                ShimmerIn(v_eq[0]),
                photon_run,
                run_time = time
            )
        self.dither()
        for start_y, brace in zip(start_ys, braces):
            self.add(start_y)            
            self.play(GrowFromCenter(brace))
        self.dither()
        quads = zip(v_equations, start_ys, end_ys, braces)
        self.equations = []
        for v_eq, start_y, end_y, brace in quads:
            self.remove(brace)
            self.play(
                ShowCreation(v_eq[1]),
                ShowCreation(v_eq[2]),
                Transform(start_y, end_y)
            )

            v_eq.append(start_y)
            self.equations.append(Mobject(*v_eq))
Exemple #23
0
    def construct(self):
        self.add_layers()
        v_equations = []
        start_ys = []
        end_ys = []
        center_paths = []
        braces = []
        for layer, x in zip(self.layers[:3], it.count(1)):
            eq_mob = TexMobject(
                ["v_%d"%x, "=", "\sqrt{\phantom{y_1}}"],
                size = "\\Large"
            )
            eq_mob.shift(layer.get_center()+2*LEFT)
            v_eq = eq_mob.split()
            v_eq[0].highlight(layer.get_color())
            path = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT)
            path.shift(layer.get_center())
            brace_endpoints = Mobject(
                Point(self.top),
                Point(layer.get_bottom())
            )
            brace = Brace(brace_endpoints, RIGHT)
            brace.shift(x*RIGHT)

            start_y = TexMobject("y_%d"%x, size = "\\Large")
            end_y = start_y.copy()
            start_y.next_to(brace, RIGHT)
            end_y.shift(v_eq[-1].get_center())
            nudge = 0.2*RIGHT
            end_y.shift(nudge)

            v_equations.append(v_eq)
            start_ys.append(start_y)
            end_ys.append(end_y)
            center_paths.append(path)            
            braces.append(brace)

        for v_eq, path, time in zip(v_equations, center_paths, [2, 1, 0.5]):
            photon_run = self.photon_run_along_path(
                path,
                rate_func = None
            )
            self.play(
                FadeToColor(v_eq[0], WHITE),
                photon_run,
                run_time = time
            )
        self.dither()

        starts = [0, 0.3, 0.6]
        self.play(*it.chain(*[
            [
                GrowFromCenter(
                    mob,
                    rate_func=squish_rate_func(smooth, start, 1)
                )
                for mob, start in zip(mobs, starts)
            ]
            for mobs in start_ys, braces
        ]))
        self.dither()

        triplets = zip(v_equations, start_ys, end_ys)
        anims = []
        for v_eq, start_y, end_y in triplets:
            anims += [
                ShowCreation(v_eq[1]),
                ShowCreation(v_eq[2]),
                Transform(start_y.copy(), end_y)
            ]
        self.play(*anims)
        self.dither()
Exemple #24
0
    def construct(self):

        title = TextMobject("Russell's paradox").to_edge(UP)
        self.add(title)

        set_inside = TextMobject("Sets that does not contain themselves")
        set_rect = SurroundingRectangle(set_inside, buff=0.8, color=RED)
        self.play(FadeIn(set_inside), ShowCreation(set_rect))

        X_label = TexMobject('X').next_to(set_rect, UP, aligned_edge=LEFT)
        #self.wait_to(5.5)
        self.play(Write(X_label))

        bubble_q = ChatBubble("Does $X$ contain itself?", True)
        bubble_q.save_state()
        bubble_q.stretch_about_point(0, 1, SPACE_HEIGHT * DOWN)
        bubble_q.highlight(BLACK)
        #self.wait_to(7.5)
        self.play(ApplyMethod(bubble_q.restore, rate_func=rush_from))

        self.dither(2)
        #self.wait_to(13.5)

        bubble_a = ChatBubble("No?", False)
        bubble_a.save_state()
        bubble_a.stretch_about_point(0, 1, SPACE_HEIGHT * DOWN)
        bubble_a.highlight(BLACK)
        self.play(ApplyMethod(bubble_a.restore, rate_func=rush_from))
        #self.wait_to(17)

        X_label2 = X_label.copy()
        X_label2.shift(
            set_rect.get_corner(UP + RIGHT) - X_label2.get_corner(UP + RIGHT))
        X_label2.shift(0.2 * (DOWN + LEFT))

        X_label2.save_state()
        X_label2.shift(UP)
        X_label2.set_fill(opacity=0)
        self.play(X_label2.restore)
        #self.wait_to(25)

        self.dither(2)
        self.play(FadeOut(bubble_a))

        bubble_a = ChatBubble("Or yes...", False)
        bubble_a.save_state()
        bubble_a.stretch_about_point(0, 1, SPACE_HEIGHT * DOWN)
        bubble_a.highlight(BLACK)
        self.play(ApplyMethod(bubble_a.restore, rate_func=rush_from))
        #self.wait_to(27.5)

        X_label2.save_state()
        X_label2.shift(UP)
        X_label2.set_fill(opacity=0)
        self.play(MoveFromSaved(X_label2, remover=True))
        #self.wait_to(61.5)

        self.dither(2)
        self.play(
            FadeOut(
                VGroup(
                    bubble_q,
                    bubble_a,
                    title,
                    X_label,
                    set_rect,
                    set_inside,
                )))
Exemple #25
0
    def solveEquation(self):
        leftBrace = TexMobject("[")
        rightBrace = TexMobject("]")
        xBraces = Group(leftBrace, rightBrace)
        xBraces.stretch(2, 0)

        downBrace = TexMobject("[")
        upBrace = TexMobject("]")
        yBraces = Group(downBrace, upBrace)
        yBraces.stretch(2, 0)
        yBraces.rotate(TAU / 4)

        lowerX = self.initial_lower_x
        lowerY = self.func(lowerX)
        upperX = self.initial_upper_x
        upperY = self.func(upperX)

        leftBrace.move_to(self.coords_to_point(lowerX, 0), aligned_edge=LEFT)
        leftBraceLabel = DecimalNumber(lowerX)
        leftBraceLabel.next_to(leftBrace, DOWN + LEFT, buff=SMALL_BUFF)
        leftBraceLabelAnimation = ContinualChangingDecimal(
            leftBraceLabel,
            lambda alpha: self.point_to_coords(leftBrace.get_center())[0],
            tracked_mobject=leftBrace)
        self.add(leftBraceLabelAnimation)

        rightBrace.move_to(self.coords_to_point(upperX, 0), aligned_edge=RIGHT)
        rightBraceLabel = DecimalNumber(upperX)
        rightBraceLabel.next_to(rightBrace, DOWN + RIGHT, buff=SMALL_BUFF)
        rightBraceLabelAnimation = ContinualChangingDecimal(
            rightBraceLabel,
            lambda alpha: self.point_to_coords(rightBrace.get_center())[0],
            tracked_mobject=rightBrace)
        self.add(rightBraceLabelAnimation)

        downBrace.move_to(self.coords_to_point(0, lowerY), aligned_edge=DOWN)
        downBraceLabel = DecimalNumber(lowerY)
        downBraceLabel.next_to(downBrace, LEFT + DOWN, buff=SMALL_BUFF)
        downBraceLabelAnimation = ContinualChangingDecimal(
            downBraceLabel,
            lambda alpha: self.point_to_coords(downBrace.get_center())[1],
            tracked_mobject=downBrace)
        self.add(downBraceLabelAnimation)

        upBrace.move_to(self.coords_to_point(0, upperY), aligned_edge=UP)
        upBraceLabel = DecimalNumber(upperY)
        upBraceLabel.next_to(upBrace, LEFT + UP, buff=SMALL_BUFF)
        upBraceLabelAnimation = ContinualChangingDecimal(
            upBraceLabel,
            lambda alpha: self.point_to_coords(upBrace.get_center())[1],
            tracked_mobject=upBrace)
        self.add(upBraceLabelAnimation)

        lowerDotPoint = self.input_to_graph_point(lowerX, self.graph)
        lowerDotXPoint = self.coords_to_point(lowerX, 0)
        lowerDotYPoint = self.coords_to_point(0, self.func(lowerX))
        lowerDot = Dot(lowerDotPoint)
        upperDotPoint = self.input_to_graph_point(upperX, self.graph)
        upperDot = Dot(upperDotPoint)
        upperDotXPoint = self.coords_to_point(upperX, 0)
        upperDotYPoint = self.coords_to_point(0, self.func(upperX))

        lowerXLine = Line(lowerDotXPoint,
                          lowerDotPoint,
                          stroke_width=1,
                          color=YELLOW)
        upperXLine = Line(upperDotXPoint,
                          upperDotPoint,
                          stroke_width=1,
                          color=YELLOW)
        lowerYLine = Line(lowerDotYPoint,
                          lowerDotPoint,
                          stroke_width=1,
                          color=YELLOW)
        upperYLine = Line(upperDotYPoint,
                          upperDotPoint,
                          stroke_width=1,
                          color=YELLOW)
        self.add(lowerXLine, upperXLine, lowerYLine, upperYLine)

        self.add(xBraces, yBraces, lowerDot, upperDot)

        for i in range(self.num_iterations):
            if i == self.iteration_at_which_to_start_zoom:
                self.activate_zooming()
                self.little_rectangle.move_to(
                    self.coords_to_point(self.targetX, self.targetY))
                inverseZoomFactor = 1 / float(self.zoom_factor)
                self.play(lowerDot.scale_in_place, inverseZoomFactor,
                          upperDot.scale_in_place, inverseZoomFactor)

            def makeUpdater(xAtStart):
                def updater(group, alpha):
                    dot, xBrace, yBrace, xLine, yLine = group
                    newX = interpolate(xAtStart, midX, alpha)
                    newY = self.func(newX)
                    graphPoint = self.input_to_graph_point(newX, self.graph)
                    dot.move_to(graphPoint)
                    xAxisPoint = self.coords_to_point(newX, 0)
                    xBrace.move_to(xAxisPoint)
                    yAxisPoint = self.coords_to_point(0, newY)
                    yBrace.move_to(yAxisPoint)
                    xLine.put_start_and_end_on(xAxisPoint, graphPoint)
                    yLine.put_start_and_end_on(yAxisPoint, graphPoint)
                    return group

                return updater

            midX = (lowerX + upperX) / float(2)
            midY = self.func(midX)

            midCoords = self.coords_to_point(midX, midY)
            midColor = RED
            midXPoint = Dot(self.coords_to_point(midX, 0), color=midColor)
            self.play(ReplacementTransform(leftBrace.copy(), midXPoint),
                      ReplacementTransform(rightBrace.copy(), midXPoint))
            midXLine = Line(self.coords_to_point(midX, 0),
                            midCoords,
                            color=midColor)
            self.play(ShowCreation(midXLine))
            midDot = Dot(midCoords, color=midColor)
            if (self.iteration_at_which_to_start_zoom != None
                    and i >= self.iteration_at_which_to_start_zoom):
                midDot.scale_in_place(inverseZoomFactor)
            self.add(midDot)
            midYLine = Line(midCoords,
                            self.coords_to_point(0, midY),
                            color=midColor)
            self.play(ShowCreation(midYLine))

            if midY < self.targetY:
                movingGroup = Group(lowerDot, leftBrace, downBrace, lowerXLine,
                                    lowerYLine)
                self.play(UpdateFromAlphaFunc(movingGroup,
                                              makeUpdater(lowerX)))
                lowerX = midX
                lowerY = midY

            else:
                movingGroup = Group(upperDot, rightBrace, upBrace, upperXLine,
                                    upperYLine)
                self.play(UpdateFromAlphaFunc(movingGroup,
                                              makeUpdater(upperX)))
                upperX = midX
                upperY = midY
            self.remove(midXLine, midDot, midYLine)

        self.wait()
Exemple #26
0
    def construct(self):
        title = TextMobject("``Linearly dependent'' ")
        title.highlight(YELLOW)
        title.scale(2)
        title.to_edge(UP)
        self.add(title)

        equation1 = TexMobject([
            "\\vec{\\textbf{w}}",
            "=",
            "a",
            "\\vec{\\textbf{v}}",
        ])
        w, eq, a, v = equation1.split()
        w.highlight(BLUE)
        v.highlight(MAROON_C)
        equation1.scale(2)
        eq1_copy = equation1.copy()

        low_words1 = TextMobject("For some value of $a$")
        low_words1.scale(2)
        low_words1.to_edge(DOWN)
        arrow = Arrow(low_words1, a)
        arrow_copy = arrow.copy()

        equation2 = TexMobject([
            "\\vec{\\textbf{u}}",
            "=",
            "a",
            "\\vec{\\textbf{v}}",
            "+",
            "b",
            "\\vec{\\textbf{w}}",
        ])
        u, eq, a, v, plus, b, w = equation2.split()
        u.highlight(RED)
        w.highlight(BLUE)
        v.highlight(MAROON_C)
        equation2.scale(2)
        eq2_copy = equation2.copy()

        low_words2 = TextMobject("For some values of a and b")
        low_words2.scale(2)
        low_words2.to_edge(DOWN)
        arrows = VMobject(*[
            Arrow(low_words2, var)
            for var in a, b
        ])

        self.play(Write(equation1))
        self.play(
            ShowCreation(arrow),
            Write(low_words1)
        )
        self.dither()

        self.play(
            Transform(equation1, equation2),
            Transform(low_words1, low_words2),
            Transform(arrow, arrows)
        )
        self.dither(2)

        new_title = TextMobject("``Linearly independent'' ")
        new_title.highlight(GREEN)
        new_title.replace(title)

        for eq_copy in eq1_copy, eq2_copy:
            neq = TexMobject("\\neq")
            neq.replace(eq_copy.submobjects[1])
            eq_copy.submobjects[1] = neq

        new_low_words1 = TextMobject(["For", "all", "values of a"])
        new_low_words2 = TextMobject(["For", "all", "values of a and b"])
        for low_words in new_low_words1, new_low_words2:
            low_words.split()[1].highlight(GREEN)
            low_words.scale(2)
            low_words.to_edge(DOWN)

        self.play(
            Transform(title, new_title),
            Transform(equation1, eq1_copy),
            Transform(arrow, arrow_copy),
            Transform(low_words1, new_low_words1)
        )
        self.dither()
        self.play(
            Transform(equation1, eq2_copy),
            Transform(arrow, arrows),
            Transform(low_words1, new_low_words2)
        )
        self.dither()
Exemple #27
0
    def contrast_big_and_small_concavity(self):
        colors = color_gradient([GREEN, WHITE], 3)
        x0, y0 = 4, 2
        graphs = [
            self.get_graph(func, color = color)
            for color, func in zip(colors, [
                lambda x : 5*(x - x0)**2 + y0,
                lambda x : 0.2*(x - x0)**2 + y0,
                lambda x : (x-x0) + y0,
            ])
        ]
        arg_rhs_list = [
            TexMobject("(", str(x0), ")", "=", str(rhs))
            for rhs in 10, 0.4, 0
        ]
        for graph, arg_rhs in zip(graphs, arg_rhs_list):
            graph.ss_group = self.get_secant_slope_group(
                x0-1, graph, 
                dx = 0.001,
                secant_line_color = YELLOW
            )
            arg_rhs.move_to(self.second_deriv.get_center(), LEFT)
            graph.arg_rhs = arg_rhs
        graph = graphs[0]

        v_line = DashedLine(*[
            self.coords_to_point(x0, 0),
            self.coords_to_point(x0, y0),
        ])
        input_label = TexMobject(str(x0))
        input_label.next_to(v_line, DOWN)

        self.play(ShowCreation(graph, run_time = 2))
        self.play(
            Write(input_label),
            ShowCreation(v_line)
        )
        self.play(
            ReplacementTransform(
                input_label.copy(),
                graph.arg_rhs.get_part_by_tex(str(x0))
            ),
            self.second_deriv.next_to, graph.arg_rhs.copy(), LEFT, SMALL_BUFF,
            Write(VGroup(*[
                submob
                for submob in graph.arg_rhs
                if submob is not graph.arg_rhs.get_part_by_tex(str(x0))
            ]))
        )
        self.wait()
        self.play(FadeIn(graph.ss_group))
        self.animate_secant_slope_group_change(
            graph.ss_group, target_x = x0 + 1,
            run_time = 3,
        )
        self.play(FadeOut(graph.ss_group))
        self.wait()
        for new_graph in graphs[1:]:
            self.play(Transform(graph, new_graph))
            self.play(Transform(
                graph.arg_rhs,
                new_graph.arg_rhs,
            ))
            self.play(FadeIn(new_graph.ss_group))
            self.animate_secant_slope_group_change(
                new_graph.ss_group, target_x = x0 + 1,
                run_time = 3,
            )
            self.play(FadeOut(new_graph.ss_group))
Exemple #28
0
class Notation(Scene):
    def construct(self):
        self.introduce_notation()
        self.shift_to_good_and_back()
        self.shift_to_visuals()
        self.swipe_left()

    def introduce_notation(self):
        notation = TextMobject("Notation")
        notation.to_edge(UP)

        self.sum1 = TexMobject("\\sum_{n=1}^\\infty \\dfrac{1}{n}")
        self.prod1 = TexMobject(
            "\\prod_{p\\text{ prime}}\\left(1-p^{-s}\\right)")
        self.trigs1 = TexMobject([
            ["\\sin", "(x)"],
            ["\\cos", "(x)"],
            ["\\tan", "(x)"],
        ],
                                 next_to_direction=DOWN)
        self.func1 = TexMobject("f(x) = y")
        symbols = [self.sum1, self.prod1, self.trigs1, self.func1]
        for sym, vect in zip(symbols, compass_directions(4, UP + LEFT)):
            sym.scale(0.5)
            vect[0] *= 2
            sym.shift(vect)
        self.symbols = VMobject(*symbols)

        self.play(Write(notation))
        self.play(Write(self.symbols))
        self.wait()
        self.add(notation, self.symbols)

    def shift_to_good_and_back(self):
        sum2 = self.sum1.copy()
        sigma = sum2.submobjects[1]
        plus = TexMobject("+").replace(sigma)
        sum2.submobjects[1] = plus

        prod2 = self.prod1.copy()
        pi = prod2.submobjects[0]
        times = TexMobject("\\times").replace(pi)
        prod2.submobjects[0] = times

        new_sin, new_cos, new_tan = [
            VMobject().set_anchor_points(corners, mode="corners").replace(
                trig_part.split()[0]) for corners, trig_part in zip([
                    [RIGHT, RIGHT + UP, LEFT],
                    [RIGHT + UP, LEFT, RIGHT],
                    [RIGHT + UP, RIGHT, LEFT],
                ], self.trigs1.split())
        ]
        x1, x2, x3 = [
            trig_part.split()[1] for trig_part in self.trigs1.split()
        ]
        trigs2 = VMobject(
            VMobject(new_sin, x1),
            VMobject(new_cos, x2),
            VMobject(new_tan, x3),
        )

        x, arrow, y = TexMobject("x \\rightarrow y").split()
        f = TexMobject("f")
        f.next_to(arrow, UP)
        func2 = VMobject(f, VMobject(), x, VMobject(), arrow, y)
        func2.scale(0.5)
        func2.shift(self.func1.get_center())

        good_symbols = VMobject(sum2, prod2, trigs2, func2)
        bad_symbols = self.symbols.copy()
        self.play(Transform(self.symbols, good_symbols, path_arc=np.pi))
        self.wait(3)
        self.play(Transform(self.symbols, bad_symbols, path_arc=np.pi))
        self.wait()

    def shift_to_visuals(self):
        sigma, prod, trig, func = self.symbols.split()
        new_trig = trig.copy()
        sin, cos, tan = [
            trig_part.split()[0] for trig_part in new_trig.split()
        ]
        trig_anim = TrigAnimation()
        sin.highlight(trig_anim.sin_color)
        cos.highlight(trig_anim.cos_color)
        tan.highlight(trig_anim.tan_color)
        new_trig.to_corner(UP + RIGHT)
        sum_lines = self.get_harmonic_sum_lines()

        self.play(
            Transform(trig, new_trig),
            *it.starmap(ApplyMethod, [
                (sigma.to_corner, UP + LEFT),
                (prod.shift, 15 * LEFT),
                (func.shift, 5 * UP),
            ]))
        sum_lines.next_to(sigma, DOWN)
        self.remove(prod, func)
        self.play(trig_anim, Write(sum_lines))
        self.play(trig_anim)
        self.wait()

    def get_harmonic_sum_lines(self):
        result = VMobject()
        for n in range(1, 8):
            big_line = NumberLine(x_min=0,
                                  x_max=1.01,
                                  tick_frequency=1. / n,
                                  numbers_with_elongated_ticks=[],
                                  color=WHITE)
            little_line = Line(big_line.number_to_point(0),
                               big_line.number_to_point(1. / n),
                               color=RED)
            big_line.add(little_line)
            big_line.shift(0.5 * n * DOWN)
            result.add(big_line)
        return result

    def swipe_left(self):
        everyone = VMobject(*self.mobjects)
        self.play(ApplyMethod(everyone.shift, 20 * LEFT))
Exemple #29
0
    def show_equation(self):
        equation = TexMobject([
            "\\left(\\dfrac{1}{\\phantom{v_air}}\\right)",
            "\\sin(\\theta_1)", 
            "=", 
            "\\left(\\dfrac{1}{\\phantom{v_water}}\\right)",
            "\\sin(\\theta_2)"
        ])
        equation.to_corner(UP+RIGHT)
        frac1, sin1, equals, frac2, sin2 = equation.split()
        v_air, v_water = [
            TexMobject("v_{\\text{%s}}"%s, size = "\\Large")
            for s in "air", "water"
        ]
        v_air.next_to(Point(frac1.get_center()), DOWN)
        v_water.next_to(Point(frac2.get_center()), DOWN)
        frac1.add(v_air)
        frac2.add(v_water)
        f1, f2 = [
            TexMobject("F_%d"%d, size = "\\Large") 
            for d in 1, 2
        ]
        f1.next_to(sin1, LEFT)
        f2.next_to(equals, RIGHT)
        sin2_start = sin2.copy().next_to(f2, RIGHT)
        bar1 = TexMobject("\\dfrac{\\qquad}{\\qquad}")
        bar2 = bar1.copy()
        bar1.next_to(sin1, DOWN)
        bar2.next_to(sin2, DOWN)        
        v_air_copy = v_air.copy().next_to(bar1, DOWN)
        v_water_copy = v_water.copy().next_to(bar2, DOWN)
        bars = Mobject(bar1, bar2)
        new_eq = equals.copy().center().shift(bars.get_center())
        snells = TextMobject("Snell's Law")
        snells.highlight(YELLOW)
        snells.shift(new_eq.get_center()[0]*RIGHT)
        snells.shift(UP)

        anims = []
        for mob in f1, sin1, equals, f2, sin2_start:
            anims.append(ShimmerIn(mob))
        self.play(*anims)
        self.wait()
        for f, frac in (f1, frac1), (f2, frac2):
            target = frac.copy().ingest_submobjects()
            also = []
            if f is f2:
                also.append(Transform(sin2_start, sin2))
                sin2 = sin2_start
            self.play(Transform(f, target), *also)
            self.remove(f)
            self.add(frac)
        self.wait()
        self.play(
            FadeOut(frac1),
            FadeOut(frac2),
            Transform(v_air, v_air_copy),
            Transform(v_water, v_water_copy),
            ShowCreation(bars),
            Transform(equals, new_eq)
        )
        self.wait()
        frac1 = Mobject(sin1, bar1, v_air)
        frac2 = Mobject(sin2, bar2, v_water)
        for frac, vect in (frac1, LEFT), (frac2, RIGHT):
            self.play(ApplyMethod(
                frac.next_to, equals, vect
            ))
        self.wait()
        self.play(ShimmerIn(snells))
        self.wait()
Exemple #30
0
    def construct(self):

        pws_col = BLUE

        h = 1.4 * SPACE_HEIGHT
        w1 = 1
        w2 = 1.6 * SPACE_WIDTH
        set_A = Rectangle(width=w1, height=h).to_edge(LEFT).highlight(YELLOW)
        set_PA = Rectangle(width=w2,
                           height=h).to_edge(RIGHT).highlight(pws_col)
        set_A_label = TexMobject('A').highlight(YELLOW).to_corner(UP + LEFT)
        set_PA_label = TexMobject('\\mathcal P(A)').highlight(
            pws_col).to_corner(UP + RIGHT)

        dots_num = 10
        p0 = set_A.get_edge_center(UP) + set_A.get_width() / 2 * DOWN
        p1 = set_A.get_edge_center(DOWN) + set_A.get_width() / 2 * UP
        vdots = VGroup([
            Dot(interpolate(p0, p1, alpha))
            for alpha in np.linspace(0, 1, dots_num)
        ])

        subset = Rectangle(width=w2 - 1, height=0.7).move_to(set_PA)
        subset.save_state()
        p0 = subset.get_edge_center(LEFT) + RIGHT
        p1 = subset.get_edge_center(RIGHT) + LEFT
        hdots = VGroup([
            Dot(interpolate(p0, p1, alpha))
            for alpha in np.linspace(0, 1, dots_num)
        ])

        for i, dot in enumerate(vdots):
            dot.index = i
            dot.set_color(random.choice([RED, GREEN]))

        green_dots = filter(lambda dot: dot.color == Color(GREEN), vdots)
        red_dots = filter(lambda dot: dot.color == Color(RED), vdots)

        self.add(set_A, set_PA, set_A_label, set_PA_label)

        dots_to_show = VGroup(vdots.submobjects)

        cur_dot = green_dots[2]
        dots_to_show.remove(cur_dot)
        subset.move_to(cur_dot, coor_mask=Y_MASK)
        x_var = TexMobject('x').move_to(cur_dot)
        line = Line(x_var, subset, buff=0.2)

        #self.wait_to(6)
        self.play(GrowFromCenter(x_var))
        #self.wait_to(9)
        self.play(ShowCreation(line), FadeIn(subset))

        x_inside = x_var.copy().move_to(hdots[cur_dot.index])
        x_inside.move_to(subset, coor_mask=Y_MASK)
        x_inside.save_state()
        x_inside.shift(UP)
        x_inside.set_fill(opacity=0)
        #self.wait_to(11)
        self.play(x_inside.restore)
        #self.wait_to(14)
        self.dither()
        self.play(FadeOut(VGroup(line, subset, x_inside)))
        self.play(ReplacementTransform(x_var, cur_dot))

        cur_dot = red_dots[2]
        dots_to_show.remove(cur_dot)
        subset.move_to(cur_dot, coor_mask=Y_MASK)
        x_var = TexMobject('x').move_to(cur_dot)
        line = Line(x_var, subset, buff=0.2)

        self.play(GrowFromCenter(x_var))
        self.play(ShowCreation(line), FadeIn(subset))

        x_inside = x_var.copy().move_to(hdots[cur_dot.index])
        x_inside.move_to(subset, coor_mask=Y_MASK)
        x_inside.shift(UP)
        x_inside.save_state()
        x_inside.shift(DOWN)
        x_inside.set_fill(opacity=0)
        self.play(x_inside.restore)
        #self.wait_to(20)
        self.dither()
        self.play(FadeOut(VGroup(line, subset, x_inside)))
        self.play(ReplacementTransform(x_var, cur_dot))

        self.play(ShowCreation(dots_to_show))

        subset.restore()

        red_hdots = VGroup([hdots[dot.index]
                            for dot in red_dots]).highlight(RED)
        #self.wait_to(24)
        self.dither()
        self.play(
            ReplacementTransform(VGroup(list(red_dots)).copy(), red_hdots), )
        self.play(ShowCreation(subset))
        #self.wait_to(32.5)

        subset_g = VGroup(subset, hdots)
        visible_g = VGroup(subset, red_hdots)

        cur_dot = green_dots[2]
        visible_g.save_state()
        subset_g.move_to(cur_dot, coor_mask=Y_MASK)
        line = Line(cur_dot, subset, buff=0.2)
        self.play(
            MoveFromSaved(visible_g),
            ShowCreation(line),
        )
        cur_hdot = hdots[cur_dot.index]
        cur_hdot.highlight(GREEN)
        self.dither()
        self.add(cur_hdot)
        self.dither(0.3)
        self.remove(cur_hdot)
        self.dither(0.2)
        self.add(cur_hdot)
        self.dither()
        self.remove(cur_hdot)

        ori_line = line
        cur_dot = red_dots[2]
        visible_g.save_state()
        subset_g.move_to(cur_dot, coor_mask=Y_MASK)
        line = Line(cur_dot, subset, buff=0.2)
        #self.wait_to(36)
        self.dither(2)
        self.play(
            FadeOut(ori_line),
            MoveFromSaved(visible_g),
            ShowCreation(line),
        )

        cur_hdot = hdots[cur_dot.index]
        cur_hdot.highlight(YELLOW)
        self.dither(0.3)
        cur_hdot.highlight(RED)
        self.dither(0.2)
        cur_hdot.highlight(YELLOW)
        self.dither()
        #self.wait_to(39.5)

        cur_hdot.highlight(RED)
        visible_g.save_state()
        subset_g.move_to(ORIGIN, coor_mask=Y_MASK)

        self.play(FadeOut(line), MoveFromSaved(visible_g))
        #self.wait_to(53.7)

        cur_dot = vdots[-3]
        subset2 = subset.copy().move_to(cur_dot, coor_mask=Y_MASK)
        line = Line(cur_dot, subset2, buff=0.2)

        self.play(ShowCreation(line))
        self.dither()
        #self.wait_to(57)
        self.play(Uncreate(line))
        #self.wait_to(59.5)
        self.play(ReplacementTransform(cur_dot.copy(), subset2))

        #self.wait_to(60+11)
        title = TextMobject("Russell's paradox").next_to(subset, UP)
        self.play(FadeIn(title, submobject_mode="lagged_start"))
        #self.wait_to(60+20)
        self.dither(2)

        title.save_state()
        title.center()
        title.to_edge(UP)
        self.play(
            FadeOut(
                VGroup(
                    set_A,
                    set_A_label,
                    set_PA,
                    set_PA_label,
                    vdots,
                    visible_g,
                    subset2,
                )),
            MoveFromSaved(title),
        )
Exemple #31
0
    def house_example(self, starter_mobject, title):
        house = SVGMobject("house")
        house.set_stroke(width = 0)
        house.set_fill(BLUE_C, opacity = 1)
        house.scale_to_fit_height(3)
        house.center()
        square_footage_words = TextMobject("Square footage:")
        price_words = TextMobject("Price: ")
        square_footage = TexMobject("2{,}600\\text{ ft}^2")
        price = TextMobject("\\$300{,}000")

        house.to_edge(LEFT).shift(UP)
        square_footage_words.next_to(house, RIGHT)
        square_footage_words.shift(0.5*UP)
        square_footage_words.highlight(RED)
        price_words.next_to(square_footage_words, DOWN, aligned_edge = LEFT)
        price_words.highlight(GREEN)
        square_footage.next_to(square_footage_words)
        square_footage.highlight(RED)
        price.next_to(price_words)
        price.highlight(GREEN)

        vector = Matrix([square_footage.copy(), price.copy()])
        vector.next_to(house, RIGHT).shift(0.25*UP)
        new_square_footage, new_price = vector.get_mob_matrix().flatten()
        not_equals = TexMobject("\\ne")
        not_equals.next_to(vector)
        alt_vector = Matrix([
            TextMobject("300{,}000\\text{ ft}^2").highlight(RED),
            TextMobject("\\$2{,}600").highlight(GREEN)
        ])
        alt_vector.next_to(not_equals)

        brace = Brace(vector, RIGHT)
        two_dimensional = TextMobject("2 dimensional")
        two_dimensional.next_to(brace)
        brackets = vector.get_brackets()

        self.play(Transform(starter_mobject, house))
        self.remove(starter_mobject)
        self.add(house)
        self.add(square_footage_words)
        self.play(Write(square_footage, run_time = 2))
        self.add(price_words)
        self.play(Write(price, run_time = 2))
        self.dither()
        self.play(
            FadeOut(square_footage_words), FadeOut(price_words),
            Transform(square_footage, new_square_footage),
            Transform(price, new_price),
            Write(brackets),
            run_time = 1
        )
        self.remove(square_footage_words, price_words)
        self.dither()
        self.play(
            Write(not_equals),
            Write(alt_vector),
            run_time = 1
        )
        self.dither()
        self.play(FadeOut(not_equals), FadeOut(alt_vector))
        self.remove(not_equals, alt_vector)
        self.dither()
        self.play(
            GrowFromCenter(brace),
            Write(two_dimensional),
            run_time = 1
        )
        self.dither()

        everything = VMobject(
            house, square_footage, price, brackets, brace, 
            two_dimensional, title
        )
        self.play(ApplyMethod(everything.shift, 2*SPACE_WIDTH*LEFT))
        self.remove(everything)
Exemple #32
0
    def house_example(self, starter_mobject, title):
        house = SVGMobject("house")
        house.set_stroke(width=0)
        house.set_fill(BLUE_C, opacity=1)
        house.scale_to_fit_height(3)
        house.center()
        square_footage_words = TextMobject("Square footage:")
        price_words = TextMobject("Price: ")
        square_footage = TexMobject("2{,}600\\text{ ft}^2")
        price = TextMobject("\\$300{,}000")

        house.to_edge(LEFT).shift(UP)
        square_footage_words.next_to(house, RIGHT)
        square_footage_words.shift(0.5 * UP)
        square_footage_words.highlight(RED)
        price_words.next_to(square_footage_words, DOWN, aligned_edge=LEFT)
        price_words.highlight(GREEN)
        square_footage.next_to(square_footage_words)
        square_footage.highlight(RED)
        price.next_to(price_words)
        price.highlight(GREEN)

        vector = Matrix([square_footage.copy(), price.copy()])
        vector.next_to(house, RIGHT).shift(0.25 * UP)
        new_square_footage, new_price = vector.get_mob_matrix().flatten()
        not_equals = TexMobject("\\ne")
        not_equals.next_to(vector)
        alt_vector = Matrix([
            TextMobject("300{,}000\\text{ ft}^2").highlight(RED),
            TextMobject("\\$2{,}600").highlight(GREEN)
        ])
        alt_vector.next_to(not_equals)

        brace = Brace(vector, RIGHT)
        two_dimensional = TextMobject("2 dimensional")
        two_dimensional.next_to(brace)
        brackets = vector.get_brackets()

        self.play(Transform(starter_mobject, house))
        self.remove(starter_mobject)
        self.add(house)
        self.add(square_footage_words)
        self.play(Write(square_footage, run_time=2))
        self.add(price_words)
        self.play(Write(price, run_time=2))
        self.dither()
        self.play(FadeOut(square_footage_words),
                  FadeOut(price_words),
                  Transform(square_footage, new_square_footage),
                  Transform(price, new_price),
                  Write(brackets),
                  run_time=1)
        self.remove(square_footage_words, price_words)
        self.dither()
        self.play(Write(not_equals), Write(alt_vector), run_time=1)
        self.dither()
        self.play(FadeOut(not_equals), FadeOut(alt_vector))
        self.remove(not_equals, alt_vector)
        self.dither()
        self.play(GrowFromCenter(brace), Write(two_dimensional), run_time=1)
        self.dither()

        everything = VMobject(house, square_footage, price, brackets, brace,
                              two_dimensional, title)
        self.play(ApplyMethod(everything.shift, 2 * SPACE_WIDTH * LEFT))
        self.remove(everything)
Exemple #33
0
    def work_out_square_algebraically(self):
        rect = Rectangle(height=3.5,
                         width=6.5,
                         stroke_width=0,
                         fill_color=BLACK,
                         fill_opacity=0.8)
        rect.to_corner(UP + LEFT, buff=0)
        top_line = TexMobject("(2+i)", "(2+i)")
        top_line.next_to(rect.get_top(), DOWN)
        second_line = TexMobject("2^2 + 2i + 2i + i^2")
        second_line.next_to(top_line, DOWN, MED_LARGE_BUFF)
        final_line = TexMobject("3 + 4i")
        final_line.next_to(second_line, DOWN, MED_LARGE_BUFF)

        result_dot = Dot(self.plane.coords_to_point(3, 4),
                         color=MAROON_B,
                         radius=self.dot_radius)

        self.play(FadeIn(rect),
                  ReplacementTransform(VGroup(self.example_label[1].copy()),
                                       top_line),
                  run_time=2)
        self.dither()

        #From top line to second line
        index_alignment_lists = [
            [(0, 1, 0), (1, 1, 1)],
            [(0, 2, 2), (0, 1, 3), (1, 3, 4)],
            [(0, 2, 5), (1, 1, 6), (0, 3, 7)],
            [(0, 2, 8), (0, 3, 9), (1, 3, 10)],
        ]
        for index_alignment in index_alignment_lists:
            self.play(*[
                ReplacementTransform(
                    top_line[i][j].copy(),
                    second_line[k],
                ) for i, j, k in index_alignment
            ])
        self.dither(2)

        #From second line to final line
        index_alignment_lists = [
            [(0, 0), (1, 0), (9, 0), (10, 0)],
            [(2, 1), (3, 2), (4, 3), (6, 2), (7, 3)],
        ]
        for index_alignment in index_alignment_lists:
            self.play(*[
                ReplacementTransform(
                    second_line[i].copy(), final_line[j], run_time=1.5)
                for i, j in index_alignment
            ])
            self.dither()

        #Move result to appropriate place
        result_label = final_line.copy()
        result_label.add_background_rectangle()
        self.play(
            result_label.next_to,
            result_dot,
            UP + RIGHT,
            SMALL_BUFF,
            Animation(final_line),
            run_time=2,
        )
        self.play(
            DrawBorderThenFill(result_dot, stroke_width=4, stroke_color=PINK))
        self.dither(2)
Exemple #34
0
    def show_equation(self):
        equation = TexMobject([
            "\\left(\\dfrac{1}{\\phantom{v_air}}\\right)",
            "\\sin(\\theta_1)", 
            "=", 
            "\\left(\\dfrac{1}{\\phantom{v_water}}\\right)",
            "\\sin(\\theta_2)"
        ])
        equation.to_corner(UP+RIGHT)
        frac1, sin1, equals, frac2, sin2 = equation.split()
        v_air, v_water = [
            TexMobject("v_{\\text{%s}}"%s, size = "\\Large")
            for s in "air", "water"
        ]
        v_air.next_to(Point(frac1.get_center()), DOWN)
        v_water.next_to(Point(frac2.get_center()), DOWN)
        frac1.add(v_air)
        frac2.add(v_water)
        f1, f2 = [
            TexMobject("F_%d"%d, size = "\\Large") 
            for d in 1, 2
        ]
        f1.next_to(sin1, LEFT)
        f2.next_to(equals, RIGHT)
        sin2_start = sin2.copy().next_to(f2, RIGHT)
        bar1 = TexMobject("\\dfrac{\\qquad}{\\qquad}")
        bar2 = bar1.copy()
        bar1.next_to(sin1, DOWN)
        bar2.next_to(sin2, DOWN)        
        v_air_copy = v_air.copy().next_to(bar1, DOWN)
        v_water_copy = v_water.copy().next_to(bar2, DOWN)
        bars = Mobject(bar1, bar2)
        new_eq = equals.copy().center().shift(bars.get_center())
        snells = TextMobject("Snell's Law")
        snells.highlight(YELLOW)
        snells.shift(new_eq.get_center()[0]*RIGHT)
        snells.shift(UP)

        anims = []
        for mob in f1, sin1, equals, f2, sin2_start:
            anims.append(ShimmerIn(mob))
        self.play(*anims)
        self.dither()
        for f, frac in (f1, frac1), (f2, frac2):
            target = frac.copy().ingest_submobjects()
            also = []
            if f is f2:
                also.append(Transform(sin2_start, sin2))
                sin2 = sin2_start
            self.play(Transform(f, target), *also)
            self.remove(f)
            self.add(frac)
        self.dither()
        self.play(
            FadeOut(frac1),
            FadeOut(frac2),
            Transform(v_air, v_air_copy),
            Transform(v_water, v_water_copy),
            ShowCreation(bars),
            Transform(equals, new_eq)
        )
        self.dither()
        frac1 = Mobject(sin1, bar1, v_air)
        frac2 = Mobject(sin2, bar2, v_water)
        for frac, vect in (frac1, LEFT), (frac2, RIGHT):
            self.play(ApplyMethod(
                frac.next_to, equals, vect
            ))
        self.dither()
        self.play(ShimmerIn(snells))
        self.dither()