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()
Esempio n. 2
0
    def get_subdivision_braces_and_labels(
        self, parts, labels, direction,
        buff=SMALL_BUFF,
        min_num_quads=1
    ):
        label_mobs = VGroup()
        braces = VGroup()
        for label, part in zip(labels, parts):
            brace = Brace(
                part, direction,
                min_num_quads=min_num_quads,
                buff=buff
            )
            if isinstance(label, Mobject):
                label_mob = label
            else:
                label_mob = TexMobject(label)
                label_mob.scale(self.default_label_scale_val)
            label_mob.next_to(brace, direction, buff)

            braces.add(brace)
            label_mobs.add(label_mob)
        parts.braces = braces
        parts.labels = label_mobs
        parts.label_kwargs = {
            "labels": label_mobs.copy(),
            "direction": direction,
            "buff": buff,
        }
        return VGroup(parts.braces, parts.labels)
    def get_coordinate_labels(self, *numbers):
        # TODO: Should merge this with the code from NumberPlane.get_coordinate_labels

        result = VGroup()
        if len(numbers) == 0:
            numbers = range(-int(self.x_radius), int(self.x_radius) + 1)
            numbers += [
                complex(0, y)
                for y in range(-int(self.y_radius), int(self.y_radius) + 1)
            ]
        for number in numbers:
            if number == complex(0, 0):
                continue
            point = self.number_to_point(number)
            num_str = str(number).replace("j", "i")
            if num_str.startswith("0"):
                num_str = "0"
            elif num_str in ["1i", "-1i"]:
                num_str = num_str.replace("1", "")
            num_mob = TexMobject(num_str)
            num_mob.add_background_rectangle()
            num_mob.scale_to_fit_height(self.written_coordinate_height)
            num_mob.next_to(point, DOWN + LEFT, SMALL_BUFF)
            result.add(num_mob)
        self.coordinate_labels = result
        return result
Esempio n. 4
0
    def add_axes(self):
        x_axis = Line(self.tick_width * LEFT / 2, self.width * RIGHT)
        y_axis = Line(MED_LARGE_BUFF * DOWN, self.height * UP)
        ticks = VGroup()
        heights = np.linspace(0, self.height, self.n_ticks + 1)
        values = np.linspace(0, self.max_value, self.n_ticks + 1)
        for y, value in zip(heights, values):
            tick = Line(LEFT, RIGHT)
            tick.scale_to_fit_width(self.tick_width)
            tick.move_to(y * UP)
            ticks.add(tick)
        y_axis.add(ticks)

        self.add(x_axis, y_axis)
        self.x_axis, self.y_axis = x_axis, y_axis

        if self.label_y_axis:
            labels = VGroup()
            for tick, value in zip(ticks, values):
                label = TexMobject(str(np.round(value, 2)))
                label.scale_to_fit_height(self.y_axis_label_height)
                label.next_to(tick, LEFT, SMALL_BUFF)
                labels.add(label)
            self.y_axis_labels = labels
            self.add(labels)
Esempio n. 5
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()
    def setup_in_uv_space(self):
        u_min = self.u_min
        u_max = self.u_max
        u_res = self.u_resolution or self.resolution
        v_min = self.v_min
        v_max = self.v_max
        v_res = self.v_resolution or self.resolution

        u_values = np.linspace(u_min, u_max, u_res + 1)
        v_values = np.linspace(v_min, v_max, v_res + 1)
        faces = VGroup()
        for u1, u2 in zip(u_values[:-1], u_values[1:]):
            for v1, v2 in zip(v_values[:-1], v_values[1:]):
                piece = ThreeDVMobject()
                piece.set_points_as_corners([
                    [u1, v1, 0],
                    [u2, v1, 0],
                    [u2, v2, 0],
                    [u1, v2, 0],
                    [u1, v1, 0],
                ])
                faces.add(piece)
        faces.set_fill(color=self.fill_color, opacity=self.fill_opacity)
        faces.set_stroke(
            color=self.stroke_color,
            width=self.stroke_width,
            opacity=self.stroke_opacity,
        )
        self.add(*faces)
        if self.checkerboard_colors:
            self.set_fill_by_checkerboard(*self.checkerboard_colors)
Esempio n. 7
0
    def get_coordinate_labels(self, *numbers):
        # TODO: Should merge this with the code from NumberPlane.get_coordinate_labels

        result = VGroup()
        if len(numbers) == 0:
            numbers = list(range(-int(self.x_radius), int(self.x_radius) + 1))
            numbers += [
                complex(0, y) for y in range(-int(self.y_radius),
                                             int(self.y_radius) + 1) if y != 0
            ]
        for number in numbers:
            # if number == complex(0, 0):
            #     continue
            point = self.number_to_point(number)
            num_str = str(number).replace("j", "i")
            if num_str.startswith("0"):
                num_str = "0"
            elif num_str in ["1i", "-1i"]:
                num_str = num_str.replace("1", "")
            num_mob = TexMobject(num_str)
            num_mob.add_background_rectangle()
            num_mob.set_height(self.written_coordinate_height)
            num_mob.next_to(point, DOWN + LEFT, SMALL_BUFF)
            result.add(num_mob)
        self.coordinate_labels = result
        return result
Esempio n. 8
0
class DoubleArrow(Arrow):
    def init_tip(self):
        self.tip = VGroup()
        for b in True, False:
            t = self.add_tip(add_at_end=b)
            t.add_at_end = b
            self.tip.add(t)
        self.tip.match_style(self.tip[0])
Esempio n. 9
0
class DoubleArrow(Arrow):
    def init_tip(self):
        self.tip = VGroup()
        for b in True, False:
            t = self.add_tip(add_at_end=b)
            t.add_at_end = b
            self.tip.add(t)
        self.tip.match_style(self.tip[0])
 def get_transformer(self, **kwargs):
     transform_kwargs = dict(self.default_apply_complex_function_kwargs)
     transform_kwargs.update(kwargs)
     transformer = VGroup()
     if hasattr(self, "plane"):
         self.prepare_for_transformation(self.plane)
         transformer.add(self.plane)
     transformer.add(*self.transformable_mobjects)
     return transformer, transform_kwargs
