Skip to content
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6ca620d
added docstings to mobject
kolibril13 Mar 31, 2021
3884b78
updated code
kolibril13 Mar 31, 2021
ac670c7
second code environment stroke
kolibril13 Mar 31, 2021
bbf514d
added flip example
kolibril13 Mar 31, 2021
54f2145
fixed format
kolibril13 Mar 31, 2021
67bff33
fixed format2
kolibril13 Mar 31, 2021
f716a4c
further docstings
kolibril13 Mar 31, 2021
7646a44
Merge branch 'master' into added_docstings_mobject
kolibril13 Mar 31, 2021
a1fc6a9
run black and small change
kolibril13 Mar 31, 2021
0fcd4c0
Merge remote-tracking branch 'fork/added_docstings_mobject' into adde…
kolibril13 Mar 31, 2021
181aa53
Apply suggestions from code review
kolibril13 Apr 1, 2021
9ccde7f
Update manim/mobject/mobject.py
kolibril13 Apr 1, 2021
f0ab5c4
Update manim/mobject/mobject.py
kolibril13 Apr 1, 2021
83aa7de
Update manim/mobject/mobject.py
kolibril13 Apr 1, 2021
f4d34ac
Update manim/mobject/mobject.py
kolibril13 Apr 1, 2021
d831bd2
fix error
kolibril13 Apr 1, 2021
0d6b746
added some typehints
kolibril13 Apr 1, 2021
8ffb417
added further docstings
kolibril13 Apr 1, 2021
fab4276
Merge branch 'master' into added_docstings_mobject
huguesdevimeux Apr 1, 2021
e57adfd
added some typehints
kolibril13 Apr 1, 2021
4333708
Merge remote-tracking branch 'fork/added_docstings_mobject' into adde…
kolibril13 Apr 1, 2021
3e73bad
added some more typehints
kolibril13 Apr 1, 2021
e679e26
black
kolibril13 Apr 1, 2021
934d9f5
Added more instances of :class: to Mobject
jsonvillanueva Apr 2, 2021
862978d
Merge branch 'master' into added_docstings_mobject
jsonvillanueva Apr 2, 2021
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
120 changes: 82 additions & 38 deletions manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,9 +1011,11 @@ def scale(self, scale_factor: float, **kwargs) -> "Mobject":
return self

def rotate_about_origin(self, angle, axis=OUT, axes=[]):
"""Rotates the :class:`~.Mobject` about the ORIGIN, which is at [0,0,0]."""
return self.rotate(angle, axis, about_point=ORIGIN)

