Exemplo n.º 1
0
    def record_basis_coordinates(self, vect_array, vect):
        i_label = vector_coordinate_label(self.i_hat)
        i_label.highlight(X_COLOR)
        j_label = vector_coordinate_label(self.j_hat)
        j_label.highlight(Y_COLOR)
        for mob in i_label, j_label:
            mob.scale_in_place(0.8)
            background = BackgroundRectangle(mob)
            self.play(ShowCreation(background), Write(mob))

        self.wait()
        x, y = vect_array.get_entries().split()
        pre_formula = VMobject(x, i_label, TexMobject("+"), y, j_label)
        post_formula = pre_formula.copy()
        pre_formula.split()[2].fade(1)
        post_formula.arrange_submobjects(buff=0.1)
        post_formula.next_to(vect, DOWN)
        background = BackgroundRectangle(post_formula)
        everything = self.get_mobjects()
        everything.remove(vect)
        self.play(*[ApplyMethod(m.fade) for m in everything] + [
            ShowCreation(background,
                         run_time=2,
                         rate_func=squish_rate_func(smooth, 0.5, 1)),
            Transform(pre_formula.copy(), post_formula, run_time=2),
            ApplyMethod(vect.set_stroke, width=7)
        ])
        self.wait()
Exemplo n.º 2
0
    def record_basis_coordinates(self, vect_array, vect):
        i_label = vector_coordinate_label(self.i_hat)
        i_label.highlight(X_COLOR)
        j_label = vector_coordinate_label(self.j_hat)
        j_label.highlight(Y_COLOR)
        for mob in i_label, j_label:
            mob.scale_in_place(0.8)
            background = BackgroundRectangle(mob)
            self.play(ShowCreation(background), Write(mob))

        self.dither()
        x, y = vect_array.get_entries().split()
        pre_formula = VMobject(
            x, i_label, TexMobject("+"),
            y, j_label
        )
        post_formula = pre_formula.copy()
        pre_formula.split()[2].fade(1)
        post_formula.arrange_submobjects(buff = 0.1)
        post_formula.next_to(vect, DOWN)
        background = BackgroundRectangle(post_formula)
        everything = self.get_mobjects()
        everything.remove(vect)
        self.play(*[
            ApplyMethod(m.fade) for m in everything
        ] + [
            ShowCreation(background, run_time = 2, rate_func = squish_rate_func(smooth, 0.5, 1)),
            Transform(pre_formula.copy(), post_formula, run_time = 2),
            ApplyMethod(vect.set_stroke, width = 7)
        ])
        self.dither()
Exemplo n.º 3
0
    def construct(self):
        title = TextMobject("Essence of Linear Algebra")
        title.highlight(BLUE)
        title.to_corner(UP+LEFT)
        h_line = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT)
        h_line.next_to(title, DOWN)
        h_line.to_edge(LEFT, buff = 0)
        chapters = VMobject(*map(TextMobject, [
            "Chapter 1: Vectors, what even are they?",
            "Chapter 2: Linear combinations, span and bases",
            "Chapter 3: Matrices as linear transformations",
            "Chapter 4: Matrix multiplication as composition",
            "Chapter 5: The determinant",
            "Chapter 6: Inverse matrices, column space and null space",
            "Chapter 7: Dot products and cross products",
            "Chapter 8: Change of basis",
            "Chapter 9: Eigenvectors and eigenvalues",
            "Chapter 10: Abstract vector spaces",
        ]))
        chapters.arrange_submobjects(DOWN)
        chapters.scale(0.7)
        chapters.next_to(h_line, DOWN)

        self.play(
            Write(title),
            ShowCreation(h_line)
        )
        for chapter in chapters.split():
            chapter.to_edge(LEFT, buff = 1)
            self.play(FadeIn(chapter))
        self.dither(2)

        entry3 = chapters.split()[2]
        added_words = TextMobject("(Personally, I'm most excited \\\\ to do this one)")
        added_words.scale(0.5)
        added_words.highlight(YELLOW)
        added_words.next_to(h_line, DOWN)
        added_words.to_edge(RIGHT)
        arrow = Arrow(added_words.get_bottom(), entry3)

        self.play(
            ApplyMethod(entry3.highlight, YELLOW),
            ShowCreation(arrow, submobject_mode = "one_at_a_time"),
            Write(added_words),
            run_time = 1
        )
        self.dither()
        removeable = VMobject(added_words, arrow, h_line, title)
        self.play(FadeOut(removeable))
        self.remove(removeable)

        self.series_of_videos(chapters)
Exemplo n.º 4
0
    def construct(self):
        title = TextMobject("Essence of Linear Algebra")
        title.highlight(BLUE)
        title.to_corner(UP + LEFT)
        h_line = Line(SPACE_WIDTH * LEFT, SPACE_WIDTH * RIGHT)
        h_line.next_to(title, DOWN)
        h_line.to_edge(LEFT, buff=0)
        chapters = VMobject(*map(TextMobject, [
            "Chapter 1: Vectors, what even are they?",
            "Chapter 2: Linear combinations, span and bases",
            "Chapter 3: Matrices as linear transformations",
            "Chapter 4: Matrix multiplication as composition",
            "Chapter 5: The determinant",
            "Chapter 6: Inverse matrices, column space and null space",
            "Chapter 7: Dot products and cross products",
            "Chapter 8: Change of basis",
            "Chapter 9: Eigenvectors and eigenvalues",
            "Chapter 10: Abstract vector spaces",
        ]))
        chapters.arrange_submobjects(DOWN)
        chapters.scale(0.7)
        chapters.next_to(h_line, DOWN)

        self.play(Write(title), ShowCreation(h_line))
        for chapter in chapters.split():
            chapter.to_edge(LEFT, buff=1)
            self.play(FadeIn(chapter))
        self.wait(2)

        entry3 = chapters.split()[2]
        added_words = TextMobject(
            "(Personally, I'm most excited \\\\ to do this one)")
        added_words.scale(0.5)
        added_words.highlight(YELLOW)
        added_words.next_to(h_line, DOWN)
        added_words.to_edge(RIGHT)
        arrow = Arrow(added_words.get_bottom(), entry3)

        self.play(ApplyMethod(entry3.highlight, YELLOW),
                  ShowCreation(arrow, submobject_mode="one_at_a_time"),
                  Write(added_words),
                  run_time=1)
        self.wait()
        removeable = VMobject(added_words, arrow, h_line, title)
        self.play(FadeOut(removeable))
        self.remove(removeable)

        self.series_of_videos(chapters)
Exemplo n.º 5
0
    def move_matrix_parentheses(self, morty, matrices):
        m1, m2, m3 = matrices
        parens = TexMobject(["(", ")"])
        parens.scale_to_fit_height(1.2*m1.get_height())
        lp, rp = parens.split()
        state1 = VMobject(
            VectorizedPoint(m1.get_left()),
            m1, m2, 
            VectorizedPoint(m2.get_right()),
            m3
        )
        state2 = VMobject(*[
            m.copy() for m in lp, m1, m2, rp, m3
        ])
        state3 = VMobject(*[
            m.copy() for m in m1, lp, m2, m3, rp
        ])
        for state in state2, state3:
            state.arrange_submobjects(RIGHT, buff = 0.1)
        m1, lp, m2, m3, rp = state3.split()
        state3 = VMobject(lp, m1, m2, rp, m3)

        self.play(morty.change_mode, "angry")
        for state in state2, state3:
            self.play(Transform(state1, state))
            self.dither()
        self.play(morty.change_mode, "confused")
        self.dither()
Exemplo n.º 6
0
    def construct(self):
        words = map(TextMobject, [
            "Just brushing up",
            "Has yet to take the course",
            "Supplementing course concurrently",
        ])
        students = VMobject(*[
            Randolph(color = c)
            for c in BLUE_D, BLUE_C, BLUE_E
        ])
        modes = ["pondering", "speaking_looking_left", "sassy"]
        students.arrange_submobjects(RIGHT)
        students.scale(0.8)
        students.center().to_edge(DOWN)

        last_word, last_arrow = None, None
        for word, student, mode in zip(words, students.split(), modes):
            word.shift(2*UP)
            arrow = Arrow(word, student)
            if last_word:
                word_anim = Transform(last_word, word)
                arrow_anim = Transform(last_arrow, arrow)
            else:
                word_anim = Write(word, run_time = 1)
                arrow_anim = ShowCreation(arrow, submobject_mode = "one_at_a_time")
                last_word = word
                last_arrow = arrow
            self.play(
                word_anim, arrow_anim,
                ApplyMethod(student.change_mode, mode)
            )
            self.play(Blink(student))
            self.dither()
        self.dither()