Esempio n. 11
0
    def add_words(self):
        # Wallis product
        product = TexMobject(*(["\\text{Wallis公式:}"] + [
            "{%d \\over %d} \\," % (wallis_numer(n), wallis_denom(n))
            for n in range(1, 8)
        ] + ["\\cdots = {\\pi \\over 2}"])).set_color(YELLOW)
        rect = SurroundingRectangle(product, color=YELLOW, buff=0.25)
        wallis_product = VGroup(product, rect)
        wallis_product.set_width(6)

        # All those steps
        nums = [TextMobject("%d. " % k) for k in [1, 2, 3, 4]]
        words = [
            TextMobject(word) for word in [
                "构造合适的矩形边长",
                "同种颜色的矩形的面积之和恒为1",
                "整个图形又像一个${1 \\over 4}$圆,半径是",
                "比较${1 \\over 4}$圆与矩形的面积",
            ]
        ]
        formulae = [
            TextMobject(formula) for formula in [
                "$a_0 = 1,\\, a_n = {1 \\over 2} \cdot {3 \\over 4} \cdots {2n-1 \\over 2n} (n \geq 1)$",
                "$a_0 a_n + a_1 a_{n-1} + \\cdots + a_n a_0 = 1$",
                "$\\begin{aligned} \
                r_n & = a_0 + a_1 + \\cdots + a_{n-1} \\\\ \
                    & = \\textstyle{3 \\over 2} \cdot {5 \\over 4} \cdots {2n-1 \\over 2n-2} \
                    \\quad (n \geq 2) \
                \\end{aligned}$",
                "${1 \\over 4} \\pi {r_n}^2 \\approx n \\quad \\Rightarrow \\quad \\text{Wallis公式}$"
            ]
        ]

        steps = VGroup()
        for num, word, formula in zip(nums, words, formulae):
            num.next_to(word, LEFT)
            formula.next_to(word, DOWN, aligned_edge=LEFT)
            steps.add(VGroup(num, word, formula))
        steps.arrange_submobjects(DOWN, buff=0.6, aligned_edge=LEFT)
        steps.set_width(6)
        steps.next_to(wallis_product, DOWN)
        VGroup(wallis_product, steps).center().to_edge(RIGHT, buff=0.15)

        # Sep line and QED
        sep_line = DashedLine(2 * TOP, 2 * BOTTOM, color=GREY, buff=0.5)
        sep_line.next_to(steps, LEFT)
        qed = QEDSymbol(height=0.570 / 2)
        qed.next_to(steps[-1][-1][-1], RIGHT, aligned_edge=DOWN)

        # Add everything
        self.add(wallis_product, steps, sep_line, qed)
Esempio n. 12
0
 def get_number_mob(self, num):
     result = VGroup()
     place = 0
     max_place = self.max_place
     while place < max_place:
         digit = TexMobject(str(self.get_place_num(num, place)))
         if place >= len(self.digit_place_colors):
             self.digit_place_colors += self.digit_place_colors
         digit.set_color(self.digit_place_colors[place])
         digit.scale(self.num_scale_factor)
         digit.next_to(result, LEFT, buff=SMALL_BUFF, aligned_edge=DOWN)
         result.add(digit)
         place += 1
     return result
Esempio n. 13
0
    def get_riemann_rectangles(
        self,
        graph,
        x_min=None,
        x_max=None,
        dx=0.1,
        input_sample_type="left",
        stroke_width=1,
        stroke_color=BLACK,
        fill_opacity=1,
        start_color=None,
        end_color=None,
        show_signed_area=True,
        width_scale_factor=1.001
    ):
        x_min = x_min if x_min is not None else self.x_min
        x_max = x_max if x_max is not None else self.x_max
        if start_color is None:
            start_color = self.default_riemann_start_color
        if end_color is None:
            end_color = self.default_riemann_end_color
        rectangles = VGroup()
        x_range = np.arange(x_min, x_max, dx)
        colors = color_gradient([start_color, end_color], len(x_range))
        for x, color in zip(x_range, colors):
            if input_sample_type == "left":
                sample_input = x
            elif input_sample_type == "right":
                sample_input = x + dx
            elif input_sample_type == "center":
                sample_input = x + 0.5 * dx
            else:
                raise Exception("Invalid input sample type")
            graph_point = self.input_to_graph_point(sample_input, graph)
            points = VGroup(*list(map(VectorizedPoint, [
                self.coords_to_point(x, 0),
                self.coords_to_point(x + width_scale_factor * dx, 0),
                graph_point
            ])))

            rect = Rectangle()
            rect.replace(points, stretch=True)
            if graph_point[1] < self.graph_origin[1] and show_signed_area:
                fill_color = invert_color(color)
            else:
                fill_color = color
            rect.set_fill(fill_color, opacity=fill_opacity)
            rect.set_stroke(stroke_color, width=stroke_width)
            rectangles.add(rect)
        return rectangles
Esempio n. 14
0
 def generate_tower_tex_from_texts(self, texts):
     tower_tex = VGroup(*[
         TexMobject(text)
         for text in self.tower_texts
     ])
     if self.is_infinite:
         tower_tex.add(ExpDots(**self.expdots_config))
     for k, part in enumerate(tower_tex):
         part.scale(self.scale_factor**k)
         if k > 0:
             buff = 0.05 / np.sqrt(k)
             part.stretch(self.height_stretch_factor, 1)
             part.next_to(tower_tex[k-1], RIGHT+UP, buff = buff)
     return tower_tex
Esempio n. 15
0
    def get_division_along_dimension(self, p_list, dim, colors, vect):
        p_list = self.complete_p_list(p_list)
        colors = color_gradient(colors, len(p_list))

        last_point = self.get_edge_center(-vect)
        parts = VGroup()
        for factor, color in zip(p_list, colors):
            part = SampleSpace()
            part.set_fill(color, 1)
            part.replace(self, stretch=True)
            part.stretch(factor, dim)
            part.move_to(last_point, -vect)
            last_point = part.get_edge_center(vect)
            parts.add(part)
        return parts
 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
Esempio n. 17
0
 def get_number_mobjects(self, *numbers, **kwargs):
     # TODO, handle decimals
     if len(numbers) == 0:
         numbers = self.default_numbers_to_display()
     result = VGroup()
     for number in numbers:
         mob = DecimalNumber(number, **self.decimal_number_config)
         mob.scale(self.number_scale_val)
         mob.next_to(
             self.number_to_point(number),
             self.label_direction,
             self.line_to_number_buff,
         )
         result.add(mob)
     return result
Esempio n. 18
0
 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
