예제 #1
0
    def coords_to_vector(self,
                         vector,
                         coords_start=2 * RIGHT + 2 * UP,
                         clean_up=True):
        starting_mobjects = list(self.mobjects)
        array = Matrix(vector)
        array.shift(coords_start)
        arrow = Vector(vector)
        x_line = Line(ORIGIN, vector[0] * RIGHT)
        y_line = Line(x_line.get_end(), arrow.get_end())
        x_line.set_color(X_COLOR)
        y_line.set_color(Y_COLOR)
        x_coord, y_coord = array.get_mob_matrix().flatten()

        self.play(Write(array, run_time=1))
        self.wait()
        self.play(
            ApplyFunction(
                lambda x: self.position_x_coordinate(x, x_line, vector),
                x_coord))
        self.play(ShowCreation(x_line))
        self.play(
            ApplyFunction(
                lambda y: self.position_y_coordinate(y, y_line, vector),
                y_coord), FadeOut(array.get_brackets()))
        y_coord, brackets = self.get_mobjects_from_last_animation()
        self.play(ShowCreation(y_line))
        self.play(ShowCreation(arrow))
        self.wait()
        if clean_up:
            self.clear()
            self.add(*starting_mobjects)
예제 #2
0
    def add_lines(self, left, right):
        line_kwargs = {
            "color": BLUE,
            "stroke_width": 2,
        }
        left_rows = [VGroup(*row) for row in left.get_mob_matrix()]
        h_lines = VGroup()
        for row in left_rows[:-1]:
            h_line = Line(row.get_left(), row.get_right(), **line_kwargs)
            h_line.next_to(row, DOWN, buff=left.v_buff / 2.)
            h_lines.add(h_line)

        right_cols = [
            VGroup(*col) for col in np.transpose(right.get_mob_matrix())
        ]
        v_lines = VGroup()
        for col in right_cols[:-1]:
            v_line = Line(col.get_top(), col.get_bottom(), **line_kwargs)
            v_line.next_to(col, RIGHT, buff=right.h_buff / 2.)
            v_lines.add(v_line)

        self.play(ShowCreation(h_lines))
        self.play(ShowCreation(v_lines))
        self.wait()
        self.show_frame()
예제 #3
0
    def construct(self):
        # Setup
        pos_axis = NumberLine(x_min=-3.5, x_max=3.5, color=WHITE)
        pos_axis.rotate(np.pi / 2)
        pos_axis.add_tip()
        time_axis = NumberLine(x_min=0, x_max=9.5, color=WHITE)
        time_axis.add_tip()
        house = House()
        house.rotate(np.pi / 2)
        house.place_on(pos_axis.number_to_point(0))
        zero_drunk = Drunk(direction=UP, color=self.zero_color)
        zero_drunk.step_on(pos_axis.number_to_point(0))
        neg_drunk = Drunk(direction=UP, color=self.neg_color)
        neg_drunk.step_on(pos_axis.number_to_point(0))
        group = VGroup(house, VGroup(pos_axis, time_axis), zero_drunk,
                       neg_drunk)
        group.to_edge(LEFT)
        pos_text = TextMobject("位置")
        pos_text.next_to(pos_axis.number_to_point(3.5), LEFT)
        time_text = TextMobject("时间")
        time_text.next_to(time_axis.number_to_point(9.5), DOWN)
        self.add(group, pos_text, time_text)
        old_zero_drunk = zero_drunk.copy()
        old_neg_drunk = neg_drunk.copy()

        # Start Wandering
        zero_sequence = "UUUDDDDU"
        zero_walk = RandomWalk1DArrow(
            zero_sequence,
            up_color=self.zero_color,
            down_color=self.zero_color,
        )
        zero_walk.move_start_to(pos_axis.number_to_point(0))
        neg_sequence = "DDUDDUDU"
        neg_walk = RandomWalk1DArrow(
            neg_sequence,
            up_color=self.neg_color,
            down_color=self.neg_color,
        )
        neg_walk.move_start_to(pos_axis.number_to_point(0))
        for k, (zero_char,
                neg_char) in enumerate(zip(zero_sequence, neg_sequence)):
            zero_increment = 1 if zero_char == "U" else -1
            neg_increment = 1 if neg_char == "U" else -1
            zero_arrow = zero_walk.get_arrow_by_number(k)
            neg_arrow = neg_walk.get_arrow_by_number(k)
            self.play(DrunkWander(zero_drunk, zero_increment, direction=UP),
                      DrunkWander(neg_drunk, neg_increment, direction=UP),
                      ShowCreation(zero_arrow), ShowCreation(neg_arrow))
        self.wait()

        # Reset
        self.play(
            Transform(zero_drunk, old_zero_drunk),
            Transform(neg_drunk, old_neg_drunk),
            FadeOut(zero_walk),
            FadeOut(neg_walk),
        )
        self.wait()
