Skip to content

Add docstring for Mobject.rotate and Refactor Rotating and also add its docstring #4147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ Animations
path.become(previous_path)
path.add_updater(update_path)
self.add(path, dot)
self.play(Rotating(dot, radians=PI, about_point=RIGHT, run_time=2))
self.play(Rotating(dot, angle=PI, about_point=RIGHT, run_time=2))
self.wait()
self.play(dot.animate.shift(UP))
self.play(dot.animate.shift(LEFT))
Expand Down
78 changes: 74 additions & 4 deletions manim/animation/rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,93 @@


class Rotating(Animation):
"""Animation that rotates a Mobject.

Parameters
----------
mobject
The mobject to be rotated.
angle
The rotation angle in radians. Predefined constants such as ``DEGREES``
can also be used to specify the angle in degrees.
axis
The rotation axis as a numpy vector.
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:: RotatingDemo

class RotatingDemo(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)
vg = VGroup(circle,line,arrow)
self.add(vg)
anim_kw = {"about_point": arrow.get_start(), "run_time": 1}
self.play(Rotating(arrow, 180*DEGREES, **anim_kw))
self.play(Rotating(arrow, PI, **anim_kw))
self.play(Rotating(vg, PI, about_point=RIGHT))
self.play(Rotating(vg, PI, axis=UP, about_point=ORIGIN))
self.play(Rotating(vg, PI, axis=RIGHT, about_edge=UP))
self.play(vg.animate.move_to(ORIGIN))

.. manim:: RotatingDifferentAxis

class RotatingDifferentAxis(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, phi=40*DEGREES, theta=40*DEGREES)
self.add(axes, cube_group)
play_kw = {"run_time": 1.5}
self.play(Rotating(cube_group, PI), **play_kw)
self.play(Rotating(cube_group, PI, axis=UP), **play_kw)
self.play(Rotating(cube_group, 180*DEGREES, axis=RIGHT), **play_kw)
self.wait(0.5)

See also
--------
:class:`~.Rotate`, :meth:`~.Mobject.rotate`

"""

def __init__(
self,
mobject: Mobject,
angle: np.ndarray = TAU,
axis: np.ndarray = OUT,
radians: np.ndarray = TAU,
about_point: np.ndarray | None = None,
about_edge: np.ndarray | None = None,
run_time: float = 5,
run_time: float = 2,
rate_func: Callable[[float], float] = linear,
**kwargs,
) -> None:
self.angle = angle
self.axis = axis
self.radians = radians
self.about_point = about_point
self.about_edge = about_edge
super().__init__(mobject, run_time=run_time, rate_func=rate_func, **kwargs)

def interpolate_mobject(self, alpha: float) -> None:
self.mobject.become(self.starting_mobject)
self.mobject.rotate(
self.rate_func(alpha) * self.radians,
self.rate_func(alpha) * self.angle,
axis=self.axis,
about_point=self.about_point,
about_edge=self.about_edge,
Expand Down Expand Up @@ -80,6 +146,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__(
Expand Down
68 changes: 64 additions & 4 deletions manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1282,7 +1285,64 @@ 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.

Parameters
----------
angle
The angle of rotation in radians. Predefined constants such as ``DEGREES``
can also be used to specify the angle in degrees.
axis
The rotation axis (see :class:`~.Rotating` for more).
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)


.. 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).

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=120 * 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
Expand Down Expand Up @@ -3143,7 +3203,7 @@ def override_animate(method) -> types.FunctionType:

.. seealso::

:attr:`Mobject.animate`
:attr:`~.Mobject.animate`

.. note::

Expand Down