Esempio n. 19
0
    def get_number_design(self, value, symbol):
        num = int(value)
        n_rows = {
            2: 2,
            3: 3,
            4: 2,
            5: 2,
            6: 3,
            7: 3,
            8: 3,
            9: 4,
            10: 4,
        }[num]
        n_cols = 1 if num in [2, 3] else 2
        insertion_indices = {
            5: [0],
            7: [0],
            8: [0, 1],
            9: [1],
            10: [0, 2],
        }.get(num, [])

        top = self.get_top() + symbol.get_height() * DOWN
        bottom = self.get_bottom() + symbol.get_height() * UP
        column_points = [
            interpolate(top, bottom, alpha)
            for alpha in np.linspace(0, 1, n_rows)
        ]

        design = VGroup(*[
            symbol.copy().move_to(point)
            for point in column_points
        ])
        if n_cols == 2:
            space = 0.2 * self.get_width()
            column_copy = design.copy().shift(space * RIGHT)
            design.shift(space * LEFT)
            design.add(*column_copy)
        design.add(*[
            symbol.copy().move_to(
                center_of_mass(column_points[i:i + 2])
            )
            for i in insertion_indices
        ])
        for symbol in design:
            if symbol.get_center()[1] < self.get_center()[1]:
                symbol.rotate_in_place(np.pi)
        return design
Esempio n. 20
0
    def get_number_design(self, value, symbol):
        num = int(value)
        n_rows = {
            2 : 2, 
            3 : 3, 
            4 : 2, 
            5 : 2, 
            6 : 3, 
            7 : 3, 
            8 : 3, 
            9 : 4, 
            10 : 4,
        }[num]
        n_cols = 1 if num in [2, 3] else 2
        insertion_indices = {
            5 : [0], 
            7 : [0], 
            8 : [0, 1], 
            9 : [1], 
            10 : [0, 2],
        }.get(num, [])

        top = self.get_top() + symbol.get_height()*DOWN
        bottom = self.get_bottom() + symbol.get_height()*UP
        column_points = [
            interpolate(top, bottom, alpha)
            for alpha in np.linspace(0, 1, n_rows)
        ]

        design = VGroup(*[
            symbol.copy().move_to(point)
            for point in column_points
        ])
        if n_cols == 2:
            space = 0.2*self.get_width()
            column_copy = design.copy().shift(space*RIGHT)
            design.shift(space*LEFT)
            design.add(*column_copy)
        design.add(*[
            symbol.copy().move_to(
                center_of_mass(column_points[i:i+2])
            )
            for i in insertion_indices
        ])
        for symbol in design:
            if symbol.get_center()[1] < self.get_center()[1]:
                symbol.rotate_in_place(np.pi)
        return design
Esempio n. 21
0
 def __init__(self, focal_point, **kwargs):
     digest_config(self, kwargs)
     circles = VGroup()
     for x in range(self.n_circles):
         circle = Circle(
             radius=self.big_radius,
             stroke_color=BLACK,
             stroke_width=0,
         )
         circle.move_to(focal_point)
         circle.save_state()
         circle.set_width(self.small_radius * 2)
         circle.set_stroke(self.color, self.start_stroke_width)
         circles.add(circle)
     LaggedStart.__init__(self, ApplyMethod, circles, lambda c:
                          (c.restore, ), **kwargs)
Esempio n. 22
0
 def get_number_mobjects(self, *numbers, **kwargs):
     # TODO, handle decimals
     if len(numbers) == 0:
         numbers = self.default_numbers_to_display()
     if "force_integers" in kwargs and kwargs["force_integers"]:
         numbers = list(map(int, numbers))
     result = VGroup()
     for number in numbers:
         mob = TexMobject(str(number))
         mob.scale(self.number_scale_val)
         mob.next_to(
             self.number_to_point(number),
             self.label_direction,
             self.line_to_number_buff,
         )
         result.add(mob)
     return result
Esempio n. 23
0
    def solve_the_equations(self):
        rects = VGroup(*[
            CoverRectangle(
                equation[0].get_exponent(), stroke_color = color,
                text = str(num), text_color = color
            )
            for equation, color, num in zip(self.equations, self.colors, self.nums)
        ])
        self.play(DrawBorderThenFill(rects))
        self.wait()

        sps = VGroup()
        for equation, num, color in zip(self.equations, self.nums, self.colors):
            sp = TexMobject("x", "^{%d}" % num, "=", "%d" % num)
            sp[1::2].set_color(color)
            sp.scale(2)
            sp.next_to(equation, DOWN, buff = 1)
            sps.add(sp)

        rss = VGroup()
        for num, sp, color in zip(self.nums, sps, self.colors):
            rs = TexMobject("x", "=", "%d" % num , "^{{1}\\over{%d}}" % num, "=\\sqrt{2}")
            for tex in (rs[2], rs[3][2]):
                tex.set_color(color)
            rs.match_height(sp).move_to(sp)
            rss.add(rs)

        tf_anims = []
        for sp, rs in zip(sps, rss):
            tf_anims.append(ReplacementTransform(sp[0], rs[0]))
            tf_anims.append(ReplacementTransform(sp[1], rs[3][2], path_arc = -TAU/4))
            tf_anims.append(ReplacementTransform(sp[2], rs[1]))
            tf_anims.append(ReplacementTransform(sp[3], rs[2]))
            tf_anims.append(Write(rs[3][:2]))

        self.play(FadeIn(sps))
        self.wait()
        self.play(AnimationGroup(*tf_anims), run_time = 2)
        self.wait()
        self.play(Write(VGroup(*[rs[4:] for rs in rss]), submobject_mode = "all_at_once"))
        self.wait()
        self.play(FadeOut(rects))
        self.wait()

        self.rss = rss
Esempio n. 24
0
 def __init__(self, focal_point, **kwargs):
     digest_config(self, kwargs)
     circles = VGroup()
     for x in range(self.n_circles):
         circle = Circle(
             radius=self.big_radius,
             stroke_color=BLACK,
             stroke_width=0,
         )
         circle.move_to(focal_point)
         circle.save_state()
         circle.scale_to_fit_width(self.small_radius * 2)
         circle.set_stroke(self.color, self.start_stroke_width)
         circles.add(circle)
     LaggedStart.__init__(
         self, ApplyMethod, circles,
         lambda c: (c.restore,),
         **kwargs
     )