예제 #4
0
    def vector_to_coords(self, vector, integer_labels=True, clean_up=True):
        starting_mobjects = list(self.mobjects)
        show_creation = False
        if isinstance(vector, Arrow):
            arrow = vector
            vector = arrow.get_end()[:2]
        else:
            arrow = Vector(vector)
            show_creation = True
        array = vector_coordinate_label(arrow, integer_labels=integer_labels)
        x_line = Line(ORIGIN, vector[0] * RIGHT)
        y_line = Line(x_line.get_end(), arrow.get_end())
        x_line.set_color(X_COLOR)
        y_line.set_color(Y_COLOR)
        x_coord, y_coord = array.get_mob_matrix().flatten()
        x_coord_start = self.position_x_coordinate(
            x_coord.copy(), x_line, vector
        )
        y_coord_start = self.position_y_coordinate(
            y_coord.copy(), y_line, vector
        )
        brackets = array.get_brackets()

        if show_creation:
            self.play(ShowCreation(arrow))
        self.play(
            ShowCreation(x_line),
            Write(x_coord_start),
            run_time=1
        )
        self.play(
            ShowCreation(y_line),
            Write(y_coord_start),
            run_time=1
        )
        self.wait()
        self.play(
            Transform(x_coord_start, x_coord, submobject_mode="all_at_once"),
            Transform(y_coord_start, y_coord, submobject_mode="all_at_once"),
            Write(brackets, run_time=1),
        )
        self.wait()

        self.remove(x_coord_start, y_coord_start, brackets)
        self.add(array)
        if clean_up:
            self.clear()
            self.add(*starting_mobjects)
        return array, x_line, y_line
예제 #5
0
 def add_vector(self, vector, color=YELLOW, animate=True, **kwargs):
     if not isinstance(vector, Arrow):
         vector = Vector(vector, color=color, **kwargs)
     if animate:
         self.play(ShowCreation(vector))
     self.add(vector)
     return vector
예제 #6
0
    def add_T_label(self,
                    x_val,
                    side=RIGHT,
                    label=None,
                    color=WHITE,
                    animated=False,
                    **kwargs):
        triangle = RegularPolygon(n=3, start_angle=np.pi / 2)
        triangle.scale_to_fit_height(MED_SMALL_BUFF)
        triangle.move_to(self.coords_to_point(x_val, 0), UP)
        triangle.set_fill(color, 1)
        triangle.set_stroke(width=0)
        if label == None:
            T_label = TexMobject(self.variable_point_label, fill_color=color)
        else:
            T_label = TexMobject(label, fill_color=color)

        T_label.next_to(triangle, DOWN)
        v_line = self.get_vertical_line_to_graph(x_val,
                                                 self.v_graph,
                                                 color=YELLOW)

        if animated:
            self.play(DrawBorderThenFill(triangle), ShowCreation(v_line),
                      Write(T_label, run_time=1), **kwargs)

        if np.all(side == LEFT):
            self.left_T_label_group = VGroup(T_label, triangle)
            self.left_v_line = v_line
            self.add(self.left_T_label_group, self.left_v_line)
        elif np.all(side == RIGHT):
            self.right_T_label_group = VGroup(T_label, triangle)
            self.right_v_line = v_line
            self.add(self.right_T_label_group, self.right_v_line)