def rotate(self, angle, axis=OUT, **kwargs):
"""Rotates the :class:`~.Mobject` about a certain point."""
if config["use_opengl_renderer"]:
rot_matrix_T = rotation_matrix_transpose(angle, axis)
self.apply_points_function(
Expand All @@ -1028,6 +1030,22 @@ def rotate(self, angle, axis=OUT, **kwargs):
return self

def flip(self, axis=UP, **kwargs):
"""Flips/Mirrors an mobject about its center.

Examples
--------

.. manim:: FlipExample
:save_last_frame:

class FlipExample(Scene):
def construct(self):
s= Line(LEFT, RIGHT+UP).shift(4*LEFT)
self.add(s)
s2= s.copy().flip()
self.add(s2)

"""
return self.rotate(TAU / 2, axis, **kwargs)

def stretch(self, factor, dim, **kwargs):
Expand Down Expand Up @@ -1198,7 +1216,7 @@ def next_to(
index_of_submobject_to_align=None,
coor_mask=np.array([1, 1, 1]),
):
"""Move this mobject next to another mobject or coordinate.
"""Move this :class:`~.Mobject` next to another's :class:`~.Mobject` or coordinate.

Examples
--------
Expand Down Expand Up @@ -1277,7 +1295,7 @@ def rescale_to_fit(self, length, dim, stretch=False, **kwargs):
return self

def scale_to_fit_width(self, width, **kwargs):
"""Scales the mobject to fit a width while keeping height/depth proportional.
"""Scales the :class:`~.Mobject` to fit a width while keeping height/depth proportional.

Returns
-------
Expand All @@ -1303,7 +1321,7 @@ def scale_to_fit_width(self, width, **kwargs):
return self.rescale_to_fit(width, 0, stretch=False, **kwargs)

def stretch_to_fit_width(self, width, **kwargs):
"""Stretches the mobject to fit a width, not keeping height/depth proportional.
"""Stretches the :class:`~.Mobject` to fit a width, not keeping height/depth proportional.

Returns
-------
Expand All @@ -1329,7 +1347,7 @@ def stretch_to_fit_width(self, width, **kwargs):
return self.rescale_to_fit(width, 0, stretch=True, **kwargs)

def scale_to_fit_height(self, height, **kwargs):
"""Scales the mobject to fit a height while keeping width/depth proportional.
"""Scales the :class:`~.Mobject` to fit a height while keeping width/depth proportional.

Returns
-------
Expand All @@ -1355,7 +1373,7 @@ def scale_to_fit_height(self, height, **kwargs):
return self.rescale_to_fit(height, 1, stretch=False, **kwargs)

def stretch_to_fit_height(self, height, **kwargs):
"""Stretches the mobject to fit a height, not keeping width/depth proportional.
"""Stretches the :class:`~.Mobject` to fit a height, not keeping width/depth proportional.

Returns
-------
Expand All @@ -1381,12 +1399,12 @@ def stretch_to_fit_height(self, height, **kwargs):
return self.rescale_to_fit(height, 1, stretch=True, **kwargs)

def scale_to_fit_depth(self, depth, **kwargs):
"""Scales the mobject to fit a depth while keeping width/height proportional."""
"""Scales the :class:`~.Mobject` to fit a depth while keeping width/height proportional."""

return self.rescale_to_fit(depth, 2, stretch=False, **kwargs)

def stretch_to_fit_depth(self, depth, **kwargs):
"""Stretches the mobject to fit a depth, not keeping width/height proportional."""
"""Stretches the :class:`~.Mobject` to fit a depth, not keeping width/height proportional."""

return self.rescale_to_fit(depth, 2, stretch=True, **kwargs)

Expand All @@ -1398,12 +1416,15 @@ def set_coord(self, value, dim, direction=ORIGIN):
return self

def set_x(self, x, direction=ORIGIN):
"""Set x value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
return self.set_coord(x, 0, direction)

def set_y(self, y, direction=ORIGIN):
"""Set y value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
return self.set_coord(y, 1, direction)

def set_z(self, z, direction=ORIGIN):
"""Set z value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
return self.set_coord(z, 2, direction)

def space_out_submobjects(self, factor=1.5, **kwargs):
Expand All @@ -1415,6 +1436,7 @@ def space_out_submobjects(self, factor=1.5, **kwargs):
def move_to(
self, point_or_mobject, aligned_edge=ORIGIN, coor_mask=np.array([1, 1, 1])
):
"""Move center of the :class:`~.Mobject` to certain coordinate."""
if isinstance(point_or_mobject, Mobject):
target = point_or_mobject.get_critical_point(aligned_edge)
else:
Expand All @@ -1437,7 +1459,9 @@ def replace(self, mobject, dim_to_match=0, stretch=False):
self.shift(mobject.get_center() - self.get_center())
return self

def surround(self, mobject, dim_to_match=0, stretch=False, buff=MED_SMALL_BUFF):
def surround(
self, mobject: "Mobject", dim_to_match=0, stretch=False, buff=MED_SMALL_BUFF
):
self.replace(mobject, dim_to_match, stretch)
length = mobject.length_over_dim(dim_to_match)
self.scale_in_place((length + buff) / length)
Expand Down Expand Up @@ -1590,6 +1614,7 @@ def get_color(self):
##

def save_state(self):
"""Save the current state (position, color & size). Can be restored with :meth:`~.Mobject.restore`."""
if hasattr(self, "saved_state"):
# Prevent exponential growth of data
self.saved_state = None
Expand All @@ -1598,6 +1623,7 @@ def save_state(self):
return self

def restore(self):
"""Restores the state that was previously saved with :meth:`~.Mobject.save_state`."""
if not hasattr(self, "saved_state") or self.save_state is None:
raise Exception("Trying to restore without having saved")
self.become(self.saved_state)
Expand Down Expand Up @@ -1654,7 +1680,7 @@ def get_extremum_along_dim(self, points=None, dim=0, key=0):
return np.max(values)

def get_critical_point(self, direction):
"""Picture a box bounding the mobject. Such a box has
"""Picture a box bounding the :class:`~.Mobject`. Such a box has
9 'critical points': 4 corners, 4 edge center, the
center. This returns one of them, along the given direction.

Expand All @@ -1680,13 +1706,14 @@ def get_critical_point(self, direction):

# Pseudonyms for more general get_critical_point method

def get_edge_center(self, direction):
def get_edge_center(self, direction) -> np.ndarray:
return self.get_critical_point(direction)

def get_corner(self, direction):
def get_corner(self, direction) -> np.ndarray:
return self.get_critical_point(direction)

def get_center(self):
def get_center(self) -> np.ndarray:
"""Get center coordinates"""
return self.get_critical_point(np.zeros(self.dim))

def get_center_of_mass(self):
Expand All @@ -1697,16 +1724,20 @@ def get_boundary_point(self, direction):
index = np.argmax(np.dot(all_points, np.array(direction).T))
return all_points[index]

def get_top(self):
def get_top(self) -> np.ndarray:
"""Get top coordinates of a box bounding the :class:`~.Mobject`"""
return self.get_edge_center(UP)

def get_bottom(self):
def get_bottom(self) -> np.ndarray:
"""Get bottom coordinates of a box bounding the :class:`~.Mobject`"""
return self.get_edge_center(DOWN)

def get_right(self):
def get_right(self) -> np.ndarray:
"""Get right coordinates of a box bounding the :class:`~.Mobject`"""
return self.get_edge_center(RIGHT)

def get_left(self):
def get_left(self) -> np.ndarray:
"""Get left coordinates of a box bounding the :class:`~.Mobject`"""
return self.get_edge_center(LEFT)

def get_zenith(self):
Expand All @@ -1716,38 +1747,45 @@ def get_nadir(self):
return self.get_edge_center(IN)

def length_over_dim(self, dim):
"""Measure the length of an :class:`~.Mobject` in a certain direction."""
return self.reduce_across_dimension(
np.max, np.max, dim
) - self.reduce_across_dimension(np.min, np.min, dim)

def get_coord(self, dim, direction=ORIGIN):
"""Meant to generalize get_x, get_y, get_z"""
"""Meant to generalize ``get_x``, ``get_y`` and ``get_z``"""
return self.get_extremum_along_dim(dim=dim, key=direction[dim])

def get_x(self, direction=ORIGIN):
def get_x(self, direction=ORIGIN) -> np.float64:
"""Returns x coordinate of the center of the :class:`~.Mobject` as ``float`` """
return self.get_coord(0, direction)

def get_y(self, direction=ORIGIN):
def get_y(self, direction=ORIGIN) -> np.float64:
"""Returns y coordinate of the center of the :class:`~.Mobject` as ``float`` """
return self.get_coord(1, direction)

def get_z(self, direction=ORIGIN):
def get_z(self, direction=ORIGIN) -> np.float64:
"""Returns z coordinate of the center of the :class:`~.Mobject` as ``float`` """
return self.get_coord(2, direction)

def get_start(self):
"""Returns the point, where the stroke that surrounds the :class:`~.Mobject` starts."""
self.throw_error_if_no_points()
if config["use_opengl_renderer"]:
return np.array(self.data["points"][0])
else:
return np.array(self.points[0])

def get_end(self):
"""Returns the point, where the stroke that surrounds the :class:`~.Mobject` ends."""
self.throw_error_if_no_points()
if config["use_opengl_renderer"]:
return np.array(self.data["points"][-1])
else:
return np.array(self.points[-1])

def get_start_and_end(self):
"""Returns starting and ending point of a stroke as a ``tuple``. """
return self.get_start(), self.get_end()

def point_from_proportion(self, alpha):
Expand All @@ -1770,45 +1808,51 @@ def get_z_index_reference_point(self):
return z_index_group.get_center()

def has_points(self):
"""Check if :class:`~.Mobject` contains points. """
return len(self.points) > 0

def has_no_points(self):
return not self.has_points()

# Match other mobject properties

def match_color(self, mobject):
def match_color(self, mobject: "Mobject"):
return self.set_color(mobject.get_color())

def match_dim_size(self, mobject, dim, **kwargs):
def match_dim_size(self, mobject: "Mobject", dim, **kwargs):
return self.rescale_to_fit(mobject.length_over_dim(dim), dim, **kwargs)

def match_width(self, mobject, **kwargs):
def match_width(self, mobject: "Mobject", **kwargs):
return self.match_dim_size(mobject, 0, **kwargs)

def match_height(self, mobject, **kwargs):
def match_height(self, mobject: "Mobject", **kwargs):
return self.match_dim_size(mobject, 1, **kwargs)

def match_depth(self, mobject, **kwargs):
def match_depth(self, mobject: "Mobject", **kwargs):
return self.match_dim_size(mobject, 2, **kwargs)

def match_coord(self, mobject, dim, direction=ORIGIN):
def match_coord(self, mobject: "Mobject", dim, direction=ORIGIN):
return self.set_coord(
mobject.get_coord(dim, direction),
dim=dim,
direction=direction,
)

def match_x(self, mobject, direction=ORIGIN):
def match_x(self, mobject: "Mobject", direction=ORIGIN):
return self.match_coord(mobject, 0, direction)

def match_y(self, mobject, direction=ORIGIN):
def match_y(self, mobject: "Mobject", direction=ORIGIN):
return self.match_coord(mobject, 1, direction)

def match_z(self, mobject, direction=ORIGIN):
def match_z(self, mobject: "Mobject", direction=ORIGIN):
return self.match_coord(mobject, 2, direction)

def align_to(self, mobject_or_point, direction=ORIGIN, alignment_vect=UP):
def align_to(
self,
mobject_or_point: Union["Mobject", np.ndarray, List],
direction=ORIGIN,
alignment_vect=UP,
):
"""Examples:
mob1.align_to(mob2, UP) moves mob1 vertically so that its
top edge lines ups with mob2's top edge.
Expand Down Expand Up @@ -1865,7 +1909,7 @@ def family_members_with_points(self):

def arrange(
self,
direction=RIGHT,
direction: Union[np.ndarray, List] = RIGHT,
buff=DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
center=True,
**kwargs,
Expand Down Expand Up @@ -1952,7 +1996,7 @@ def align_data(self, mobject):
m1.align_data(m2)

def get_point_mobject(self, center=None):
"""The simplest mobject to be transformed to or from self.
"""The simplest :class:`~.Mobject` to be transformed to or from self.
Should by a point of the appropriate type
"""
msg = f"get_point_mobject not implemented for {self.__class__.__name__}"
Expand Down Expand Up @@ -1980,7 +2024,7 @@ def align_submobjects(self, mobject):
return self

def null_point_align(self, mobject: "Mobject") -> "Mobject":
"""If a mobject with points is being aligned to
"""If a :class:`~.Mobject` with points is being aligned to
one without, treat both as groups, and push
the one with points into its own submobjects
list.
Expand Down Expand Up @@ -2024,7 +2068,7 @@ def repeat_submobject(self, submob):
return submob.copy()

def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path):
"""Turns this mobject into an interpolation between ``mobject1``
"""Turns this :class:`~.Mobject` into an interpolation between ``mobject1``
and ``mobject2``.

Examples
Expand Down Expand Up @@ -2061,7 +2105,7 @@ def pointwise_become_partial(self, mobject, a, b):

def become(self, mobject: "Mobject", copy_submobjects: bool = True):
"""Edit points, colors and submobjects to be identical
to another mobject
to another :class:`~.Mobject`

Examples
--------
Expand Down Expand Up @@ -2099,7 +2143,7 @@ def throw_error_if_no_points(self):

# About z-index
def set_z_index(self, z_index_value: Union[int, float]):
"""Sets the mobject's :attr:`z_index` to the value specified in `z_index_value`.
"""Sets the :class:`~.Mobject`'s :attr:`z_index` to the value specified in `z_index_value`.

Parameters
----------
Expand All @@ -2115,7 +2159,7 @@ def set_z_index(self, z_index_value: Union[int, float]):
return self

def set_z_index_by_z_coordinate(self):
"""Sets the mobject's z coordinate to the value of :attr:`z_index`.
"""Sets the :class:`~.Mobject`'s z coordinate to the value of :attr:`z_index`.

Returns
-------
Expand All @@ -2128,7 +2172,7 @@ def set_z_index_by_z_coordinate(self):


class Group(Mobject):
"""Groups together multiple Mobjects."""
"""Groups together multiple :class:`~.Mobject`s."""

def __init__(self, *mobjects, **kwargs):
Mobject.__init__(self, **kwargs)
Expand Down