Esempio n. 25
0
    def get_animation_integral_bounds_change(
        self,
        graph,
        new_t_min,
        new_t_max,
        fade_close_to_origin=True,
        run_time=1.0
    ):
        curr_t_min = self.x_axis.point_to_number(self.area.get_left())
        curr_t_max = self.x_axis.point_to_number(self.area.get_right())
        if new_t_min is None:
            new_t_min = curr_t_min
        if new_t_max is None:
            new_t_max = curr_t_max

        group = VGroup(self.area)
        group.add(self.left_v_line)
        group.add(self.left_T_label_group)
        group.add(self.right_v_line)
        group.add(self.right_T_label_group)

        def update_group(group, alpha):
            area, left_v_line, left_T_label, right_v_line, right_T_label = group
            t_min = interpolate(curr_t_min, new_t_min, alpha)
            t_max = interpolate(curr_t_max, new_t_max, alpha)
            new_area = self.get_area(graph, t_min, t_max)

            new_left_v_line = self.get_vertical_line_to_graph(
                t_min, graph
            )
            new_left_v_line.set_color(left_v_line.get_color())
            left_T_label.move_to(new_left_v_line.get_bottom(), UP)

            new_right_v_line = self.get_vertical_line_to_graph(
                t_max, graph
            )
            new_right_v_line.set_color(right_v_line.get_color())
            right_T_label.move_to(new_right_v_line.get_bottom(), UP)

            # Fade close to 0
            if fade_close_to_origin:
                if len(left_T_label) > 0:
                    left_T_label[0].set_fill(opacity=min(1, np.abs(t_min)))
                if len(right_T_label) > 0:
                    right_T_label[0].set_fill(opacity=min(1, np.abs(t_max)))

            Transform(area, new_area).update(1)
            Transform(left_v_line, new_left_v_line).update(1)
            Transform(right_v_line, new_right_v_line).update(1)
            return group

        return UpdateFromAlphaFunc(group, update_group, run_time=run_time)
Esempio n. 26
0
    def setup_in_uv_space(self):
        res = tuplify(self.resolution)
        if len(res) == 1:
            u_res = v_res = res[0]
        else:
            u_res, v_res = res
        u_min = self.u_min
        u_max = self.u_max
        v_min = self.v_min
        v_max = self.v_max

        u_values = np.linspace(u_min, u_max, u_res + 1)
        v_values = np.linspace(v_min, v_max, v_res + 1)
        faces = VGroup()
        for i in range(u_res):
            for j in range(v_res):
                u1, u2 = u_values[i:i + 2]
                v1, v2 = v_values[j:j + 2]
                face = ThreeDVMobject()
                face.set_points_as_corners([
                    [u1, v1, 0],
                    [u2, v1, 0],
                    [u2, v2, 0],
                    [u1, v2, 0],
                    [u1, v1, 0],
                ])
                faces.add(face)
                face.u_index = i
                face.v_index = j
                face.u1 = u1
                face.u2 = u2
                face.v1 = v1
                face.v2 = v2
        faces.set_fill(color=self.fill_color, opacity=self.fill_opacity)
        faces.set_stroke(
            color=self.stroke_color,
            width=self.stroke_width,
            opacity=self.stroke_opacity,
        )
        self.add(*faces)
        if self.checkerboard_colors:
            self.set_fill_by_checkerboard(*self.checkerboard_colors)