예제 #7
0
    def update_labels(self, new_labels, **kwargs):
        assert (type(new_labels) == OrderedDict)
        # make sure labels are different
        for old_label in self.labels.values():
            for new_label in new_labels.values():
                assert (id(old_label) != id(new_label))

        anims = []
        # delete
        for key, val in new_labels.items():
            if val is None:
                anims.append(Uncreate(self.labels[key]))
                self.remove(self.labels[key])
                del new_labels[key]
                del self.labels[key]

        # scale
        for label in new_labels.values():
            if type(label) == Arrow:
                continue  # TODO
            scale_factor = self.get_label_scale_factor(label, len(new_labels))
            label.scale(scale_factor)

        # place
        new_labels = self.place_labels(new_labels, **kwargs)

        # animate
        if "animate" not in kwargs or kwargs["animate"]:
            for name in new_labels.keys():
                if name in self.labels:
                    anims.extend([
                        ReplacementTransform(self.labels[name],
                                             new_labels[name],
                                             parent=self)
                    ])
                else:
                    anims.extend([ShowCreation(new_labels[name])])
                    self.add(new_labels[name])
            for name in self.labels:
                if name not in new_labels:
                    anims.extend([Uncreate(self.labels[name])])
                    self.remove(self.labels[name])
        else:
            for name in new_labels.keys():
                if name not in self.labels:
                    self.add(new_labels[name])
                else:
                    self.add(new_labels[name])
                    self.remove(self.labels[name])
            for name in self.labels:
                if name not in new_labels:
                    self.remove(self.labels[name])
        self.labels = new_labels
        return anims
예제 #8
0
    def construct(self):
        # Setup
        self.set_camera_orientation(phi = np.pi/3, theta = 3*np.pi/4)
        self.begin_ambient_camera_rotation(np.pi/50)

        # Part 1: Increasing the order
        for order in range(1, self.max_order+1):
            if order == 1:
                fractal = HilbertCurve3D(order = 1)
                self.play(ShowCreation(fractal), run_time = 2)
                cur_order = fractal.order
            else:
                new_fractal = HilbertCurve3D(order = cur_order + 1)
                self.play(Transform(fractal, new_fractal))
                cur_order = new_fractal.order
                self.wait(2)
        self.wait(5)
        self.play(FadeOut(fractal))
        self.wait(3)

        # Part 2: Show one-touch construction
        self.play(ShowCreation(fractal, run_time = 60))
        self.wait(5)

        # Part 3: Decreasing the order till it vanishes
        for k in reversed(range(1, self.max_order)):
            new_fractal = HilbertCurve3D(order = cur_order - 1)
            self.play(Transform(fractal, new_fractal))
            cur_order = new_fractal.order
            self.wait(2)
        self.play(Uncreate(fractal), run_time = 1)

        # The end
        self.stop_ambient_camera_rotation()
        self.set_camera_orientation(phi = 0, theta = -np.pi/2)
        author = TextMobject("@Solara570")
        author.scale(1.5)
        author.to_corner(RIGHT+DOWN)
        self.play(FadeIn(author), run_time = 1)
        self.wait(2)
예제 #9
0
 def add_unit_square(self, color=YELLOW, opacity=0.3, animate=False):
     square = Square(color=color, side_length=1)
     square.shift(-square.get_corner(DOWN + LEFT))
     if animate:
         added_anims = map(Animation, self.moving_vectors)
         self.play(ShowCreation(square), *added_anims)
         self.play(square.set_fill, color, opacity, *added_anims)
     else:
         square.set_fill(color, opacity)
     self.add_transformable_mobject(square)
     self.bring_to_front(*self.moving_vectors)
     self.square = square
     return self
