Beispiel #1
0
 def _add_horizontal_lines(self) -> Table:
     """Adds the horizontal lines to the table."""
     anchor_left = self.get_left()[0] - 0.5 * self.h_buff
     anchor_right = self.get_right()[0] + 0.5 * self.h_buff
     line_group = VGroup()
     if self.include_outer_lines:
         anchor = self.get_rows()[0].get_top()[1] + 0.5 * self.v_buff
         line = Line([anchor_left, anchor, 0], [anchor_right, anchor, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
         anchor = self.get_rows()[-1].get_bottom()[1] - 0.5 * self.v_buff
         line = Line([anchor_left, anchor, 0], [anchor_right, anchor, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
     for k in range(len(self.mob_table) - 1):
         anchor = self.get_rows()[k + 1].get_top()[1] + 0.5 * (
             self.get_rows()[k].get_bottom()[1] -
             self.get_rows()[k + 1].get_top()[1])
         line = Line([anchor_left, anchor, 0], [anchor_right, anchor, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
     self.horizontal_lines = line_group
     return self
Beispiel #2
0
 def _add_vertical_lines(self) -> Table:
     """Adds the vertical lines to the table"""
     anchor_top = self.get_rows().get_top()[1] + 0.5 * self.v_buff
     anchor_bottom = self.get_rows().get_bottom()[1] - 0.5 * self.v_buff
     line_group = VGroup()
     if self.include_outer_lines:
         anchor = self.get_columns()[0].get_left()[0] - 0.5 * self.h_buff
         line = Line([anchor, anchor_top, 0], [anchor, anchor_bottom, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
         anchor = self.get_columns()[-1].get_right()[0] + 0.5 * self.h_buff
         line = Line([anchor, anchor_top, 0], [anchor, anchor_bottom, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
     for k in range(len(self.mob_table[0]) - 1):
         anchor = self.get_columns()[k + 1].get_left()[0] + 0.5 * (
             self.get_columns()[k].get_right()[0] -
             self.get_columns()[k + 1].get_left()[0])
         line = Line([anchor, anchor_bottom, 0], [anchor, anchor_top, 0],
                     **self.line_config)
         line_group.add(line)
         self.add(line)
     self.vertical_lines = line_group
     return self
Beispiel #3
0
 def __init__(
     self,
     mobject: Mobject | None = None,
     stroke_color: Color = RED,
     stroke_width: float = 6,
     scale_factor: float = 1,
     **kwargs,
 ):
     super().__init__(Line(UP + LEFT, DOWN + RIGHT),
                      Line(UP + RIGHT, DOWN + LEFT), **kwargs)
     if mobject is not None:
         self.replace(mobject, stretch=True)
     self.scale(scale_factor)
     self.set_stroke(color=stroke_color, width=stroke_width)
Beispiel #4
0
    def __init__(
        self,
        color: Color = WHITE,
        height: float = 2.0,
        width: float = 4.0,
        grid_xstep: float | None = None,
        grid_ystep: float | None = None,
        mark_paths_closed=True,
        close_new_points=True,
        **kwargs,
    ):
        super().__init__(UR, UL, DL, DR, color=color, **kwargs)
        self.stretch_to_fit_width(width)
        self.stretch_to_fit_height(height)
        v = self.get_vertices()
        if grid_xstep is not None:
            from manim.mobject.geometry.line import Line

            grid_xstep = abs(grid_xstep)
            count = int(width / grid_xstep)
            grid = VGroup(
                *(
                    Line(
                        v[1] + i * grid_xstep * RIGHT,
                        v[1] + i * grid_xstep * RIGHT + height * DOWN,
                        color=color,
                    )
                    for i in range(1, count)
                )
            )
            self.add(grid)
        if grid_ystep is not None:
            grid_ystep = abs(grid_ystep)
            count = int(height / grid_ystep)
            grid = VGroup(
                *(
                    Line(
                        v[1] + i * grid_ystep * DOWN,
                        v[1] + i * grid_ystep * DOWN + width * RIGHT,
                        color=color,
                    )
                    for i in range(1, count)
                )
            )
            self.add(grid)
Beispiel #5
0
 def __init__(
     self,
     point_1: Sequence[float] | None,
     point_2: Sequence[float] | None,
     direction: Sequence[float] | None = ORIGIN,
     **kwargs,
 ):
     if all(direction == ORIGIN):
         line_vector = np.array(point_2) - np.array(point_1)
         direction = np.array([line_vector[1], -line_vector[0], 0])
     super().__init__(Line(point_1, point_2), direction=direction, **kwargs)
Beispiel #6
0
    def get_axes(self):
        """Return a set of 3D axes.

        Returns
        -------
        :class:`.ThreeDAxes`
            A set of 3D axes.
        """
        axes = ThreeDAxes(**self.three_d_axes_config)
        for axis in axes:
            if self.cut_axes_at_radius:
                p0 = axis.get_start()
                p1 = axis.number_to_point(-1)
                p2 = axis.number_to_point(1)
                p3 = axis.get_end()
                new_pieces = VGroup(Line(p0, p1), Line(p1, p2), Line(p2, p3))
                for piece in new_pieces:
                    piece.shade_in_3d = True
                new_pieces.match_style(axis.pieces)
                axis.pieces.submobjects = new_pieces.submobjects
            for tick in axis.tick_marks:
                tick.add(VectorizedPoint(1.5 * tick.get_center()))
        return axes
Beispiel #7
0
    def __init__(
        self,
        arc: Arc = Arc(start_angle=-1, angle=2, radius=1),
        direction: Sequence[float] = RIGHT,
        **kwargs,
    ):
        arc_end_angle = arc.start_angle + arc.angle
        line = Line(UP * arc.start_angle, UP * arc_end_angle)
        scale_shift = RIGHT * np.log(arc.radius)

        if arc.radius >= 1:
            line.scale(arc.radius, about_point=ORIGIN)
            super().__init__(line, direction=direction, **kwargs)
            self.scale(1 / (arc.radius), about_point=ORIGIN)
        else:
            super().__init__(line, direction=direction, **kwargs)

        if arc.radius >= 0.3:
            self.shift(scale_shift)
        else:
            self.shift(RIGHT * np.log(0.3))

        self.apply_complex_function(np.exp)
        self.shift(arc.get_arc_center())
Beispiel #8
0
 def create_lines(self) -> VGroup:
     lines = VGroup()
     for angle in np.arange(0, TAU, TAU / self.num_lines):
         line = Line(self.point, self.point + self.line_length * RIGHT)
         line.shift((self.flash_radius) * RIGHT)
         line.rotate(angle, about_point=self.point)
         lines.add(line)
     lines.set_color(self.color)
     lines.set_stroke(width=self.line_stroke_width)
     return lines
Beispiel #9
0
def test_succession_in_succession_timing(using_opengl_renderer):
    """Test timing of nested successions."""
    line = Line()
    animation_1s = FadeIn(line, shift=UP, run_time=1.0)
    animation_4s = FadeOut(line, shift=DOWN, run_time=4.0)
    nested_succession = Succession(animation_1s, animation_4s)
    succession = Succession(
        FadeIn(line, shift=UP, run_time=4.0),
        nested_succession,
        FadeIn(line, shift=UP, run_time=1.0),
    )
    assert nested_succession.get_run_time() == 5.0
    assert succession.get_run_time() == 10.0
    succession._setup_scene(MagicMock())
    succession.begin()
    succession.interpolate(0.1)
    assert succession.active_index == 0
    # The nested succession must not be active yet, and as a result hasn't set active_animation yet.
    assert not hasattr(nested_succession, "active_animation")
    succession.interpolate(0.39)
    assert succession.active_index == 0
    assert not hasattr(nested_succession, "active_animation")
    # The nested succession starts at 40% of total run time
    succession.interpolate(0.4)
    assert succession.active_index == 1
    assert nested_succession.active_index == 0
    # The nested succession second animation starts at 50% of total run time.
    succession.interpolate(0.49)
    assert succession.active_index == 1
    assert nested_succession.active_index == 0
    succession.interpolate(0.5)
    assert succession.active_index == 1
    assert nested_succession.active_index == 1
    # The last animation starts at 90% of total run time. The nested succession must be finished at that time.
    succession.interpolate(0.89)
    assert succession.active_index == 1
    assert nested_succession.active_index == 1
    succession.interpolate(0.9)
    assert succession.active_index == 2
    assert nested_succession.active_index == 2
    assert nested_succession.active_animation is None
    # After 100%, nothing must be playing anymore.
    succession.interpolate(1.0)
    assert succession.active_index == 3
    assert succession.active_animation is None
    assert nested_succession.active_index == 2
    assert nested_succession.active_animation is None
Beispiel #10
0
    def get_tick(self, x: float, size: float | None = None) -> Line:
        """Generates a tick and positions it along the number line.

        Parameters
        ----------
        x
            The position of the tick.
        size
            The factor by which the tick is scaled.

        Returns
        -------
        :class:`~.Line`
            A positioned tick.
        """
        if size is None:
            size = self.tick_size
        result = Line(size * DOWN, size * UP)
        result.rotate(self.get_angle())
        result.move_to(self.number_to_point(x))
        result.match_style(self)
        return result
Beispiel #11
0
    def _line_to_mobject(self, line_element: MinidomElement, style: dict):
        """Creates a Line VMobject from an SVG <line> element.

        Parameters
        ----------
        line_element : :class:`minidom.Element`
            An SVG line element.

        style : :class:`dict`
            Style specification, using the SVG names for properties.

        Returns
        -------
        Line
            A Line VMobject
        """
        x1, y1, x2, y2 = (self._attribute_to_float(
            line_element.getAttribute(key))
                          if line_element.hasAttribute(key) else 0.0
                          for key in ("x1", "y1", "x2", "y2"))
        return Line([x1, -y1, 0], [x2, -y2, 0], **parse_style(style))
Beispiel #12
0
def test_succession_timing(using_opengl_renderer):
    """Test timing of animations in a succession."""
    line = Line()
    animation_1s = FadeIn(line, shift=UP, run_time=1.0)
    animation_4s = FadeOut(line, shift=DOWN, run_time=4.0)
    succession = Succession(animation_1s, animation_4s)
    assert succession.get_run_time() == 5.0
    succession._setup_scene(MagicMock())
    succession.begin()
    assert succession.active_index == 0
    # The first animation takes 20% of the total run time.
    succession.interpolate(0.199)
    assert succession.active_index == 0
    succession.interpolate(0.2)
    assert succession.active_index == 1
    succession.interpolate(0.8)
    assert succession.active_index == 1
    # At 100% and more, no animation must be active anymore.
    succession.interpolate(1.0)
    assert succession.active_index == 2
    assert succession.active_animation is None
    succession.interpolate(1.2)
    assert succession.active_index == 2
    assert succession.active_animation is None
Beispiel #13
0
    def __init__(
        self,
        *text_parts,
        include_underline=True,
        match_underline_width_to_text=False,
        underline_buff=MED_SMALL_BUFF,
        **kwargs,
    ):

        self.include_underline = include_underline
        self.match_underline_width_to_text = match_underline_width_to_text
        self.underline_buff = underline_buff
        super().__init__(*text_parts, **kwargs)
        self.to_edge(UP)
        if self.include_underline:
            underline_width = config["frame_width"] - 2
            underline = Line(LEFT, RIGHT)
            underline.next_to(self, DOWN, buff=self.underline_buff)
            if self.match_underline_width_to_text:
                underline.match_width(self)
            else:
                underline.width = underline_width
            self.add(underline)
            self.underline = underline
Beispiel #14
0
 def __init__(self):
     super().__init__()
     self.left_dot = Dot().shift((-1, 0, 0))
     self.right_dot = Dot().shift((1, 0, 0))
     self.line = Line(self.left_dot, self.right_dot)
     self.add(self.left_dot, self.right_dot, self.line)
Beispiel #15
0
    def round_corners(self, radius: float = 0.5):
        """Rounds off the corners of the :class:`Polygram`.

        Parameters
        ----------
        radius
            The curvature of the corners of the :class:`Polygram`.


        .. seealso::
            :class:`.~RoundedRectangle`

        Examples
        --------
        .. manim:: PolygramRoundCorners
            :save_last_frame:

            class PolygramRoundCorners(Scene):
                def construct(self):
                    star = Star(outer_radius=2)

                    shapes = VGroup(star)
                    shapes.add(star.copy().round_corners(radius=0.1))
                    shapes.add(star.copy().round_corners(radius=0.25))

                    shapes.arrange(RIGHT)
                    self.add(shapes)
        """

        if radius == 0:
            return self

        new_points = []

        for vertices in self.get_vertex_groups():
            arcs = []
            for v1, v2, v3 in adjacent_n_tuples(vertices, 3):
                vect1 = v2 - v1
                vect2 = v3 - v2
                unit_vect1 = normalize(vect1)
                unit_vect2 = normalize(vect2)

                angle = angle_between_vectors(vect1, vect2)
                # Negative radius gives concave curves
                angle *= np.sign(radius)

                # Distance between vertex and start of the arc
                cut_off_length = radius * np.tan(angle / 2)

                # Determines counterclockwise vs. clockwise
                sign = np.sign(np.cross(vect1, vect2)[2])

                arc = ArcBetweenPoints(
                    v2 - unit_vect1 * cut_off_length,
                    v2 + unit_vect2 * cut_off_length,
                    angle=sign * angle,
                )
                arcs.append(arc)

            # To ensure that we loop through starting with last
            arcs = [arcs[-1], *arcs[:-1]]
            from manim.mobject.geometry.line import Line

            for arc1, arc2 in adjacent_pairs(arcs):
                new_points.extend(arc1.points)

                line = Line(arc1.get_end(), arc2.get_start())

                # Make sure anchors are evenly distributed
                len_ratio = line.get_length() / arc1.get_arc_length()

                line.insert_n_curves(int(arc1.get_num_curves() * len_ratio))

                new_points.extend(line.points)

        self.set_points(new_points)

        return self