diff --git a/manim/animation/rotation.py b/manim/animation/rotation.py index 7bdd42238a..8aad6fb23b 100644 --- a/manim/animation/rotation.py +++ b/manim/animation/rotation.py @@ -19,6 +19,66 @@ class Rotating(Animation): + """Animation that rotates a Mobject. + + Parameters + ---------- + mobject + The mobject to be rotated. + axis + The rotation axis (3D vector). Defaults to ``OUT`` (z-axis), producing 2D rotations + perpendicular to the screen. Use other axes (e.g., ``UP``) for 3D rotations. + radians + The rotation angle in radians. Predefined constants such as ``DEGREES`` + can also be used to specify the angle in degrees. + For example, ``PI`` (180 degrees) or ``120 * DEGREES`` (120 degrees). + about_point + The rotation center. + about_edge + If ``about_point`` is ``None``, this argument specifies + the direction of the bounding box point to be taken as + the rotation center. + run_time + The duration of the animation in seconds. + rate_func + The function defining the animation progress based on the relative + runtime (see :mod:`~.rate_functions`) . + **kwargs + Additional keyword arguments passed to :class:`~.Animation`. + + Examples + -------- + .. manim:: RotatingExample + + class RotatingExample(Scene): + def construct(self): + circle = Circle(radius=1, color=BLUE) + line = Line(start=ORIGIN, end=RIGHT) + arrow = Arrow(start=ORIGIN, end=RIGHT, buff=0, color=GOLD) + self.add(circle, line, arrow) + + anim_kwargs = {"rate_func": linear, "run_time": 1} + self.play(Rotating(arrow, radians=PI, about_point=arrow.get_start()), **anim_kwargs) + self.play(Rotating(arrow, radians=180 * DEGREES, about_point=arrow.get_start()), **anim_kwargs) + + .. manim:: Rotating3D + + class Rotating3D(ThreeDScene): + def construct(self): + axes = ThreeDAxes() + cube = Cube() + arrow2d = Arrow(start=[0, -1.2, 1], end=[0, 1.2, 1], color=YELLOW_E) + cube_group = VGroup(cube,arrow2d) + self.set_camera_orientation(gamma=0*DEGREES, phi=40*DEGREES, theta=40*DEGREES) + self.add(axes, cube_group) + self.play(Rotating(cube_group, radians=2*PI, axis=UP), run_time=3, rate_func=linear) + + See also + -------- + :class:`~.Rotate`, :meth:`~.Mobject.rotate` + + """ + def __init__( self, mobject: Mobject, @@ -80,6 +140,10 @@ def construct(self): Rotate(Square(side_length=0.5), angle=2*PI, rate_func=linear), ) + See also + -------- + :class:`~.Rotating`, :meth:`~.Mobject.rotate` + """ def __init__( diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py index 6ad3ece777..22f37bbf3e 100644 --- a/manim/mobject/mobject.py +++ b/manim/mobject/mobject.py @@ -387,9 +387,9 @@ def construct(self): will interpolate the :class:`~.Mobject` between its points prior to ``.animate`` and its points after applying ``.animate`` to it. This may result in unexpected behavior when attempting to interpolate along paths, - or rotations. + or rotations (see :meth:`.rotate`). If you want animations to consider the points between, consider using - :class:`~.ValueTracker` with updaters instead. + :class:`~.ValueTracker` with updaters instead (see :meth:`.add_updater`). """ return _AnimationBuilder(self) @@ -1011,7 +1011,7 @@ def dot_position(mobject): label.add_updater(dot_position) self.add(dot, label) - self.play(Rotating(dot, about_point=ORIGIN, angle=TAU, run_time=TAU, rate_func=linear)) + self.play(Rotating(dot, about_point=ORIGIN, radians=TAU, run_time=TAU, rate_func=linear)) .. manim:: DtUpdater @@ -1029,6 +1029,9 @@ def construct(self): :meth:`get_updaters` :meth:`remove_updater` :class:`~.UpdateFromFunc` + :class:`~.Rotating` + :meth:`rotate` + :attr:`~.Mobject.animate` """ if index is None: self.updaters.append(update_function) @@ -1282,7 +1285,67 @@ def rotate( about_point: Point3DLike | None = None, **kwargs, ) -> Self: - """Rotates the :class:`~.Mobject` about a certain point.""" + """Rotates the :class:`~.Mobject` around a specified axis and point. + + The rotation is counterclockwise by the given ``angle`` (following the right-hand rule). + + .. note:: + To animate a rotation, use :class:`~.Rotating` or :class:`~.Rotate` + instead of ``.animate.rotate(...)``. + The ``.animate.rotate(...)`` syntax only applies a transformation + from the initial state to the final rotated state + (interpolation between the two states), without showing proper rotational motion + based on the angle (from 0 to the given angle). + + Parameters + ---------- + angle + The angle of rotation in radians. Predefined constants such as ``DEGREES`` + can also be used to specify the angle in degrees. + For example, ``PI`` (180 degrees) or ``120 * DEGREES`` (120 degrees). + axis + Rotation axis (3D vector). Defaults to ``OUT`` (z-axis), producing 2D rotations + perpendicular to the screen. Use other axes (e.g., ``UP``) for 3D rotations (see :class:`~.Rotating`). + about_point + The point about which the mobject rotates. If ``None``, rotation occurs around + the center of the mobject. + **kwargs + Additional keyword arguments passed to :meth:`apply_points_function_about_point`, + such as ``about_edge``. + + Returns + ------- + :class:`Mobject` + ``self`` (for method chaining) + + Examples + -------- + + .. manim:: RotateMethodExample + :save_last_frame: + + class RotateMethodExample(Scene): + def construct(self): + circle = Circle(radius=1, color=BLUE) + line = Line(start=ORIGIN, end=RIGHT) + arrow1 = Arrow(start=ORIGIN, end=RIGHT, buff=0, color=GOLD) + group1 = VGroup(circle, line, arrow1) + + group2 = group1.copy() + arrow2 = group2[2] + arrow2.rotate(angle=PI / 4, about_point=arrow2.get_start()) + + group3 = group1.copy() + arrow3 = group3[2] + arrow3.rotate(angle=111 * DEGREES, about_point=arrow3.get_start()) + + self.add(VGroup(group1, group2, group3).arrange(RIGHT, buff=1)) + + See also + -------- + :class:`~.Rotating`, :class:`~.Rotate`, :attr:`~.Mobject.animate`, :meth:`apply_points_function_about_point` + + """ rot_matrix = rotation_matrix(angle, axis) self.apply_points_function_about_point( lambda points: np.dot(points, rot_matrix.T), about_point, **kwargs @@ -3143,7 +3206,7 @@ def override_animate(method) -> types.FunctionType: .. seealso:: - :attr:`Mobject.animate` + :attr:`~.Mobject.animate` .. note::