예제 #10
0
 def get_digit_increment_animations(self):
     result = []
     self.number += 1
     is_next_digit = self.is_next_digit()
     if is_next_digit: self.max_place += 1
     new_number_mob = self.get_number_mob(self.number)
     new_number_mob.move_to(self.number_mob, RIGHT)
     if is_next_digit:
         self.add_configuration()
         place = len(new_number_mob.split()) - 1
         result.append(FadeIn(self.dot_templates[place]))
         arrow = Arrow(new_number_mob[place].get_top(),
                       self.dot_templates[place].get_bottom(),
                       color=self.digit_place_colors[place])
         self.arrows.add(arrow)
         result.append(ShowCreation(arrow))
     result.append(
         Transform(self.number_mob,
                   new_number_mob,
                   submobject_mode="lagged_start"))
     return result
예제 #11
0
 def place_cursors(self, indices=None, block=None):
     """
     place cursors on the blocks denoted by indices if it was passed,
     otherwise the blocks denoted by self.cursor_indices
     """
     if indices is None and len(self.cursor_indices) == 0:
         raise Exception("no indices to use")
     elif indices is None:
         indices = self.cursor_indices
     if block is None:
         cur_block = self
     else:
         cur_block = block
     cursors = []
     for block_idx in indices:
         cur_block = cur_block.submobjects[block_idx]
         cursor = TexMobject("\\blacktriangleright")
         cursor.next_to(cur_block[0], LEFT)
         cursors.append(cursor)
     self.cursors.extend(cursors)
     return [ShowCreation(Group(*cursors))]
예제 #12
0
    def construct(self):
        # Setup
        pos_axis = NumberLine(x_min=-3.5, x_max=3.5, color=WHITE)
        pos_axis.rotate(np.pi / 2)
        pos_axis.add_tip()
        time_axis = NumberLine(x_min=0, x_max=9.5, color=WHITE)
        time_axis.add_tip()
        house = House()
        house.rotate(np.pi / 2)
        house.place_on(pos_axis.number_to_point(0))
        drunk = Drunk(direction=UP)
        drunk.step_on(pos_axis.number_to_point(0))
        group = VGroup(house, VGroup(pos_axis, time_axis), drunk)
        group.to_edge(LEFT)
        pos_text = TextMobject("位置")
        pos_text.next_to(pos_axis.number_to_point(3.5), LEFT)
        time_text = TextMobject("时间")
        time_text.next_to(time_axis.number_to_point(9.5), DOWN)
        self.add(group, pos_text, time_text)
        old_drunk = drunk.copy()

        # Start Wandering
        sequence = "UDUDDDUD"
        random_walk = RandomWalk1DArrow(sequence)
        random_walk.move_start_to(pos_axis.number_to_point(0))
        for k, walk_char in enumerate(sequence):
            increment = 1 if walk_char == "U" else -1
            arrow = random_walk.get_arrow_by_number(k)
            self.play(
                DrunkWander(drunk, increment, direction=UP),
                ShowCreation(arrow),
            )
        self.wait()

        # Reset
        self.play(Transform(drunk, old_drunk), FadeOut(random_walk))
        self.wait()
예제 #13
0
 def add_axes(self, animate=False, color=WHITE, **kwargs):
     axes = Axes(color=color, tick_frequency=1)
     if animate:
         self.play(ShowCreation(axes, submobject_mode="one_at_a_time"))
     self.add(axes)
     return axes
예제 #14
0
 def add_plane(self, animate=False, **kwargs):
     plane = NumberPlane(**kwargs)
     if animate:
         self.play(ShowCreation(plane, submobject_mode="lagged_start"))
     self.add(plane)
     return plane