Exemplo n.º 7
0
    def show_overall_effect(self, matrix):
        everything = self.get_mobjects()
        everything = list_difference_update(everything,
                                            matrix.submobject_family())
        self.play(*map(FadeOut, everything) + [Animation(matrix)])
        new_matrix = matrix.copy()
        new_matrix.center().to_edge(UP)
        self.play(Transform(matrix, new_matrix))
        self.wait()
        self.remove(matrix)

        self.setup()
        everything = self.get_mobjects()
        self.play(*map(FadeIn, everything) + [Animation(matrix)])
        func = self.get_matrix_transformation([[1, 1], [-1, 0]])
        bases = VMobject(self.i_hat, self.j_hat)
        new_bases = VMobject(*[
            Vector(func(v.get_end()), color=v.get_color())
            for v in bases.split()
        ])
        self.play(ApplyPointwiseFunction(func, self.plane),
                  Transform(bases, new_bases),
                  Animation(matrix),
                  run_time=3)
        self.wait()
Exemplo n.º 8
0
    def show_overall_effect(self, matrix):
        everything = self.get_mobjects()
        everything = list_difference_update(
            everything, matrix.submobject_family()
        )
        self.play(*map(FadeOut, everything) + [Animation(matrix)])
        new_matrix = matrix.copy()
        new_matrix.center().to_edge(UP)
        self.play(Transform(matrix, new_matrix))
        self.dither()        
        self.remove(matrix)

        self.setup()
        everything = self.get_mobjects()
        self.play(*map(FadeIn, everything) + [Animation(matrix)])
        func = self.get_matrix_transformation([[1, 1], [-1, 0]])
        bases = VMobject(self.i_hat, self.j_hat)
        new_bases = VMobject(*[
            Vector(func(v.get_end()), color = v.get_color())
            for v in bases.split()
        ])
        self.play(
            ApplyPointwiseFunction(func, self.plane),
            Transform(bases, new_bases),
            Animation(matrix),
            run_time = 3
        )
        self.dither()
Exemplo n.º 9
0
    def construct(self):
        randy = Randolph().to_corner()
        bubble = randy.get_bubble(height=3.8)
        text1 = TextMobject("Think of individual vectors as arrows")
        text2 = TextMobject("Think of sets of vectors as points")
        for text in text1, text2:
            text.to_edge(UP)

        single_vector = Vector([2, 1])
        vector_group = VMobject(
            *[Vector([x, 1]) for x in np.linspace(-2, 2, 5)])
        bubble.position_mobject_inside(single_vector)
        bubble.position_mobject_inside(vector_group)
        dots = VMobject(*[Dot(v.get_end()) for v in vector_group.split()])

        self.add(randy)
        self.play(ApplyMethod(randy.change_mode, "pondering"),
                  ShowCreation(bubble))
        self.play(FadeIn(text1))
        self.play(ShowCreation(single_vector))
        self.wait(3)
        self.play(Transform(text1, text2),
                  Transform(single_vector, vector_group))
        self.remove(single_vector)
        self.add(vector_group)
        self.wait()
        self.play(Transform(vector_group, dots))
        self.wait()
Exemplo n.º 10
0
    def construct(self):
        morty = Mortimer()
        morty.scale(0.8)
        morty.to_corner(DOWN+RIGHT)
        morty.shift(0.5*LEFT)
        title = TextMobject("Associativity:")
        title.to_corner(UP+LEFT)

        lhs = TexMobject(list("(AB)C"))
        lp, a, b, rp, c = lhs.split()
        rhs = VMobject(*[m.copy() for m in a, lp, b, c, rp])
        point = VectorizedPoint()
        start = VMobject(*[m.copy() for m in point, a, b, point, c])
        for mob in lhs, rhs, start:
            mob.arrange_submobjects(buff = 0.1)
        a, lp, b, c, rp = rhs.split()
        rhs = VMobject(lp, a, b, rp, c)##Align order to lhs
        eq = TexMobject("=")
        q_marks = TextMobject("???")
        q_marks.submobject_gradient_highlight(TEAL_B, TEAL_D)
        q_marks.next_to(eq, UP)
        lhs.next_to(eq, LEFT)
        rhs.next_to(eq, RIGHT)
        start.move_to(lhs)


        self.add(morty, title)
        self.dither()
        self.play(Blink(morty))
        self.play(Write(start))
        self.dither()
        self.play(Transform(start, lhs))
        self.dither()
        self.play(
            Transform(lhs, rhs, path_arc = -np.pi),
            Write(eq)
        )
        self.play(Write(q_marks))
        self.play(Blink(morty))
        self.play(morty.change_mode, "pondering")

        lp, a, b, rp, c = start.split()
        self.show_full_matrices(morty, a, b, c, title)
Exemplo n.º 11
0
    def construct(self):
        vector = Vector([-2, 3])
        plane = NumberPlane()
        axis_labels = plane.get_axis_labels()
        other_vectors = VMobject(*map(Vector, [[1, 2], [2, -1], [4, 0]]))
        colors = [GREEN_B, MAROON_B, PINK]
        for v, color in zip(other_vectors.split(), colors):
            v.highlight(color)
        shift_val = 4 * RIGHT + DOWN

        dot = Dot(radius=0.1)
        dot.highlight(RED)
        tail_word = TextMobject("Tail")
        tail_word.shift(0.5 * DOWN + 2.5 * LEFT)
        line = Line(tail_word, dot)

        self.play(ShowCreation(vector, submobject_mode="one_at_a_time"))
        self.dither(2)
        self.play(ShowCreation(plane, summobject_mode="lagged_start"),
                  Animation(vector))
        self.play(Write(axis_labels, run_time=1))
        self.dither()
        self.play(GrowFromCenter(dot), ShowCreation(line),
                  Write(tail_word, run_time=1))
        self.dither()
        self.play(FadeOut(tail_word),
                  ApplyMethod(VMobject(dot, line).scale, 0.01))
        self.remove(tail_word, line, dot)
        self.dither()

        self.play(
            ApplyMethod(vector.shift,
                        shift_val,
                        path_arc=3 * np.pi / 2,
                        run_time=3))
        self.play(
            ApplyMethod(vector.shift,
                        -shift_val,
                        rate_func=rush_into,
                        run_time=0.5))
        self.dither(3)

        self.play(
            ShowCreation(other_vectors,
                         submobject_mode="one_at_a_time",
                         run_time=3))
        self.dither(3)

        x_axis, y_axis = plane.get_axes().split()
        x_label = axis_labels.split()[0]
        x_axis = x_axis.copy()
        x_label = x_label.copy()
        everything = VMobject(*self.mobjects)
        self.play(FadeOut(everything), Animation(x_axis), Animation(x_label))
Exemplo n.º 12
0
    def animate_product(self, left, right, result):
        l_matrix = left.get_mob_matrix()
        r_matrix = right.get_mob_matrix()
        result_matrix = result.get_mob_matrix()
        circle = Circle(
            radius = l_matrix[0][0].get_height(),
            color = GREEN
        )
        circles = VMobject(*[
            entry.get_point_mobject()
            for entry in l_matrix[0][0], r_matrix[0][0]
        ])
        (m, k), n = l_matrix.shape, r_matrix.shape[1]
        for mob in result_matrix.flatten():
            mob.highlight(BLACK)
        lagging_anims = []
        for a in range(m):
            for b in range(n):
                for c in range(k):
                    l_matrix[a][c].highlight(YELLOW)
                    r_matrix[c][b].highlight(YELLOW)
                for c in range(k):
                    start_parts = VMobject(
                        l_matrix[a][c].copy(),
                        r_matrix[c][b].copy()
                    )
                    result_entry = result_matrix[a][b].split()[c]

                    new_circles = VMobject(*[
                        circle.copy().shift(part.get_center())
                        for part in start_parts.split()
                    ])
                    self.play(Transform(circles, new_circles))
                    self.play(
                        Transform(
                            start_parts, 
                            result_entry.copy().highlight(YELLOW), 
                            path_arc = -np.pi/2,
                            submobject_mode = "all_at_once",
                        ),
                        *lagging_anims
                    )
                    result_entry.highlight(YELLOW)
                    self.remove(start_parts)
                    lagging_anims = [
                        ApplyMethod(result_entry.highlight, WHITE)
                    ]

                for c in range(k):
                    l_matrix[a][c].highlight(WHITE)
                    r_matrix[c][b].highlight(WHITE)
        self.play(FadeOut(circles), *lagging_anims)
        self.dither()
