コード例 #1
0
ファイル: probability.py プロジェクト: PythonJedi/manim
    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)
コード例 #2
0
ファイル: graph_scene.py プロジェクト: crclayton/manim
    def get_riemann_rectangles(
        self, 
        graph,
        x_min = None, 
        x_max = None, 
        dx = 0.1, 
        input_sample_type = "left",
        stroke_width = 1,
        start_color = BLUE,
        end_color = GREEN):
        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
        rectangles = VGroup()
        for x in np.arange(x_min, x_max, dx):
            if input_sample_type == "left":
                sample_input = x
            elif input_sample_type == "right":
                sample_input = x+dx
            else:
                raise Exception("Invalid input sample type")
            graph_point = self.input_to_graph_point(sample_input, graph)
            points = VGroup(*map(VectorizedPoint, [
                self.coords_to_point(x, 0),
                self.coords_to_point(x+dx, 0),
                graph_point
            ]))

            rect = Rectangle()
            rect.replace(points, stretch = True)
            rect.set_fill(opacity = 1)
            rectangles.add(rect)
        rectangles.gradient_highlight(start_color, end_color)
        rectangles.set_stroke(BLACK, width = stroke_width)
        return rectangles
コード例 #3
0
    def get_coordinate_labels(self, *numbers):
        # TODO: Should merge this with the code from NumberPlane.get_coordinate_labels

        result = VGroup()
        nudge = 0.1*(DOWN+RIGHT)
        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
コード例 #4
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 = TexMobject(str(int(number)))
         mob.scale_to_fit_height(3 * self.tick_size)
         mob.shift(self.number_to_point(number),
                   self.get_vertical_number_offset(**kwargs))
         result.add(mob)
     return result
コード例 #5
0
ファイル: counting.py プロジェクト: PythonJedi/manim
 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.highlight(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
コード例 #6
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
コード例 #7
0
ファイル: number_line.py プロジェクト: PythonJedi/manim
 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 = TexMobject(str(int(number)))
         mob.scale_to_fit_height(3*self.tick_size)
         mob.shift(
             self.number_to_point(number),
             self.get_vertical_number_offset(**kwargs)
         )
         result.add(mob)
     return result
コード例 #8
0
ファイル: probability.py プロジェクト: PythonJedi/manim
    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.full_space.get_edge_center(-vect)
        parts = VGroup()
        for factor, color in zip(p_list, colors):
            part = SampleSpace()
            part.set_fill(color, 1)
            part.replace(self.full_space, stretch = True)
            part.stretch(factor, dim)
            part.move_to(last_point, -vect)
            last_point = part.get_edge_center(vect)
            parts.add(part)
        return parts
コード例 #9
0
ファイル: number_line.py プロジェクト: PythonJedi/manim
 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
コード例 #10
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
            else:
                raise Exception("Invalid input sample type")
            graph_point = self.input_to_graph_point(sample_input, graph)
            points = VGroup(*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
コード例 #11
0
ファイル: graph_scene.py プロジェクト: PythonJedi/manim
    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
            else:
                raise Exception("Invalid input sample type")
            graph_point = self.input_to_graph_point(sample_input, graph)
            points = VGroup(*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
コード例 #12
0
ファイル: probability.py プロジェクト: PythonJedi/manim
    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
コード例 #13
0
ファイル: objects.py プロジェクト: waknaudt/manim
 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(WHITE, 8)
         circles.add(circle)
     LaggedStart.__init__(self, ApplyMethod, circles, lambda c:
                          (c.restore, ), **kwargs)
コード例 #14
0
 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
コード例 #15
0
ファイル: graph_scene.py プロジェクト: aquafemi/manim
 def get_riemann_rectangles(self, 
                            x_min = None, 
                            x_max = None, 
                            dx = 0.1, 
                            stroke_width = 1,
                            start_color = BLUE,
                            end_color = GREEN):
     assert(hasattr(self, "func"))
     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
     rectangles = VGroup()
     for x in np.arange(x_min, x_max, dx):
         points = VGroup(*map(VectorizedPoint, [
             self.coords_to_point(x, 0),
             self.coords_to_point(x+dx, self.func(x+dx)),
         ]))
         rect = Rectangle()
         rect.replace(points, stretch = True)
         rect.set_fill(opacity = 1)
         rectangles.add(rect)
     rectangles.gradient_highlight(start_color, end_color)
     rectangles.set_stroke(BLACK, width = stroke_width)
     return rectangles
コード例 #16
0
ファイル: graph_scene.py プロジェクト: crclayton/manim
    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.highlight(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.highlight(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
コード例 #17
0
ファイル: graph_scene.py プロジェクト: liuliuy/manim
    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.highlight(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.highlight(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
コード例 #18
0
ファイル: counting.py プロジェクト: PythonJedi/manim
class CountingScene(Scene):
    CONFIG = {
        "digit_place_colors" : [YELLOW, MAROON_B, RED, GREEN, BLUE, PURPLE_D],
        "counting_dot_starting_position" : (SPACE_WIDTH-1)*RIGHT + (SPACE_HEIGHT-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
        down_right = (0.5)*RIGHT + (np.sqrt(3)/2)*DOWN
        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.highlight(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
コード例 #19
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
        down_right = (0.5) * RIGHT + (np.sqrt(3) / 2) * DOWN
        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