Esempio n. 27
0
 def get_coordinate_labels(self, x_vals=None, y_vals=None):
     coordinate_labels = VGroup()
     if x_vals is None:
         x_vals = list(range(-int(self.x_radius), int(self.x_radius) + 1))
     if y_vals is None:
         y_vals = list(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.set_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
Esempio n. 28
0
class RandomWalk1DLineAndDot(RandomWalk1D):
    CONFIG = {
        "dot_color": WHITE,
    }

    def generate_points(self):
        self.line_group = VGroup()
        self.dot_group = VGroup()
        vertices = self.generate_vertices_from_string(self.walk_string)
        for k in range(len(vertices) - 1):
            line = Line(vertices[k],
                        vertices[k + 1],
                        color=self.get_mob_color_by_number(k))
            dot = Dot(vertices[k], color=self.dot_color)
            self.line_group.add(line)
            self.dot_group.add(dot)
        self.dot_group.add(Dot(vertices[-1], color=self.dot_color))
        self.add(self.line_group, self.dot_group)
        self.horizontally_center()

    def get_line_by_number(self, n):
        return self.line_group[n]

    def get_dots_by_number(self, n):
        return VGroup(self.dot_group[n:n + 2])

    def get_mob_color_by_number(self, n):
        return self.up_color if self.walk_string[
            n] == self.up_char else self.down_color

    def split_at(self, n):
        extra_dot = self.get_dots_by_number(n)[0].copy()
 def get_coordinate_labels(self, x_vals=None, y_vals=None):
     coordinate_labels = VGroup()
     if x_vals is None:
         x_vals = range(-int(self.x_radius), int(self.x_radius) + 1)
     if y_vals is 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
Esempio n. 30
0
    def add_bars(self, values):
        buff = float(self.width) / (2 * len(values) + 1)
        bars = VGroup()
        for i, value in enumerate(values):
            bar = Rectangle(
                height=(value / self.max_value) * self.height,
                width=buff,
                stroke_width=self.bar_stroke_width,
                fill_opacity=self.bar_fill_opacity,
            )
            bar.move_to((2 * i + 1) * buff * RIGHT, DOWN + LEFT)
            bars.add(bar)
        bars.set_color_by_gradient(*self.bar_colors)

        bar_labels = VGroup()
        for bar, name in zip(bars, self.bar_names):
            label = TexMobject(str(name))
            label.scale(self.bar_label_scale_val)
            label.next_to(bar, DOWN, SMALL_BUFF)
            bar_labels.add(label)

        self.add(bars, bar_labels)
        self.bars = bars
        self.bar_labels = bar_labels
Esempio n. 31
0
    def get_animation_integral_bounds_change(self,
                                             graph,
                                             new_t_min,
                                             new_t_max,
                                             run_time=1.0):
        curr_t_min = self.x_axis.point_to_number(self.area.get_left())
        curr_t_max = self.x_axis.point_to_number(self.area.get_right())
        if new_t_min is None:
            new_t_min = curr_t_min
        if new_t_max is None:
            new_t_max = curr_t_max

        group = VGroup(self.area)
        if hasattr(self, "right_v_line"):
            group.add(self.right_v_line)
        else:
            group.add(VGroup())
        # because update_group expects 3 elements in group
        if hasattr(self, "T_label_group"):
            group.add(self.T_label_group)
        else:
            group.add(VGroup())

        def update_group(group, alpha):
            area, v_line, T_label = group
            t_min = interpolate(curr_t_min, new_t_min, alpha)
            t_max = interpolate(curr_t_max, new_t_max, alpha)
            new_area = self.get_area(graph, t_min, t_max)
            new_v_line = self.get_vertical_line_to_graph(t_max, graph)
            new_v_line.set_color(v_line.get_color())
            T_label.move_to(new_v_line.get_bottom(), UP)

            #Fade close to 0
            if len(T_label) > 0:
                T_label[0].set_fill(opacity=min(1, t_max))

            Transform(area, new_area).update(1)
            Transform(v_line, new_v_line).update(1)
            return group

        return UpdateFromAlphaFunc(group, update_group, run_time=run_time)
Esempio n. 32
0
class Arrow(Line):
    CONFIG = {
        "tip_length": 0.25,
        "tip_width_to_length_ratio": 1,
        "max_tip_length_to_length_ratio": 0.35,
        "max_stem_width_to_tip_width_ratio": 0.3,
        "buff": MED_SMALL_BUFF,
        "propagate_style_to_family": False,
        "preserve_tip_size_when_scaling": True,
        "normal_vector": OUT,
        "use_rectangular_stem": True,
        "rectangular_stem_width": 0.05,
    }

    def __init__(self, *args, **kwargs):
        points = map(self.pointify, args)
        if len(args) == 1:
            args = (points[0] + UP + LEFT, points[0])
        Line.__init__(self, *args, **kwargs)
        self.init_tip()
        if self.use_rectangular_stem and not hasattr(self, "rect"):
            self.add_rectangular_stem()
        self.init_colors()

    def init_tip(self):
        self.add_tip()

    def add_tip(self, add_at_end=True):
        tip = VMobject(
            close_new_points=True,
            mark_paths_closed=True,
            fill_color=self.color,
            fill_opacity=1,
            stroke_color=self.color,
            stroke_width=0,
        )
        tip.add_at_end = add_at_end
        self.set_tip_points(tip, add_at_end, preserve_normal=False)
        self.add(tip)
        if not hasattr(self, 'tip'):
            self.tip = VGroup()
            self.tip.match_style(tip)
        self.tip.add(tip)
        return tip

    def add_rectangular_stem(self):
        self.rect = Rectangle(stroke_width=0,
                              fill_color=self.tip.get_fill_color(),
                              fill_opacity=self.tip.get_fill_opacity())
        self.add_to_back(self.rect)
        self.set_stroke(width=0)
        self.set_rectangular_stem_points()

    def set_rectangular_stem_points(self):
        start, end = self.get_start_and_end()
        tip_base_points = self.tip[0].get_anchors()[1:]
        tip_base = center_of_mass(tip_base_points)
        tbp1, tbp2 = tip_base_points
        perp_vect = tbp2 - tbp1
        tip_base_width = np.linalg.norm(perp_vect)
        if tip_base_width > 0:
            perp_vect /= tip_base_width
        width = min(
            self.rectangular_stem_width,
            self.max_stem_width_to_tip_width_ratio * tip_base_width,
        )
        if hasattr(self, "second_tip"):
            start = center_of_mass(self.second_tip.get_anchors()[1:])
        self.rect.set_points_as_corners([
            tip_base + perp_vect * width / 2,
            start + perp_vect * width / 2,
            start - perp_vect * width / 2,
            tip_base - perp_vect * width / 2,
        ])
        self.stem = self.rect  # Alternate name
        return self

    def set_tip_points(
        self,
        tip,
        add_at_end=True,
        tip_length=None,
        preserve_normal=True,
    ):
        if tip_length is None:
            tip_length = self.tip_length
        if preserve_normal:
            normal_vector = self.get_normal_vector()
        else:
            normal_vector = self.normal_vector
        line_length = np.linalg.norm(self.points[-1] - self.points[0])
        tip_length = min(tip_length,
                         self.max_tip_length_to_length_ratio * line_length)

        indices = (-2, -1) if add_at_end else (1, 0)
        pre_end_point, end_point = [
            self.get_anchors()[index] for index in indices
        ]
        vect = end_point - pre_end_point
        perp_vect = np.cross(vect, normal_vector)
        for v in vect, perp_vect:
            if np.linalg.norm(v) == 0:
                v[0] = 1
            v *= tip_length / np.linalg.norm(v)
        ratio = self.tip_width_to_length_ratio
        tip.set_points_as_corners([
            end_point,
            end_point - vect + perp_vect * ratio / 2,
            end_point - vect - perp_vect * ratio / 2,
        ])

        return self

    def get_normal_vector(self):
        p0, p1, p2 = self.tip[0].get_anchors()
        result = np.cross(p2 - p1, p1 - p0)
        norm = np.linalg.norm(result)
        if norm == 0:
            return self.normal_vector
        else:
            return result / norm

    def reset_normal_vector(self):
        self.normal_vector = self.get_normal_vector()
        return self

    def get_end(self):
        if hasattr(self, "tip"):
            return self.tip[0].get_anchors()[0]
        else:
            return Line.get_end(self)

    def get_tip(self):
        return self.tip

    def put_start_and_end_on(self, *args, **kwargs):
        Line.put_start_and_end_on(self, *args, **kwargs)
        self.set_tip_points(self.tip[0], preserve_normal=False)
        self.set_rectangular_stem_points()
        return self

    def scale(self, scale_factor, **kwargs):
        Line.scale(self, scale_factor, **kwargs)
        if self.preserve_tip_size_when_scaling:
            for t in self.tip:
                self.set_tip_points(t, add_at_end=t.add_at_end)
        if self.use_rectangular_stem:
            self.set_rectangular_stem_points()
        return self

    def copy(self):
        return self.deepcopy()
Esempio n. 33
0
    def get_secant_slope_group(
        self,
        x,
        graph,
        dx=None,
        dx_line_color=None,
        df_line_color=None,
        dx_label=None,
        df_label=None,
        include_secant_line=True,
        secant_line_color=None,
        secant_line_length=10,
    ):
        """
        Resulting group is of the form VGroup(
            dx_line,
            df_line,
            dx_label, (if applicable)
            df_label, (if applicable)
            secant_line, (if applicable)
        )
        with attributes of those names.
        """
        kwargs = locals()
        kwargs.pop("self")
        group = VGroup()
        group.kwargs = kwargs

        dx = dx or float(self.x_max - self.x_min) / 10
        dx_line_color = dx_line_color or self.default_input_color
        df_line_color = df_line_color or graph.get_color()

        p1 = self.input_to_graph_point(x, graph)
        p2 = self.input_to_graph_point(x + dx, graph)
        interim_point = p2[0] * RIGHT + p1[1] * UP

        group.dx_line = Line(p1, interim_point, color=dx_line_color)
        group.df_line = Line(interim_point, p2, color=df_line_color)
        group.add(group.dx_line, group.df_line)

        labels = VGroup()
        if dx_label is not None:
            group.dx_label = TexMobject(dx_label)
            labels.add(group.dx_label)
            group.add(group.dx_label)
        if df_label is not None:
            group.df_label = TexMobject(df_label)
            labels.add(group.df_label)
            group.add(group.df_label)

        if len(labels) > 0:
            max_width = 0.8 * group.dx_line.get_width()
            max_height = 0.8 * group.df_line.get_height()
            if labels.get_width() > max_width:
                labels.scale_to_fit_width(max_width)
            if labels.get_height() > max_height:
                labels.scale_to_fit_height(max_height)

        if dx_label is not None:
            group.dx_label.next_to(group.dx_line,
                                   np.sign(dx) * DOWN,
                                   buff=group.dx_label.get_height() / 2)
            group.dx_label.set_color(group.dx_line.get_color())

        if df_label is not None:
            group.df_label.next_to(group.df_line,
                                   np.sign(dx) * RIGHT,
                                   buff=group.df_label.get_height() / 2)
            group.df_label.set_color(group.df_line.get_color())

        if include_secant_line:
            secant_line_color = secant_line_color or self.default_derivative_color
            group.secant_line = Line(p1, p2, color=secant_line_color)
            group.secant_line.scale_in_place(secant_line_length /
                                             group.secant_line.get_length())
            group.add(group.secant_line)

        return group
Esempio n. 34
0
class Arrow(Line):
    CONFIG = {
        "tip_length": 0.25,
        "tip_width_to_length_ratio": 1,
        "max_tip_length_to_length_ratio": 0.35,
        "max_stem_width_to_tip_width_ratio": 0.3,
        "buff": MED_SMALL_BUFF,
        "propagate_style_to_family": False,
        "preserve_tip_size_when_scaling": True,
        "normal_vector": OUT,
        "use_rectangular_stem": True,
        "rectangular_stem_width": 0.05,
    }

    def __init__(self, *args, **kwargs):
        points = map(self.pointify, args)
        if len(args) == 1:
            args = (points[0] + UP + LEFT, points[0])
        Line.__init__(self, *args, **kwargs)
        self.init_tip()
        if self.use_rectangular_stem and not hasattr(self, "rect"):
            self.add_rectangular_stem()
        self.init_colors()

    def init_tip(self):
        self.add_tip()

    def add_tip(self, add_at_end=True):
        tip = VMobject(
            close_new_points=True,
            mark_paths_closed=True,
            fill_color=self.color,
            fill_opacity=1,
            stroke_color=self.color,
            stroke_width=0,
        )
        tip.add_at_end = add_at_end
        self.set_tip_points(tip, add_at_end, preserve_normal=False)
        self.add(tip)
        if not hasattr(self, 'tip'):
            self.tip = VGroup()
            self.tip.match_style(tip)
        self.tip.add(tip)
        return tip

    def add_rectangular_stem(self):
        self.rect = Rectangle(
            stroke_width=0,
            fill_color=self.tip.get_fill_color(),
            fill_opacity=self.tip.get_fill_opacity()
        )
        self.add_to_back(self.rect)
        self.set_stroke(width=0)
        self.set_rectangular_stem_points()

    def set_rectangular_stem_points(self):
        start, end = self.get_start_and_end()
        tip_base_points = self.tip[0].get_anchors()[1:]
        tip_base = center_of_mass(tip_base_points)
        tbp1, tbp2 = tip_base_points
        perp_vect = tbp2 - tbp1
        tip_base_width = np.linalg.norm(perp_vect)
        if tip_base_width > 0:
            perp_vect /= tip_base_width
        width = min(
            self.rectangular_stem_width,
            self.max_stem_width_to_tip_width_ratio * tip_base_width,
        )
        if hasattr(self, "second_tip"):
            start = center_of_mass(
                self.second_tip.get_anchors()[1:]
            )
        self.rect.set_points_as_corners([
            tip_base + perp_vect * width / 2,
            start + perp_vect * width / 2,
            start - perp_vect * width / 2,
            tip_base - perp_vect * width / 2,
        ])
        self.stem = self.rect  # Alternate name
        return self

    def set_tip_points(
        self, tip,
        add_at_end=True,
        tip_length=None,
        preserve_normal=True,
    ):
        if tip_length is None:
            tip_length = self.tip_length
        if preserve_normal:
            normal_vector = self.get_normal_vector()
        else:
            normal_vector = self.normal_vector
        line_length = np.linalg.norm(self.points[-1] - self.points[0])
        tip_length = min(
            tip_length, self.max_tip_length_to_length_ratio * line_length
        )

        indices = (-2, -1) if add_at_end else (1, 0)
        pre_end_point, end_point = [
            self.get_anchors()[index]
            for index in indices
        ]
        vect = end_point - pre_end_point
        perp_vect = np.cross(vect, normal_vector)
        for v in vect, perp_vect:
            if np.linalg.norm(v) == 0:
                v[0] = 1
            v *= tip_length / np.linalg.norm(v)
        ratio = self.tip_width_to_length_ratio
        tip.set_points_as_corners([
            end_point,
            end_point - vect + perp_vect * ratio / 2,
            end_point - vect - perp_vect * ratio / 2,
        ])

        return self

    def get_normal_vector(self):
        p0, p1, p2 = self.tip[0].get_anchors()
        result = np.cross(p2 - p1, p1 - p0)
        norm = np.linalg.norm(result)
        if norm == 0:
            return self.normal_vector
        else:
            return result / norm

    def reset_normal_vector(self):
        self.normal_vector = self.get_normal_vector()
        return self

    def get_end(self):
        if hasattr(self, "tip"):
            return self.tip[0].get_anchors()[0]
        else:
            return Line.get_end(self)

    def get_tip(self):
        return self.tip

    def put_start_and_end_on(self, *args, **kwargs):
        Line.put_start_and_end_on(self, *args, **kwargs)
        self.set_tip_points(self.tip[0], preserve_normal=False)
        self.set_rectangular_stem_points()
        return self

    def scale(self, scale_factor, **kwargs):
        Line.scale(self, scale_factor, **kwargs)
        if self.preserve_tip_size_when_scaling:
            for t in self.tip:
                self.set_tip_points(t, add_at_end=t.add_at_end)
        if self.use_rectangular_stem:
            self.set_rectangular_stem_points()
        return self

    def copy(self):
        return self.deepcopy()
Esempio n. 35
0
class CountingScene(Scene):
    CONFIG = {
        "digit_place_colors": [YELLOW, MAROON_B, RED, GREEN, BLUE, PURPLE_D],
        "counting_dot_starting_position": (FRAME_X_RADIUS - 1) * RIGHT + (FRAME_Y_RADIUS - 1) * UP,
        "count_dot_starting_radius": 0.5,
        "dot_configuration_height": 2,
        "ones_configuration_location": UP + 2 * RIGHT,
        "num_scale_factor": 2,
        "num_start_location": 2 * DOWN,
    }

    def setup(self):
        self.dots = VGroup()
        self.number = 0
        self.max_place = 0
        self.number_mob = VGroup(TexMobject(str(self.number)))
        self.number_mob.scale(self.num_scale_factor)
        self.number_mob.shift(self.num_start_location)

        self.dot_templates = []
        self.dot_template_iterators = []
        self.curr_configurations = []

        self.arrows = VGroup()

        self.add(self.number_mob)

    def get_template_configuration(self, place):
        # This should probably be replaced for non-base-10 counting scenes
        down_right = (0.5) * RIGHT + (np.sqrt(3) / 2) * DOWN
        result = []
        for down_right_steps in range(5):
            for left_steps in range(down_right_steps):
                result.append(
                    down_right_steps * down_right + left_steps * LEFT
                )
        return reversed(result[:self.get_place_max(place)])

    def get_dot_template(self, place):
        # This should be replaced for non-base-10 counting scenes
        dots = VGroup(*[
            Dot(
                point,
                radius=0.25,
                fill_opacity=0,
                stroke_width=2,
                stroke_color=WHITE,
            )
            for point in self.get_template_configuration(place)
        ])
        dots.scale_to_fit_height(self.dot_configuration_height)
        return dots

    def add_configuration(self):
        new_template = self.get_dot_template(len(self.dot_templates))
        new_template.move_to(self.ones_configuration_location)
        left_vect = (new_template.get_width() + LARGE_BUFF) * LEFT
        new_template.shift(
            left_vect * len(self.dot_templates)
        )
        self.dot_templates.append(new_template)
        self.dot_template_iterators.append(
            it.cycle(new_template)
        )
        self.curr_configurations.append(VGroup())

    def count(self, max_val, run_time_per_anim=1):
        for x in range(max_val):
            self.increment(run_time_per_anim)

    def increment(self, run_time_per_anim=1):
        moving_dot = Dot(
            self.counting_dot_starting_position,
            radius=self.count_dot_starting_radius,
            color=self.digit_place_colors[0],
        )
        moving_dot.generate_target()
        moving_dot.set_fill(opacity=0)
        kwargs = {
            "run_time": run_time_per_anim
        }

        continue_rolling_over = True
        first_move = True
        place = 0
        while continue_rolling_over:
            added_anims = []
            if first_move:
                added_anims += self.get_digit_increment_animations()
                first_move = False
            moving_dot.target.replace(
                self.dot_template_iterators[place].next()
            )
            self.play(MoveToTarget(moving_dot), *added_anims, **kwargs)
            self.curr_configurations[place].add(moving_dot)

            if len(self.curr_configurations[place].split()) == self.get_place_max(place):
                full_configuration = self.curr_configurations[place]
                self.curr_configurations[place] = VGroup()
                place += 1
                center = full_configuration.get_center_of_mass()
                radius = 0.6 * max(
                    full_configuration.get_width(),
                    full_configuration.get_height(),
                )
                circle = Circle(
                    radius=radius,
                    stroke_width=0,
                    fill_color=self.digit_place_colors[place],
                    fill_opacity=0.5,
                )
                circle.move_to(center)
                moving_dot = VGroup(circle, full_configuration)
                moving_dot.generate_target()
                moving_dot[0].set_fill(opacity=0)
            else:
                continue_rolling_over = False

    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

    def get_number_mob(self, num):
        result = VGroup()
        place = 0
        max_place = self.max_place
        while place < max_place:
            digit = TexMobject(str(self.get_place_num(num, place)))
            if place >= len(self.digit_place_colors):
                self.digit_place_colors += self.digit_place_colors
            digit.set_color(self.digit_place_colors[place])
            digit.scale(self.num_scale_factor)
            digit.next_to(result, LEFT, buff=SMALL_BUFF, aligned_edge=DOWN)
            result.add(digit)
            place += 1
        return result

    def is_next_digit(self):
        return False

    def get_place_num(self, num, place):
        return 0

    def get_place_max(self, place):
        return 0
Esempio n. 36
0
    def construct(self):
        colors = ["#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#0080FF"]
        wallis_rects_4 = WallisRectangles(
            order=5,
            rect_colors=colors,
        )
        vert_lines = VGroup(*[
            Line(3.5*UP, 3.5*DOWN, color = GREY, stroke_width = 3) \
            .next_to(wallis_rects_4.get_rectangle(0, k), direction, buff = 0)
            for k, direction in zip(list(range(5))+[4], [LEFT]*5+[RIGHT])
        ])
        horiz_lines = VGroup(*[
            Line(3.5*LEFT, 3.5*RIGHT, color = GREY, stroke_width = 3) \
            .next_to(wallis_rects_4.get_rectangle(k, 0), direction, buff = 0)
            for k, direction in zip(list(range(5))+[4], [DOWN]*5+[UP])
        ])
        for vert_line in vert_lines:
            vert_line.vertically_center()
        for horiz_line in horiz_lines:
            horiz_line.horizontally_center()
        vert_labels = VGroup(*[
            TexMobject("a_%d" % k) \
            .move_to((vert_lines[k].get_center() + vert_lines[k+1].get_center())/2) \
            .shift(3.5*DOWN)
            for k in range(5)
        ])
        horiz_labels = VGroup(*[
            TexMobject("a_%d" % k) \
            .move_to((horiz_lines[k].get_center() + horiz_lines[k+1].get_center())/2) \
            .shift(3.5*LEFT)
            for k in range(5)
        ])

        area_texs = VGroup()
        factors = [1.25, 1, 0.9, 0.7, 0.6]
        for p in range(5):
            for q in range(5 - p):
                rect = wallis_rects_4.get_rectangle(p, q)
                tex = TexMobject("{a_%d} {a_%d}" % (q, p))
                tex.scale(factors[p + q])
                tex.move_to(rect)
                area_texs.add(tex)

        figure = VGroup()
        figure.add(wallis_rects_4, vert_lines, horiz_lines, vert_labels,
                   horiz_labels, area_texs)
        figure.to_edge(LEFT)
        self.add(figure)

        tex_list = VGroup()
        for p in range(5):
            formula_string = (
                " + ".join(["a_%d a_%d" % (q, p - q)
                            for q in range(p + 1)]) + "=1")
            formula = TexMobject(formula_string)
            tex_list.add(formula)
        # tex_list.add(TexMobject("\\vdots"))
        tex_factors = np.linspace(1, 0.7, 5)
        for tex, color, factor in zip(tex_list, colors, tex_factors):
            tex.set_color(color)
            tex.scale(factor)
        tex_list.arrange_submobjects(DOWN, aligned_edge=LEFT)
        tex_list.to_edge(RIGHT)
        self.add(tex_list)
        self.wait()
Esempio n. 37
0
    def construct(self):
        # Chart on the left
        colors = [WHITE, ORANGE, GREEN]
        titles = VGroup(*[
            TexMobject(text).set_color(color)
            for text, color in zip(["n", "p_n", "q_n"], colors)
        ])
        contents = VGroup(*[
            VGroup(*[
                TexMobject("%d" % num) for num in
                [k, central_binomial_coeff(k),
                 central_binomial_coeff(k)]
            ]) for k in range(8)
        ])
        titles.arrange_submobjects(RIGHT, buff=1)
        for num, line in enumerate(contents):
            for k, element in enumerate(line):
                buff = 0.6 + 0.8 * num
                element.next_to(titles[k], DOWN, aligned_edge=LEFT, buff=buff)
                element.set_color(colors[k])
        sep_line = Line(ORIGIN, 4.5 * RIGHT, stroke_width=5)
        sep_line.next_to(titles, DOWN)
        chart = VGroup(titles, contents, sep_line)
        chart.set_height(7)
        chart.center().to_edge(LEFT)
        self.add(chart)

        # Figures on the right
        std_zero_pos_axis = NumberLine(x_min=-2,
                                       x_max=2,
                                       color=GREY,
                                       unit_size=0.25,
                                       tick_size=0.05)
        std_zero_pos_axis.rotate(np.pi / 2)
        std_nocross_pos_axis = NumberLine(x_min=-4,
                                          x_max=4,
                                          color=GREY,
                                          unit_size=0.25,
                                          tick_size=0.05)
        std_nocross_pos_axis.rotate(np.pi / 2)
        std_time_axis = NumberLine(x_min=0,
                                   x_max=5.5,
                                   color=GREY,
                                   unit_size=0.25,
                                   tick_size=0.05)
        std_zero_axes = VGroup(std_zero_pos_axis, std_time_axis)
        std_nocross_axes = VGroup(std_nocross_pos_axis, std_time_axis)

        zero_walks = VGroup()
        for sequence in ["UUDD", "UDUD", "UDDU", "DDUU", "DUDU", "DUUD"]:
            axes = std_zero_axes.copy()
            zero_walk = RandomWalk1DArrow(sequence, step_size=0.25)
            zero_walk.move_start_to(axes[0].number_to_point(0))
            zero_walks.add(VGroup(axes, zero_walk))
        zero_walks.arrange_submobjects_in_grid(2, 3, buff=0.5)
        zero_rect = SurroundingRectangle(zero_walks, color=ORANGE, buff=0.4)
        zero_walks.add(zero_rect)

        nocross_walks = VGroup()
        for sequence in ["DDDD", "DDUD", "DDDU", "UUUU", "UUDU", "UUUD"]:
            axes = std_nocross_axes.copy()
            nocross_walk = RandomWalk1DArrow(sequence, step_size=0.25)
            nocross_walk.move_start_to(axes[0].number_to_point(0))
            nocross_walks.add(VGroup(axes, nocross_walk))
        nocross_walks.arrange_submobjects_in_grid(2, 3, buff=0.5)
        nocross_rect = SurroundingRectangle(nocross_walks,
                                            color=GREEN,
                                            buff=0.4)
        nocross_walks.add(nocross_rect)

        relation = TexMobject("p_2", "=", "q_2", "=", "6")
        relation[0].set_color(ORANGE)
        relation[2].set_color(GREEN)
        relation.scale(1.5)
        figure = VGroup(zero_walks, relation, nocross_walks)
        figure.arrange_submobjects(DOWN)
        figure.set_height(7)
        figure.center().to_edge(RIGHT)

        self.add(figure)
        self.wait()
Esempio n. 38
0
class RandomWalk1DArrow(RandomWalk1D):
    CONFIG = {
        "up_color": BLUE,
        "down_color": RED,
    }

    def generate_points(self):
        self.arrow_group = VGroup()
        vertices = self.generate_vertices_from_string(self.walk_string)
        for k in range(len(vertices) - 1):
            arrow = Arrow(vertices[k],
                          vertices[k + 1],
                          color=self.get_arrow_color_by_number(k),
                          buff=0)
            self.arrow_group.add(arrow)
        self.add(self.arrow_group)
        self.horizontally_center()

    def get_length(self):
        return len(self.arrow_group)

    def get_arrow_by_number(self, n):
        return self.arrow_group[n]

    def get_arrow_color_by_number(self, n):
        return self.up_color if self.walk_string[
            n] == self.up_char else self.down_color

    def split_at(self, n):
        if n < 0:
            return VGroup(), self.arrow_group
        else:
            return VGroup(self.arrow_group[:n + 1]), VGroup(
                self.arrow_group[n + 1:])

    def get_arrow_starting_point(self, n):
        arrow = self.get_arrow_by_number(n)
        return arrow.get_start()

    def get_arrow_end_point(self, n):
        arrow = self.get_arrow_by_number(n)
        return arrow.get_end()

    def get_starting_point(self):
        return self.get_arrow_starting_point(0)

    def get_end_point(self):
        return self.get_arrow_end_point(-1)

    def move_start_to(self, position):
        self.shift(position - self.get_starting_point())
        return self

    def get_flip_arrows_animation(self, n, color=None):
        arrows = [self.get_arrow_by_number(k) for k in range(n + 1)]
        for arrow in arrows:
            arrow.generate_target()
            arrow.target.rotate(np.pi)
            if color is not None:
                arrow.target.set_color(color)
        return AnimationGroup(*[MoveToTarget(arrow) for arrow in arrows])