Exemplo n.º 13
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()
Exemplo n.º 14
0
 def construct(self):
     title = TextMobject("Questions to ponder")
     title.highlight(YELLOW).to_edge(UP)
     self.add(title)
     questions = VMobject(*map(TextMobject, [
         "1. Can you visualize these transformations?",
         "2. Can you represent them with matrices?",
         "3. How many rows and columns?",
         "4. When can you multiply these matrices?",
     ]))
     questions.arrange_submobjects(DOWN, buff=1, aligned_edge=LEFT)
     questions.to_edge(LEFT)
     for question in questions.split():
         self.play(Write(question, run_time=1))
         self.wait()
Exemplo n.º 15
0
 def construct(self):
     title = TextMobject("Questions to ponder")
     title.highlight(YELLOW).to_edge(UP)
     self.add(title)
     questions = VMobject(*map(TextMobject, [
         "1. Can you visualize these transformations?",
         "2. Can you represent them with matrices?",
         "3. How many rows and columns?",
         "4. When can you multiply these matrices?",
     ]))
     questions.arrange_submobjects(DOWN, buff = 1, aligned_edge = LEFT)
     questions.to_edge(LEFT)
     for question in questions.split():
         self.play(Write(question, run_time = 1))
         self.dither()
Exemplo n.º 16
0
    def construct(self):
        i_to = TexMobject("\\hat{\\imath} \\to").highlight(X_COLOR)
        j_to = TexMobject("\\hat{\\jmath} \\to").highlight(Y_COLOR)
        k_to = TexMobject("\\hat{k} \\to").highlight(Z_COLOR)
        i_array = Matrix(self.col1)
        j_array = Matrix(self.col2)
        k_array = Matrix(self.col3)
        everything = VMobject(
            i_to,
            i_array,
            TexMobject("=").highlight(BLACK),
            j_to,
            j_array,
            TexMobject("=").highlight(BLACK),
            k_to,
            k_array,
            TexMobject("=").highlight(BLACK),
        )
        everything.arrange_submobjects(RIGHT, buff=0.1)
        everything.scale_to_fit_width(2 * SPACE_WIDTH - 1)
        everything.to_edge(DOWN)

        i_array.highlight(X_COLOR)
        j_array.highlight(Y_COLOR)
        k_array.highlight(Z_COLOR)
        arrays = [i_array, j_array, k_array]
        matrix = Matrix(
            reduce(lambda a1, a2: np.append(a1, a2, axis=1),
                   [m.copy().get_mob_matrix() for m in arrays]))
        matrix.to_edge(DOWN)

        start_entries = reduce(op.add,
                               map(lambda a: a.get_entries().split(), arrays))
        target_entries = matrix.get_mob_matrix().transpose().flatten()
        start_l_bracket = i_array.get_brackets().split()[0]
        start_r_bracket = k_array.get_brackets().split()[1]
        start_brackets = VMobject(start_l_bracket, start_r_bracket)
        target_bracketes = matrix.get_brackets()

        for mob in everything.split():
            self.play(Write(mob, run_time=1))
        self.wait()
        self.play(
            FadeOut(everything),
            Transform(VMobject(*start_entries), VMobject(*target_entries)),
            Transform(start_brackets, target_bracketes))
        self.wait()
Exemplo n.º 17
0
    def animate_product(self, left, right, result):
        l_matrix = left.get_mob_matrix()
        r_matrix = right.get_mob_matrix()
        result_matrix = result.get_mob_matrix()
        circle = Circle(radius=l_matrix[0][0].get_height(), color=GREEN)
        circles = VMobject(*[
            entry.get_point_mobject()
            for entry in l_matrix[0][0], r_matrix[0][0]
        ])
        (m, k), n = l_matrix.shape, r_matrix.shape[1]
        for mob in result_matrix.flatten():
            mob.highlight(BLACK)
        lagging_anims = []
        for a in range(m):
            for b in range(n):
                for c in range(k):
                    l_matrix[a][c].highlight(YELLOW)
                    r_matrix[c][b].highlight(YELLOW)
                for c in range(k):
                    start_parts = VMobject(l_matrix[a][c].copy(),
                                           r_matrix[c][b].copy())
                    result_entry = result_matrix[a][b].split()[c]

                    new_circles = VMobject(*[
                        circle.copy().shift(part.get_center())
                        for part in start_parts.split()
                    ])
                    self.play(Transform(circles, new_circles))
                    self.play(
                        Transform(
                            start_parts,
                            result_entry.copy().highlight(YELLOW),
                            path_arc=-np.pi / 2,
                            submobject_mode="all_at_once",
                        ), *lagging_anims)
                    result_entry.highlight(YELLOW)
                    self.remove(start_parts)
                    lagging_anims = [
                        ApplyMethod(result_entry.highlight, WHITE)
                    ]

                for c in range(k):
                    l_matrix[a][c].highlight(WHITE)
                    r_matrix[c][b].highlight(WHITE)
        self.play(FadeOut(circles), *lagging_anims)
        self.wait()
Exemplo n.º 18
0
    def construct(self):
        i_to = TexMobject("\\hat{\\imath} \\to").highlight(X_COLOR)
        j_to = TexMobject("\\hat{\\jmath} \\to").highlight(Y_COLOR)
        k_to = TexMobject("\\hat{k} \\to").highlight(Z_COLOR)
        i_array = Matrix(self.col1)
        j_array = Matrix(self.col2)
        k_array = Matrix(self.col3)
        everything = VMobject(
            i_to, i_array, TexMobject("=").highlight(BLACK),
            j_to, j_array, TexMobject("=").highlight(BLACK),
            k_to, k_array, TexMobject("=").highlight(BLACK),
        )
        everything.arrange_submobjects(RIGHT, buff = 0.1)
        everything.scale_to_fit_width(2*SPACE_WIDTH-1)
        everything.to_edge(DOWN)

        i_array.highlight(X_COLOR)
        j_array.highlight(Y_COLOR)
        k_array.highlight(Z_COLOR)
        arrays = [i_array, j_array, k_array]
        matrix = Matrix(reduce(
            lambda a1, a2 : np.append(a1, a2, axis = 1),
            [m.copy().get_mob_matrix() for m in arrays]
        ))
        matrix.to_edge(DOWN)

        start_entries = reduce(op.add, map(
            lambda a : a.get_entries().split(),
            arrays
        ))
        target_entries = matrix.get_mob_matrix().transpose().flatten()
        start_l_bracket = i_array.get_brackets().split()[0]
        start_r_bracket = k_array.get_brackets().split()[1]
        start_brackets = VMobject(start_l_bracket, start_r_bracket)
        target_bracketes = matrix.get_brackets()

        for mob in everything.split():
            self.play(Write(mob, run_time = 1))
        self.dither()
        self.play(
            FadeOut(everything),
            Transform(VMobject(*start_entries), VMobject(*target_entries)),
            Transform(start_brackets, target_bracketes)
        )
        self.dither()
Exemplo n.º 19
0
    def construct(self):
        morty = Mortimer()
        morty.to_corner(DOWN+RIGHT)
        morty.look(DOWN+LEFT)
        new_morty = morty.copy().change_mode("speaking")  
        new_morty.look(DOWN+LEFT)      

        randys = VMobject(*[
            Randolph(color = color).scale(0.8)
            for color in BLUE_D, BLUE_C, BLUE_E
        ])
        randys.arrange_submobjects(RIGHT)
        randys.to_corner(DOWN+LEFT)
        randy = randys.split()[1]

        speech_bubble = morty.get_bubble("speech")
        words = TextMobject("Think of some vector...")
        speech_bubble.position_mobject_inside(words)
        thought_bubble = randy.get_bubble()
        arrow = Vector([2, 1]).scale(0.7)
        or_word = TextMobject("or")
        array = Matrix([2, 1]).scale(0.5)
        q_mark = TextMobject("?")
        thought = VMobject(arrow, or_word, array, q_mark)
        thought.arrange_submobjects(RIGHT, buff = 0.2)
        thought_bubble.position_mobject_inside(thought)
        thought_bubble.set_fill(BLACK, opacity = 1)


        self.add(morty, randys)
        self.play(
            ShowCreation(speech_bubble),
            Transform(morty, new_morty),
            Write(words)
        )
        self.dither(2)
        self.play(
            FadeOut(speech_bubble),
            FadeOut(words),
            ApplyMethod(randy.change_mode, "pondering"),
            ShowCreation(thought_bubble),
            Write(thought)
        )
        self.dither(2)