예제 #15
0
    def construct(self):
        # Setup
        axes_group = self.axes_group
        pos_axis, time_axis = axes_group[:2]
        title_pq = self.title_pq
        walk_q = self.walk_q
        parts_q = self.parts_q
        l_arrow = self.l_arrow
        self.add(axes_group, title_pq, walk_q, l_arrow)
        walk_q_copy = walk_q.copy()

        # Q_4 -> P_4
        steps_qp = VGroup(*[
            TextMobject(text) for text in [
                "1. 找到路径终点的位置坐标$h$", "2. 找到最晚一次穿过$\\frac{h}{2}$的时刻",
                "3. 在这个时刻上进行分割", "4. 将第一段水平翻转", "5. 拼接两个片段"
            ]
        ])
        for step in steps_qp:
            step.set_color(YELLOW)
            step.add_background_rectangle()
        step1_qp, step2_qp, step3_qp, step4_qp, step5_qp = steps_qp

        # 1. Find the endpoint
        step1_qp.next_to(time_axis.number_to_point(4.5), UP)
        end_horiz_line = DashedLine(LEFT_SIDE, RIGHT_SIDE, color=YELLOW)
        end_horiz_line.move_to(pos_axis.number_to_point(-4))
        end_horiz_line.horizontally_center()
        end_brace_line = DashedLine(time_axis.number_to_point(8),
                                    walk_q.get_end_point())
        end_brace = Brace(end_brace_line, direction=RIGHT, color=YELLOW)
        h = TexMobject("h").set_color(YELLOW)
        end_brace.put_at_tip(h)
        self.play(Write(step1_qp), ShowCreation(end_horiz_line), run_time=1)
        self.play(GrowFromCenter(end_brace), GrowFromCenter(h))
        self.wait(1.5)
        self.play(FadeOut(step1_qp))

        # 2. Find the last time it GOES THROUGH half its final value
        half_point = walk_q.get_arrow_end_point(3)
        step2_qp.next_to(time_axis.number_to_point(4.5), UP)
        half_horiz_line = end_horiz_line.copy().shift(2 * UP)
        half_brace_line = DashedLine(time_axis.number_to_point(4), half_point)
        half_brace = Brace(half_brace_line, direction=RIGHT, color=YELLOW)
        half_h = TexMobject("\\frac{h}{2}").set_color(YELLOW)
        half_brace.put_at_tip(half_h)
        half_dot = Dot(half_point, color=YELLOW)
        self.play(FadeIn(step2_qp), run_time=1)
        self.wait(0.5)
        self.play(
            ReplacementTransform(end_brace, half_brace),
            ReplacementTransform(end_horiz_line, half_horiz_line),
            ReplacementTransform(h, half_h[0]),
            Write(half_h[1:]),
        )
        self.play(DrawBorderThenFill(half_dot))
        self.wait(1.5)
        self.play(
            FadeOut(VGroup(step2_qp, half_horiz_line, half_brace, half_h)))

        # 3. Split
        vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW)
        vert_line.move_to(half_point)
        step3_qp.next_to(vert_line, UP)
        left_part_q, right_part_q = parts_q
        self.play(ShowCreation(vert_line), Write(step3_qp), run_time=1)
        self.play(
            FadeOut(half_dot),
            left_part_q.shift,
            0.5 * DOWN + 0.5 * LEFT,
            right_part_q.shift,
            0.5 * UP + 0.5 * RIGHT,
        )
        self.wait(1.5)
        self.play(FadeOut(vert_line), FadeOut(step3_qp))

        # 4. Flip the first segment horizontally
        flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY)
        flip_axis.move_to(left_part_q)
        step4_qp.next_to(flip_axis, DOWN)
        self.play(
            ShowCreation(flip_axis),
            Write(step4_qp),
            run_time=1,
        )
        self.play(
            left_part_q.flip,
            Animation(flip_axis),
        )
        self.wait(1.5)
        self.play(FadeOut(step4_qp), FadeOut(flip_axis))

        # 5. Put the pieces together
        step5_qp.shift(2.5 * DOWN)
        flip_arrow_anims = walk_q.get_flip_arrows_animation(3, color=ORANGE)
        self.play(Write(step5_qp), run_time=1)
        self.wait(0.5)
        self.play(flip_arrow_anims, right_part_q.set_color, ORANGE)
        self.wait(0.5)
        self.play(
            left_part_q.shift,
            2.5 * UP + 0.5 * RIGHT,
            right_part_q.shift,
            3.5 * UP + 0.5 * LEFT,
            Animation(step5_qp),
        )
        self.wait(0.5)
        self.play(FadeOut(step5_qp))
        self.wait(1.5)

        # Now Reset
        self.play(FadeOut(walk_q))
        self.play(FadeIn(walk_q_copy))
        self.wait()
