diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py index 13a6544038..5c3ffd6d1e 100644 --- a/manim/mobject/mobject.py +++ b/manim/mobject/mobject.py @@ -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( @@ -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): @@ -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 -------- @@ -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 ------- @@ -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 ------- @@ -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 ------- @@ -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 ------- @@ -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) @@ -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): @@ -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: @@ -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) @@ -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 @@ -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) @@ -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. @@ -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): @@ -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): @@ -1716,24 +1747,29 @@ 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]) @@ -1741,6 +1777,7 @@ def get_start(self): 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]) @@ -1748,6 +1785,7 @@ def get_end(self): 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): @@ -1770,6 +1808,7 @@ 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): @@ -1777,38 +1816,43 @@ def has_no_points(self): # 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. @@ -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, @@ -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__}" @@ -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. @@ -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 @@ -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 -------- @@ -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 ---------- @@ -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 ------- @@ -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)