Exemplo n.º 20
0
    def construct(self):
        icons = [VideoIcon() for x in range(10)]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity=1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)
        icons = icons.split()

        def rate_func_creator(offset):
            return lambda a: min(max(2 * (a - offset), 0), 1)

        self.play(*[
            FadeIn(icon, run_time=5, rate_func=rate_func_creator(offset))
            for icon, offset in zip(icons, np.linspace(0, 0.5, len(icons)))
        ])
        self.wait()
Exemplo n.º 21
0
    def construct(self):
        morty = Mortimer(mode = "speaking")
        morty.to_corner(DOWN + RIGHT)
        bubble = morty.get_bubble(SpeechBubble)
        bubble.write("I'm assuming you \\\\ know linear algebra\\dots")
        words = bubble.content
        bubble.clear()
        randys = VMobject(*[
            Randolph(color = c)
            for c in BLUE_D, BLUE_C, BLUE_E
        ])
        randys.arrange_submobjects(RIGHT)
        randys.scale(0.8)
        randys.to_corner(DOWN+LEFT)

        self.add(randys, morty)
        self.play(FadeIn(bubble), Write(words), run_time = 3)
        for randy in np.array(randys.split())[[2,0,1]]:
            self.play(Blink(randy))
        self.dither()
Exemplo n.º 22
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()
Exemplo n.º 23
0
    def construct(self):
        icons = [VideoIcon() for x in range(10)]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity = 1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)
        icons = icons.split()

        def rate_func_creator(offset):
            return lambda a : min(max(2*(a-offset), 0), 1)
        self.play(*[
            FadeIn(
                icon, 
                run_time = 5,
                rate_func = rate_func_creator(offset)
            )
            for icon, offset in zip(icons, np.linspace(0, 0.5, len(icons)))
        ])
        self.dither()
Exemplo n.º 24
0
    def construct(self):
        randy = Randolph().to_corner()
        bubble = randy.get_bubble(height = 3.8)
        text1 = TextMobject("Think of individual vectors as arrows")
        text2 = TextMobject("Think of sets of vectors as points")
        for text in text1, text2:
            text.to_edge(UP)

        single_vector = Vector([2, 1])
        vector_group = VMobject(*[
            Vector([x, 1])
            for x in np.linspace(-2, 2, 5)
        ])
        bubble.position_mobject_inside(single_vector)
        bubble.position_mobject_inside(vector_group)
        dots = VMobject(*[
            Dot(v.get_end())
            for v in vector_group.split()
        ])

        self.add(randy)
        self.play(
            ApplyMethod(randy.change_mode, "pondering"),
            ShowCreation(bubble)
        )
        self.play(FadeIn(text1))
        self.play(ShowCreation(single_vector))
        self.dither(3)
        self.play(
            Transform(text1, text2),
            Transform(single_vector, vector_group)
        )
        self.remove(single_vector)
        self.add(vector_group)
        self.dither()
        self.play(Transform(vector_group, dots))
        self.dither()
Exemplo n.º 25
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.wait()
        self.apply_transposed_matrix(self.t_matrix)
        self.wait()
        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.wait()
Exemplo n.º 26
0
class NumberPlane(VMobject):
    CONFIG = {
        "color" : BLUE_D,
        "secondary_color" : BLUE_E,
        "axes_color" : WHITE,
        "secondary_stroke_width" : 1,
        "x_radius": None,
        "y_radius": None,
        "x_unit_size" : 1,
        "y_unit_size" : 1,
        "center_point" : ORIGIN,
        "x_line_frequency" : 1,
        "y_line_frequency" : 1,
        "secondary_line_ratio" : 1,
        "written_coordinate_height" : 0.2,
        "propagate_style_to_family" : False,
    }
    def generate_points(self):
        if self.x_radius is None:
            center_to_edge = (SPACE_WIDTH + abs(self.center_point[0])) 
            self.x_radius = center_to_edge / self.x_unit_size
        if self.y_radius is None:
            center_to_edge = (SPACE_HEIGHT + abs(self.center_point[1])) 
            self.y_radius = center_to_edge / self.y_unit_size
        self.axes = VMobject()
        self.main_lines = VMobject()
        self.secondary_lines = VMobject()
        tuples = [
            (
                self.x_radius, 
                self.x_line_frequency, 
                self.y_radius*DOWN, 
                self.y_radius*UP,
                RIGHT
            ),
            (
                self.y_radius, 
                self.y_line_frequency, 
                self.x_radius*LEFT, 
                self.x_radius*RIGHT,
                UP,
            ),
        ]
        for radius, freq, start, end, unit in tuples:
            main_range = np.arange(0, radius, freq)
            step = freq/float(freq + self.secondary_line_ratio)
            for v in np.arange(0, radius, step):
                line1 = Line(start+v*unit, end+v*unit)
                line2 = Line(start-v*unit, end-v*unit)                
                if v == 0:
                    self.axes.add(line1)
                elif v in main_range:
                    self.main_lines.add(line1, line2)
                else:
                    self.secondary_lines.add(line1, line2)
        self.add(self.secondary_lines, self.main_lines, self.axes)
        self.stretch(self.x_unit_size, 0)
        self.stretch(self.y_unit_size, 1)
        self.shift(self.center_point)
        #Put x_axis before y_axis
        y_axis, x_axis = self.axes.split()
        self.axes = VMobject(x_axis, y_axis)

    def init_colors(self):
        VMobject.init_colors(self)
        self.axes.set_stroke(self.axes_color, self.stroke_width)
        self.main_lines.set_stroke(self.color, self.stroke_width)
        self.secondary_lines.set_stroke(
            self.secondary_color, self.secondary_stroke_width
        )
        return self

    def get_center_point(self):
        return self.coords_to_point(0, 0)

    def coords_to_point(self, x, y):
        x, y = np.array([x, y])
        result = self.axes.get_center()
        result += x*self.get_x_unit_size()*RIGHT
        result += y*self.get_y_unit_size()*UP
        return result

    def point_to_coords(self, point):
        new_point = point - self.axes.get_center()
        x = new_point[0]/self.get_x_unit_size()
        y = new_point[1]/self.get_y_unit_size()
        return x, y

    def get_x_unit_size(self):
        return self.axes.get_width() / (2.0*self.x_radius)

    def get_y_unit_size(self):
        return self.axes.get_height() / (2.0*self.y_radius)

    def get_coordinate_labels(self, x_vals = None, y_vals = None):
        coordinate_labels = VGroup()
        if x_vals == None:
            x_vals = range(-int(self.x_radius), int(self.x_radius)+1)
        if y_vals == None:
            y_vals = range(-int(self.y_radius), int(self.y_radius)+1)
        for index, vals in enumerate([x_vals, y_vals]):
            num_pair = [0, 0]
            for val in vals:
                if val == 0:
                    continue
                num_pair[index] = val
                point = self.coords_to_point(*num_pair)
                num = TexMobject(str(val))
                num.add_background_rectangle()
                num.scale_to_fit_height(
                    self.written_coordinate_height
                )
                num.next_to(point, DOWN+LEFT, buff = SMALL_BUFF)
                coordinate_labels.add(num)
        self.coordinate_labels = coordinate_labels
        return coordinate_labels

    def get_axes(self):
        return self.axes

    def get_axis_labels(self, x_label = "x", y_label = "y"):
        x_axis, y_axis = self.get_axes().split()
        quads = [
            (x_axis, x_label, UP, RIGHT),
            (y_axis, y_label, RIGHT, UP),
        ]
        labels = VGroup()
        for axis, tex, vect, edge in quads:
            label = TexMobject(tex)
            label.add_background_rectangle()
            label.next_to(axis, vect)
            label.to_edge(edge)
            labels.add(label)
        self.axis_labels = labels
        return labels

    def add_coordinates(self, x_vals = None, y_vals = None):
        self.add(*self.get_coordinate_labels(x_vals, y_vals))
        return self

    def get_vector(self, coords, **kwargs):
        point = coords[0]*RIGHT + coords[1]*UP
        arrow = Arrow(ORIGIN, coords, **kwargs)
        return arrow

    def prepare_for_nonlinear_transform(self, num_inserted_anchor_points = 50):
        for mob in self.family_members_with_points():
            num_anchors = mob.get_num_anchor_points()
            if num_inserted_anchor_points > num_anchors:
                mob.insert_n_anchor_points(num_inserted_anchor_points-num_anchors)
                mob.make_smooth()
        return self

    def apply_function(self, function, maintain_smoothness = True):
        VMobject.apply_function(self, function, maintain_smoothness = maintain_smoothness)