예제 #16
0
    def construct(self):
        # Setup
        axes_group = self.axes_group
        title_pq = self.title_pq
        walk_p = self.walk_p
        parts_p = self.parts_p
        r_arrow = self.r_arrow
        self.add(axes_group, title_pq, walk_p, r_arrow)
        walk_p_copy = walk_p.copy()

        # P_4 -> Q_4
        steps_pq = VGroup(*[
            TextMobject(text) for text in [
                "1. 第一步是沿着正方向走的", "2. 找到第一次到达最大值的时刻", "3. 在这个时刻上进行分割",
                "4. 将第一段水平翻转", "5. 拼接两个片段"
            ]
        ])
        for step in steps_pq:
            step.set_color(YELLOW)
            step.add_background_rectangle()
        step1_pq, step2_pq, step3_pq, step4_pq, step5_pq = steps_pq

        # 1. Check the first step of the walk
        step1_circle = Circle(color=YELLOW)
        first_arrow = walk_p.get_arrow_by_number(0)
        step1_circle.surround(first_arrow)
        step1_pq.next_to(step1_circle, RIGHT + DOWN)
        self.play(ShowCreation(step1_circle), Write(step1_pq), run_time=1)
        self.wait(1.5)
        self.play(FadeOut(step1_circle), FadeOut(step1_pq))

        # 2. Find the first time it reaches the maximum
        peak = walk_p.get_arrow_end_point(3)
        horiz_line = DashedLine(2.5 * LEFT, 2.5 * RIGHT, color=YELLOW)
        horiz_line.move_to(peak)
        dot = Dot(color=YELLOW)
        dot.move_to(peak)
        step2_pq.next_to(horiz_line, UP)
        self.play(ShowCreation(horiz_line),
                  DrawBorderThenFill(dot),
                  Write(step2_pq),
                  run_time=1)
        self.wait(1.5)
        self.play(FadeOut(horiz_line), FadeOut(step2_pq))

        # 3. Split
        vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW)
        vert_line.move_to(peak)
        step3_pq.next_to(vert_line, DOWN)
        left_part_p, right_part_p = parts_p
        self.play(ShowCreation(vert_line), Write(step3_pq), run_time=1)
        self.play(
            FadeOut(dot),
            left_part_p.shift,
            0.5 * DOWN + 0.5 * LEFT,
            right_part_p.shift,
            DOWN + 0.5 * RIGHT,
        )
        self.wait(1.5)
        self.play(FadeOut(vert_line), FadeOut(step3_pq))

        # 4. Flip the first segment horizontally
        flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY)
        flip_axis.move_to(left_part_p)
        step4_pq.next_to(flip_axis, DOWN)
        self.play(
            ShowCreation(flip_axis),
            Write(step4_pq),
            run_time=1,
        )
        self.play(
            left_part_p.flip,
            Animation(flip_axis),
        )
        self.wait(1.5)
        self.play(FadeOut(step4_pq), FadeOut(flip_axis))

        # 5. Put the pieces together
        step5_pq.move_to(dot)
        flip_arrow_anims = walk_p.get_flip_arrows_animation(3, color=GREEN)
        self.play(Write(step5_pq), run_time=1)
        self.wait(0.5)
        self.play(flip_arrow_anims, right_part_p.set_color, GREEN)
        self.wait(0.5)
        self.play(
            left_part_p.shift,
            1.5 * DOWN + 0.5 * RIGHT,
            right_part_p.shift,
            3 * DOWN + 0.5 * LEFT,
            Animation(step5_pq),
        )
        self.wait(0.5)
        self.play(FadeOut(step5_pq))
        self.wait(1.5)

        # Now Reset
        self.play(FadeOut(walk_p))
        self.play(FadeIn(walk_p_copy))
        self.wait()