Exemplo n.º 27
0
class TeacherStudentsScene(Scene):
    def setup(self):
        self.teacher = Mortimer()
        self.teacher.to_corner(DOWN + RIGHT)
        self.teacher.look(DOWN+LEFT)
        self.students = VMobject(*[
            Randolph(color = c)
            for c in BLUE_D, BLUE_C, BLUE_E
        ])
        self.students.arrange_submobjects(RIGHT)
        self.students.scale(0.8)
        self.students.to_corner(DOWN+LEFT)

        for pi_creature in self.get_everyone():
            pi_creature.bubble = None
        self.add(*self.get_everyone())

    def get_teacher(self):
        return self.teacher

    def get_students(self):
        return self.students.split()

    def get_everyone(self):
        return [self.get_teacher()] + self.get_students()

    def get_bubble_intro_animation(self, content, bubble_type,
                                   pi_creature,
                                   **bubble_kwargs):
        bubble = pi_creature.get_bubble(bubble_type, **bubble_kwargs)
        bubble.add_content(content)
        if pi_creature.bubble:
            content_intro_anims = [
                Transform(pi_creature.bubble, bubble),
                Transform(pi_creature.bubble.content, bubble.content)
            ]
        else:
            content_intro_anims = [
                FadeIn(bubble),
                Write(content),
            ]
            pi_creature.bubble = bubble 
        return content_intro_anims

    def introduce_bubble(self, content, bubble_type, pi_creature,
                         pi_creature_target_mode = None,
                         added_anims = [],
                         **bubble_kwargs):
        if isinstance(content, str):
            content = TextMobject(content)     
        content_intro_anims = self.get_bubble_intro_animation(
            content, bubble_type, pi_creature, **bubble_kwargs
        )

        if not pi_creature_target_mode:
            if bubble_type is "speech":
                pi_creature_target_mode = "speaking"
            else:
                pi_creature_target_mode = "pondering"

        for p in self.get_everyone():
            if p.bubble and p is not pi_creature:
                added_anims += [
                    FadeOut(p.bubble),
                    FadeOut(p.bubble.content)
                ]
                p.bubble = None
                added_anims.append(ApplyMethod(p.change_mode, "plain"))

        anims = added_anims + content_intro_anims + [
            ApplyMethod(
                pi_creature.change_mode, 
                pi_creature_target_mode,
            ),
        ]
        self.play(*anims)
        return pi_creature.bubble

    def teacher_says(self, content = "", **kwargs):
        return self.introduce_bubble(
            content, "speech", self.get_teacher(), **kwargs
        )

    def student_says(self, content = "", student_index = 1, **kwargs):
        student = self.get_students()[student_index]
        return self.introduce_bubble(content, "speech", student, **kwargs)

    def teacher_thinks(self, content = "", **kwargs):
        return self.introduce_bubble(
            content, "thought", self.get_teacher(), **kwargs
        )

    def student_thinks(self, content = "", student_index = 1, **kwargs):
        student = self.get_students()[student_index]
        return self.introduce_bubble(content, "thought", student, **kwargs)

    def random_blink(self, num_times = 1):
        for x in range(num_times):
            pi_creature = random.choice(self.get_everyone())
            self.play(Blink(pi_creature))
            self.dither()
Exemplo n.º 28
0
class NumberPlane(VMobject):
    CONFIG = {
        "color": BLUE_D,
        "secondary_color": BLUE_E,
        "axes_color": WHITE,
        "secondary_stroke_width": 1,
        "x_radius": SPACE_WIDTH,
        "y_radius": SPACE_HEIGHT,
        "space_unit_to_x_unit": 1,
        "space_unit_to_y_unit": 1,
        "x_line_frequency": 1,
        "y_line_frequency": 1,
        "secondary_line_ratio": 1,
        "written_coordinate_height": 0.2,
        "written_coordinate_nudge": 0.1 * (DOWN + RIGHT),
        "num_pair_at_center": (0, 0),
        "propogate_style_to_family": False,
    }

    def generate_points(self):
        self.axes = VMobject()
        self.main_lines = VMobject()
        self.secondary_lines = VMobject()
        tuples = [
            (self.x_radius, self.x_line_frequency, self.y_radius * DOWN,
             self.y_radius * UP, RIGHT),
            (
                self.y_radius,
                self.y_line_frequency,
                self.x_radius * LEFT,
                self.x_radius * RIGHT,
                UP,
            ),
        ]
        for radius, freq, start, end, unit in tuples:
            main_range = np.arange(0, radius, freq)
            step = freq / float(freq + self.secondary_line_ratio)
            for v in np.arange(0, radius, step):
                line1 = Line(start + v * unit, end + v * unit)
                line2 = Line(start - v * unit, end - v * unit)
                if v == 0:
                    self.axes.add(line1)
                elif v in main_range:
                    self.main_lines.add(line1, line2)
                else:
                    self.secondary_lines.add(line1, line2)
        self.add(self.secondary_lines, self.main_lines, self.axes)
        self.stretch(self.space_unit_to_x_unit, 0)
        self.stretch(self.space_unit_to_y_unit, 1)
        #Put x_axis before y_axis
        y_axis, x_axis = self.axes.split()
        self.axes = VMobject(x_axis, y_axis)

    def init_colors(self):
        VMobject.init_colors(self)
        self.axes.set_stroke(self.axes_color, self.stroke_width)
        self.main_lines.set_stroke(self.color, self.stroke_width)
        self.secondary_lines.set_stroke(self.secondary_color,
                                        self.secondary_stroke_width)
        return self

    def get_center_point(self):
        return self.num_pair_to_point(self.num_pair_at_center)

    def num_pair_to_point(self, pair):
        pair = np.array(pair) + self.num_pair_at_center
        result = self.axes.get_center()
        result[0] += pair[0] * self.space_unit_to_x_unit
        result[1] += pair[1] * self.space_unit_to_y_unit
        return result

    def point_to_num_pair(self, point):
        new_point = point - self.get_center()
        center_x, center_y = self.num_pair_at_center
        x = center_x + point[0] / self.space_unit_to_x_unit
        y = center_y + point[1] / self.space_unit_to_y_unit
        return x, y

    def get_coordinate_labels(self, x_vals=None, y_vals=None):
        result = []
        if x_vals == None and y_vals == None:
            x_vals = range(-int(self.x_radius), int(self.x_radius))
            y_vals = range(-int(self.y_radius), int(self.y_radius))
        for index, vals in enumerate([x_vals, y_vals]):
            num_pair = [0, 0]
            for val in vals:
                num_pair[index] = val
                point = self.num_pair_to_point(num_pair)
                num = TexMobject(str(val))
                num.scale_to_fit_height(self.written_coordinate_height)
                num.shift(point - num.get_corner(UP + LEFT),
                          self.written_coordinate_nudge)
                result.append(num)
        return result

    def get_axes(self):
        return self.axes

    def get_axis_labels(self, x_label="x", y_label="y"):
        x_axis, y_axis = self.get_axes().split()
        x_label_mob = TexMobject(x_label)
        y_label_mob = TexMobject(y_label)
        x_label_mob.next_to(x_axis, DOWN)
        x_label_mob.to_edge(RIGHT)
        y_label_mob.next_to(y_axis, RIGHT)
        y_label_mob.to_edge(UP)
        return VMobject(x_label_mob, y_label_mob)

    def add_coordinates(self, x_vals=None, y_vals=None):
        self.add(*self.get_coordinate_labels(x_vals, y_vals))
        return self

    def get_vector(self, coords, **kwargs):
        point = coords[0] * RIGHT + coords[1] * UP
        arrow = Arrow(ORIGIN, coords, **kwargs)
        return arrow

    def prepare_for_nonlinear_transform(self, num_inserted_anchor_points=50):
        for mob in self.family_members_with_points():
            num_anchors = mob.get_num_anchor_points()
            if num_inserted_anchor_points > num_anchors:
                mob.insert_n_anchor_points(num_inserted_anchor_points -
                                           num_anchors)
                mob.make_smooth()
        return self
Exemplo n.º 29
0
class TeacherStudentsScene(Scene):
    def setup(self):
        self.teacher = Mortimer()
        self.teacher.to_corner(DOWN + RIGHT)
        self.teacher.look(DOWN+LEFT)
        self.students = VMobject(*[
            Randolph(color = c)
            for c in BLUE_D, BLUE_C, BLUE_E
        ])
        self.students.arrange_submobjects(RIGHT)
        self.students.scale(0.8)
        self.students.to_corner(DOWN+LEFT)
        self.students = self.students.split()

        for pi_creature in self.get_everyone():
            pi_creature.bubble = None
        self.add(*self.get_everyone())

    def get_teacher(self):
        return self.teacher

    def get_students(self):
        return self.students

    def get_everyone(self):
        return [self.get_teacher()] + self.get_students()

    def get_bubble_intro_animation(self, content, bubble_type,
                                   pi_creature,
                                   **bubble_kwargs):
        bubble = pi_creature.get_bubble(bubble_type, **bubble_kwargs)
        bubble.add_content(content)
        if pi_creature.bubble:
            content_intro_anims = [
                Transform(pi_creature.bubble, bubble),
                Transform(pi_creature.bubble.content, bubble.content)
            ]
        else:
            content_intro_anims = [
                FadeIn(bubble),
                Write(content),
            ]
            pi_creature.bubble = bubble 
        return content_intro_anims

    def introduce_bubble(self, content, bubble_type, pi_creature,
                         pi_creature_target_mode = None,
                         added_anims = [],
                         **bubble_kwargs):
        if all(map(lambda s : isinstance(s, str), content)):
            content = TextMobject(*content)
        elif len(content) == 1 and isinstance(content[0], TexMobject):
            content = content[0]
        else:
            raise Exception("Invalid content type")
        content_intro_anims = self.get_bubble_intro_animation(
            content, bubble_type, pi_creature, **bubble_kwargs
        )

        if not pi_creature_target_mode:
            if bubble_type is "speech":
                pi_creature_target_mode = "speaking"
            else:
                pi_creature_target_mode = "pondering"

        for p in self.get_everyone():
            if p.bubble and p is not pi_creature:
                added_anims += [
                    FadeOut(p.bubble),
                    FadeOut(p.bubble.content)
                ]
                p.bubble = None
                added_anims.append(ApplyMethod(p.change_mode, "plain"))

        anims = added_anims + content_intro_anims + [
            ApplyMethod(
                pi_creature.change_mode, 
                pi_creature_target_mode,
            ),
        ]
        self.play(*anims)
        return pi_creature.bubble

    def teacher_says(self, *content, **kwargs):
        return self.introduce_bubble(
            content, "speech", self.get_teacher(), **kwargs
        )

    def student_says(self, *content, **kwargs):
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.introduce_bubble(content, "speech", student, **kwargs)

    def teacher_thinks(self, *content, **kwargs):
        return self.introduce_bubble(
            content, "thought", self.get_teacher(), **kwargs
        )

    def student_thinks(self, *content, **kwargs):
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.introduce_bubble(content, "thought", student, **kwargs)

    def random_blink(self, num_times = 1):
        for x in range(num_times):
            pi_creature = random.choice(self.get_everyone())
            self.play(Blink(pi_creature))
            self.dither()

    def change_student_modes(self, *modes):
        self.play(*[
            ApplyMethod(pi.change_mode, mode)
            for pi, mode in zip(self.get_students(), modes)
        ])

    def zoom_in_on_thought_bubble(self, radius = SPACE_HEIGHT+SPACE_WIDTH):
        bubble = None
        for pi in self.get_everyone():
            if hasattr(pi, "bubble") and isinstance(pi.bubble, ThoughtBubble):
                bubble = pi.bubble
                break
        if bubble is None:
            raise Exception("No pi creatures have a thought bubble")
        vect = -bubble.get_bubble_center()
        def func(point):
            centered = point+vect
            return radius*centered/np.linalg.norm(centered)
        self.play(*[
            ApplyPointwiseFunction(func, mob)
            for mob in self.get_mobjects()
        ])
Exemplo n.º 30
0
class NumberPlane(VMobject):
    CONFIG = {
        "color" : BLUE_D,
        "secondary_color" : BLUE_E,
        "axes_color" : WHITE,
        "secondary_stroke_width" : 1,
        "x_radius": SPACE_WIDTH,
        "y_radius": SPACE_HEIGHT,
        "space_unit_to_x_unit" : 1,
        "space_unit_to_y_unit" : 1,
        "x_line_frequency" : 1,
        "y_line_frequency" : 1,
        "secondary_line_ratio" : 1,
        "written_coordinate_height" : 0.2,
        "written_coordinate_nudge" : 0.1*(DOWN+RIGHT),
        "num_pair_at_center" : (0, 0),
        "propogate_style_to_family" : False,
        "submobject_partial_creation_mode" : "smoothed_lagged_start",
    }
    
    def generate_points(self):
        self.axes = VMobject()
        self.main_lines = VMobject()
        self.secondary_lines = VMobject()
        tuples = [
            (
                self.x_radius, 
                self.x_line_frequency, 
                self.y_radius*DOWN, 
                self.y_radius*UP,
                RIGHT
            ),
            (
                self.y_radius, 
                self.y_line_frequency, 
                self.x_radius*LEFT, 
                self.x_radius*RIGHT,
                UP,
            ),
        ]
        for radius, freq, start, end, unit in tuples:
            main_range = np.arange(0, radius, freq)
            step = freq/float(freq + self.secondary_line_ratio)
            for v in np.arange(0, radius, step):
                line1 = Line(start+v*unit, end+v*unit)
                line2 = Line(start-v*unit, end-v*unit)                
                if v == 0:
                    self.axes.add(line1)
                elif v in main_range:
                    self.main_lines.add(line1, line2)
                else:
                    self.secondary_lines.add(line1, line2)
        self.add(self.axes, self.main_lines, self.secondary_lines)
        self.stretch(self.space_unit_to_x_unit, 0)
        self.stretch(self.space_unit_to_y_unit, 1)
        #Put x_axis before y_axis
        y_axis, x_axis = self.axes.split()
        self.axes = VMobject(x_axis, y_axis)

    def init_colors(self):
        VMobject.init_colors(self)
        self.axes.set_stroke(self.axes_color, self.stroke_width)
        self.main_lines.set_stroke(self.color, self.stroke_width)
        self.secondary_lines.set_stroke(
            self.secondary_color, self.secondary_stroke_width
        )
        return self

    def get_center_point(self):
        return self.num_pair_to_point(self.num_pair_at_center)

    def num_pair_to_point(self, pair):
        pair = np.array(pair) + self.num_pair_at_center
        result = self.get_center()
        result[0] += pair[0]*self.space_unit_to_x_unit
        result[1] += pair[1]*self.space_unit_to_y_unit
        return result

    def point_to_num_pair(self, point):
        new_point = point-self.get_center()
        center_x, center_y = self.num_pair_at_center
        x = center_x + point[0]/self.space_unit_to_x_unit
        y = center_y + point[1]/self.space_unit_to_y_unit
        return x, y

    def get_coordinate_labels(self, x_vals = None, y_vals = None):
        result = []
        if x_vals == None and y_vals == None:
            x_vals = range(-int(self.x_radius), int(self.x_radius))
            y_vals = range(-int(self.y_radius), int(self.y_radius))
        for index, vals in enumerate([x_vals, y_vals]):
            num_pair = [0, 0]
            for val in vals:
                num_pair[index] = val
                point = self.num_pair_to_point(num_pair)
                num = TexMobject(str(val))
                num.scale_to_fit_height(
                    self.written_coordinate_height
                )
                num.shift(
                    point-num.get_corner(UP+LEFT),
                    self.written_coordinate_nudge
                )
                result.append(num)
        return result

    def get_axes(self):
        return self.axes

    def get_axis_labels(self, x_label = "x", y_label = "y"):
        x_axis, y_axis = self.get_axes().split()
        x_label_mob = TexMobject(x_label)
        y_label_mob = TexMobject(y_label)
        x_label_mob.next_to(x_axis, DOWN)
        x_label_mob.to_edge(RIGHT)
        y_label_mob.next_to(y_axis, RIGHT)
        y_label_mob.to_edge(UP)
        return VMobject(x_label_mob, y_label_mob)


    def add_coordinates(self, x_vals = None, y_vals = None):
        self.add(*self.get_coordinate_labels(x_vals, y_vals))
        return self

    def get_vector(self, coords, **kwargs):
        point = coords[0]*RIGHT + coords[1]*UP
        arrow = Arrow(ORIGIN, coords, **kwargs)
        return arrow

    def prepare_for_nonlinear_transform(self, num_inserted_anchor_points = 50):
        for mob in self.family_members_with_points():
            mob.insert_n_anchor_points(num_inserted_anchor_points)
            mob.make_smooth()
        return self
Exemplo n.º 31
0
class NumberPlane(VMobject):
    CONFIG = {
        "color" : BLUE_D,
        "secondary_color" : BLUE_E,
        "axes_color" : WHITE,
        "secondary_stroke_width" : 1,
        "x_radius": None,
        "y_radius": None,
        "x_unit_size" : 1,
        "y_unit_size" : 1,
        "center_point" : ORIGIN,
        "x_line_frequency" : 1,
        "y_line_frequency" : 1,
        "secondary_line_ratio" : 1,
        "written_coordinate_height" : 0.2,
        "propogate_style_to_family" : False,
    }
    
    def generate_points(self):
        if self.x_radius is None:
            center_to_edge = (SPACE_WIDTH + abs(self.center_point[0])) 
            self.x_radius = center_to_edge / self.x_unit_size
        if self.y_radius is None:
            center_to_edge = (SPACE_HEIGHT + abs(self.center_point[1])) 
            self.y_radius = center_to_edge / self.y_unit_size
        self.axes = VMobject()
        self.main_lines = VMobject()
        self.secondary_lines = VMobject()
        tuples = [
            (
                self.x_radius, 
                self.x_line_frequency, 
                self.y_radius*DOWN, 
                self.y_radius*UP,
                RIGHT
            ),
            (
                self.y_radius, 
                self.y_line_frequency, 
                self.x_radius*LEFT, 
                self.x_radius*RIGHT,
                UP,
            ),
        ]
        for radius, freq, start, end, unit in tuples:
            main_range = np.arange(0, radius, freq)
            step = freq/float(freq + self.secondary_line_ratio)
            for v in np.arange(0, radius, step):
                line1 = Line(start+v*unit, end+v*unit)
                line2 = Line(start-v*unit, end-v*unit)                
                if v == 0:
                    self.axes.add(line1)
                elif v in main_range:
                    self.main_lines.add(line1, line2)
                else:
                    self.secondary_lines.add(line1, line2)
        self.add(self.secondary_lines, self.main_lines, self.axes)
        self.stretch(self.x_unit_size, 0)
        self.stretch(self.y_unit_size, 1)
        self.shift(self.center_point)
        #Put x_axis before y_axis
        y_axis, x_axis = self.axes.split()
        self.axes = VMobject(x_axis, y_axis)

    def init_colors(self):
        VMobject.init_colors(self)
        self.axes.set_stroke(self.axes_color, self.stroke_width)
        self.main_lines.set_stroke(self.color, self.stroke_width)
        self.secondary_lines.set_stroke(
            self.secondary_color, self.secondary_stroke_width
        )
        return self

    def get_center_point(self):
        return self.coords_to_point(0, 0)

    def coords_to_point(self, x, y):
        x, y = np.array([x, y])
        result = self.axes.get_center()
        result += x*self.get_x_unit_size()*RIGHT
        result += y*self.get_y_unit_size()*UP
        return result

    def point_to_coords(self, point):
        new_point = point - self.axes.get_center()
        x = new_point[0]/self.get_x_unit_size()
        y = new_point[1]/self.get_y_unit_size()
        return x, y

    def get_x_unit_size(self):
        return self.axes.get_width() / (2.0*self.x_radius)

    def get_y_unit_size(self):
        return self.axes.get_height() / (2.0*self.y_radius)

    def get_coordinate_labels(self, x_vals = None, y_vals = None):
        result = []
        if x_vals == None and y_vals == None:
            x_vals = range(-int(self.x_radius), int(self.x_radius))
            y_vals = range(-int(self.y_radius), int(self.y_radius))
        for index, vals in enumerate([x_vals, y_vals]):
            num_pair = [0, 0]
            for val in vals:
                if val == 0:
                    continue
                num_pair[index] = val
                point = self.coords_to_point(*num_pair)
                num = TexMobject(str(val))
                num.add_background_rectangle()
                num.scale_to_fit_height(
                    self.written_coordinate_height
                )
                vect = DOWN if index == 0 else LEFT
                num.next_to(point, vect, buff = SMALL_BUFF)
                result.append(num)
        return result

    def get_axes(self):
        return self.axes

    def get_axis_labels(self, x_label = "x", y_label = "y"):
        x_axis, y_axis = self.get_axes().split()
        quads = [
            (x_axis, x_label, UP, RIGHT),
            (y_axis, y_label, RIGHT, UP),
        ]
        labels = VGroup()
        for axis, tex, vect, edge in quads:
            label = TexMobject(tex)
            label.add_background_rectangle()
            label.next_to(axis, vect)
            label.to_edge(edge)
            labels.add(label)
        self.axis_labels = labels
        return labels

    def add_coordinates(self, x_vals = None, y_vals = None):
        self.add(*self.get_coordinate_labels(x_vals, y_vals))
        return self

    def get_vector(self, coords, **kwargs):
        point = coords[0]*RIGHT + coords[1]*UP
        arrow = Arrow(ORIGIN, coords, **kwargs)
        return arrow

    def prepare_for_nonlinear_transform(self, num_inserted_anchor_points = 50):
        for mob in self.family_members_with_points():
            num_anchors = mob.get_num_anchor_points()
            if num_inserted_anchor_points > num_anchors:
                mob.insert_n_anchor_points(num_inserted_anchor_points-num_anchors)
                mob.make_smooth()
        return self
Exemplo n.º 32
0
    def construct(self):
        vector = Vector([-2, 3])
        plane = NumberPlane()
        axis_labels = plane.get_axis_labels()
        other_vectors = VMobject(*map(Vector, [
            [1, 2], [2, -1], [4, 0]
        ]))
        colors = [GREEN_B, MAROON_B, PINK]
        for v, color in zip(other_vectors.split(), colors):
            v.highlight(color)
        shift_val = 4*RIGHT+DOWN

        dot = Dot(radius = 0.1)
        dot.highlight(RED)
        tail_word = TextMobject("Tail")
        tail_word.shift(0.5*DOWN+2.5*LEFT)
        line = Line(tail_word, dot)

        self.play(ShowCreation(vector, submobject_mode = "one_at_a_time"))
        self.dither(2)
        self.play(
            ShowCreation(plane, summobject_mode = "lagged_start"),
            Animation(vector)
        )
        self.play(Write(axis_labels, run_time = 1))
        self.dither()
        self.play(
            GrowFromCenter(dot),
            ShowCreation(line),
            Write(tail_word, run_time = 1)
        )
        self.dither()
        self.play(
            FadeOut(tail_word),
            ApplyMethod(VMobject(dot, line).scale, 0.01) 
        )
        self.remove(tail_word, line, dot)
        self.dither()

        self.play(ApplyMethod(
            vector.shift, shift_val,
            path_arc = 3*np.pi/2,
            run_time = 3
        ))
        self.play(ApplyMethod(
            vector.shift, -shift_val,
            rate_func = rush_into,
            run_time = 0.5
        ))
        self.dither(3)

        self.play(ShowCreation(
            other_vectors, 
            submobject_mode = "one_at_a_time",
            run_time = 3
        ))
        self.dither(3)

        x_axis, y_axis = plane.get_axes().split()
        x_label = axis_labels.split()[0]
        x_axis = x_axis.copy()
        x_label = x_label.copy()
        everything = VMobject(*self.mobjects)
        self.play(
            FadeOut(everything),
            Animation(x_axis), Animation(x_label)
        )
Exemplo n.º 33
0
class PiCreature(SVGMobject):
    CONFIG = {
        "color": BLUE_E,
        "stroke_width": 0,
        "fill_opacity": 1.0,
        "initial_scale_factor": 0.01,
        "corner_scale_factor": 0.75,
        "flip_at_start": False,
        "is_looking_direction_purposeful": False,
        "start_corner": None,
    }

    def __init__(self, mode="plain", **kwargs):
        self.parts_named = False
        svg_file = os.path.join(PI_CREATURE_DIR, "PiCreatures_%s.svg" % mode)
        digest_config(self, kwargs, locals())
        SVGMobject.__init__(self, svg_file, **kwargs)
        self.init_colors()
        if self.flip_at_start:
            self.flip()
        if self.start_corner is not None:
            self.to_corner(self.start_corner)

    def name_parts(self):
        self.mouth = self.submobjects[MOUTH_INDEX]
        self.body = self.submobjects[BODY_INDEX]
        self.pupils = VMobject(*[
            self.submobjects[LEFT_PUPIL_INDEX],
            self.submobjects[RIGHT_PUPIL_INDEX]
        ])
        self.eyes = VMobject(*[
            self.submobjects[LEFT_EYE_INDEX], self.submobjects[RIGHT_EYE_INDEX]
        ])
        self.submobjects = []
        self.add(self.body, self.mouth, self.eyes, self.pupils)
        self.parts_named = True

    def init_colors(self):
        self.set_stroke(color=BLACK, width=self.stroke_width)
        if not self.parts_named:
            self.name_parts()
        self.mouth.set_fill(BLACK, opacity=1)
        self.body.set_fill(self.color, opacity=1)
        self.pupils.set_fill(BLACK, opacity=1)
        self.eyes.set_fill(WHITE, opacity=1)
        return self

    def highlight(self, color):
        self.body.set_fill(color)
        return self

    def change_mode(self, mode):
        curr_eye_center = self.eyes.get_center()
        curr_height = self.get_height()
        should_be_flipped = self.is_flipped()
        should_look = hasattr(self, "purposeful_looking_direction")
        if should_look:
            looking_direction = self.purposeful_looking_direction
        self.__init__(mode)
        self.scale_to_fit_height(curr_height)
        self.shift(curr_eye_center - self.eyes.get_center())
        if should_be_flipped ^ self.is_flipped():
            self.flip()
        if should_look:
            self.look(looking_direction)
        return self

    def look(self, direction):
        direction = direction / np.linalg.norm(direction)
        self.purposeful_looking_direction = direction
        for pupil, eye in zip(self.pupils.split(), self.eyes.split()):
            pupil_radius = pupil.get_width() / 2.
            eye_radius = eye.get_width() / 2.
            pupil.move_to(eye)
            if direction[1] < 0:
                pupil.shift(pupil_radius * DOWN / 3)
            pupil.shift(direction * (eye_radius - pupil_radius))
            bottom_diff = eye.get_bottom()[1] - pupil.get_bottom()[1]
            if bottom_diff > 0:
                pupil.shift(bottom_diff * UP)
        return self

    def look_at(self, point_or_mobject):
        if isinstance(point_or_mobject, Mobject):
            point = point_or_mobject.get_center()
        else:
            point = point_or_mobject
        self.look(point - self.eyes.get_center())
        return self

    def get_looking_direction(self):
        return np.sign(
            np.round(self.pupils.get_center() - self.eyes.get_center(),
                     decimals=2))

    def is_flipped(self):
        return self.eyes.submobjects[0].get_center()[0] > \
               self.eyes.submobjects[1].get_center()[0]

    def blink(self):
        eye_bottom_y = self.eyes.get_bottom()[1]
        for mob in self.eyes, self.pupils:
            mob.apply_function(lambda p: [p[0], eye_bottom_y, p[2]])
        return self

    def to_corner(self, vect=None):
        if vect is not None:
            SVGMobject.to_corner(self, vect)
        else:
            self.scale(self.corner_scale_factor)
            self.to_corner(DOWN + LEFT)
        return self

    def get_bubble(self, bubble_type="thought", **kwargs):
        if bubble_type == "thought":
            bubble = ThoughtBubble(**kwargs)
        elif bubble_type == "speech":
            bubble = SpeechBubble(**kwargs)
        else:
            raise Exception("%s is an invalid bubble type" % bubble_type)
        bubble.pin_to(self)
        return bubble
Exemplo n.º 34
0
class PiCreature(SVGMobject):
    CONFIG = {
        "color" : BLUE_E,
        "stroke_width" : 0,
        "fill_opacity" : 1.0,
        "initial_scale_factor" : 0.01,
        "corner_scale_factor" : 0.75,
        "flip_at_start" : False,
        "is_looking_direction_purposeful" : False,
    }
    def __init__(self, mode = "plain", **kwargs):
        self.parts_named = False
        svg_file = os.path.join(
            PI_CREATURE_DIR, 
            "PiCreatures_%s.svg"%mode
        )
        digest_config(self, kwargs, locals())
        SVGMobject.__init__(self, svg_file, **kwargs)
        self.init_colors()
        if self.flip_at_start:
            self.flip()

    def name_parts(self):
        self.mouth = self.submobjects[MOUTH_INDEX]
        self.body = self.submobjects[BODY_INDEX]
        self.pupils = VMobject(*[
            self.submobjects[LEFT_PUPIL_INDEX],
            self.submobjects[RIGHT_PUPIL_INDEX]
        ])
        self.eyes = VMobject(*[
            self.submobjects[LEFT_EYE_INDEX],
            self.submobjects[RIGHT_EYE_INDEX]
        ])
        self.submobjects = []
        self.add(self.body, self.mouth, self.eyes, self.pupils)
        self.parts_named = True

    def init_colors(self):
        self.set_stroke(color = BLACK, width = self.stroke_width)
        if not self.parts_named:
            self.name_parts()
        self.mouth.set_fill(BLACK, opacity = 1)
        self.body.set_fill(self.color, opacity = 1)
        self.pupils.set_fill(BLACK, opacity = 1)
        self.eyes.set_fill(WHITE, opacity = 1)
        return self


    def highlight(self, color):
        self.body.set_fill(color)
        return self

    def move_to(self, destination):
        self.shift(destination-self.get_bottom())
        return self

    def change_mode(self, mode):
        curr_center = self.get_center()
        curr_height = self.get_height()
        should_be_flipped = self.is_flipped()        
        if self.is_looking_direction_purposeful:
            looking_direction = self.get_looking_direction()
        self.__init__(mode)
        self.scale_to_fit_height(curr_height)
        self.shift(curr_center)
        if should_be_flipped ^ self.is_flipped():
            self.flip()
        if self.is_looking_direction_purposeful:
            self.look(looking_direction)
        return self

    def look(self, direction):
        self.is_looking_direction_purposeful = True
        x, y = direction[:2]        
        for pupil, eye in zip(self.pupils.split(), self.eyes.split()):
            pupil.move_to(eye, aligned_edge = direction)
            #Some hacky nudging is required here
            if y > 0 and x != 0: # Look up and to a side
                nudge_size = pupil.get_height()/4.
                if x > 0: 
                    nudge = nudge_size*(DOWN+LEFT)
                else:
                    nudge = nudge_size*(DOWN+RIGHT)
                pupil.shift(nudge)
            elif y < 0:
                nudge_size = pupil.get_height()/8.
                pupil.shift(nudge_size*UP)
        return self


    def get_looking_direction(self):
        return np.sign(np.round(
            self.pupils.get_center() - self.eyes.get_center(),
            decimals = 2
        ))

    def is_flipped(self):
        return self.eyes.submobjects[0].get_center()[0] > \
               self.eyes.submobjects[1].get_center()[0]

    def blink(self):
        eye_bottom_y = self.eyes.get_bottom()[1]
        for mob in self.eyes, self.pupils:
            mob.apply_function(
                lambda p : [p[0], eye_bottom_y, p[2]]
            )
        return self

    def to_corner(self, vect = None):
        if vect is not None:
            SVGMobject.to_corner(self, vect)
        else:
            self.scale(self.corner_scale_factor)
            self.to_corner(DOWN+LEFT)
        return self

    def get_bubble(self, bubble_type = "thought", **kwargs):
        if bubble_type == "thought":
            bubble = ThoughtBubble(**kwargs)
        elif bubble_type == "speech":
            bubble = SpeechBubble(**kwargs)
        else:
            raise Exception("%s is an invalid bubble type"%bubble_type)
        bubble.pin_to(self)
        return bubble