manim 0.18.0__py3-none-any.whl → 0.18.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of manim might be problematic. Click here for more details.

Files changed (115) hide show
  1. manim/__init__.py +3 -6
  2. manim/__main__.py +18 -10
  3. manim/_config/__init__.py +5 -2
  4. manim/_config/cli_colors.py +12 -8
  5. manim/_config/default.cfg +1 -1
  6. manim/_config/logger_utils.py +9 -8
  7. manim/_config/utils.py +637 -449
  8. manim/animation/animation.py +9 -2
  9. manim/animation/composition.py +78 -40
  10. manim/animation/creation.py +12 -6
  11. manim/animation/fading.py +0 -1
  12. manim/animation/indication.py +10 -21
  13. manim/animation/movement.py +1 -2
  14. manim/animation/rotation.py +1 -1
  15. manim/animation/specialized.py +1 -1
  16. manim/animation/speedmodifier.py +7 -2
  17. manim/animation/transform_matching_parts.py +1 -1
  18. manim/camera/camera.py +13 -4
  19. manim/cli/cfg/group.py +18 -8
  20. manim/cli/checkhealth/checks.py +2 -0
  21. manim/cli/checkhealth/commands.py +2 -0
  22. manim/cli/default_group.py +13 -5
  23. manim/cli/init/commands.py +4 -1
  24. manim/cli/plugins/commands.py +3 -0
  25. manim/cli/render/commands.py +27 -20
  26. manim/cli/render/ease_of_access_options.py +4 -3
  27. manim/cli/render/global_options.py +9 -7
  28. manim/cli/render/output_options.py +6 -5
  29. manim/cli/render/render_options.py +13 -13
  30. manim/constants.py +54 -15
  31. manim/gui/gui.py +2 -0
  32. manim/mobject/geometry/arc.py +4 -4
  33. manim/mobject/geometry/boolean_ops.py +13 -9
  34. manim/mobject/geometry/line.py +16 -8
  35. manim/mobject/geometry/polygram.py +17 -5
  36. manim/mobject/geometry/tips.py +2 -2
  37. manim/mobject/graph.py +379 -106
  38. manim/mobject/graphing/coordinate_systems.py +17 -20
  39. manim/mobject/graphing/functions.py +14 -10
  40. manim/mobject/graphing/number_line.py +1 -1
  41. manim/mobject/mobject.py +175 -72
  42. manim/mobject/opengl/opengl_compatibility.py +2 -0
  43. manim/mobject/opengl/opengl_geometry.py +26 -1
  44. manim/mobject/opengl/opengl_image_mobject.py +2 -0
  45. manim/mobject/opengl/opengl_mobject.py +3 -0
  46. manim/mobject/opengl/opengl_point_cloud_mobject.py +2 -0
  47. manim/mobject/opengl/opengl_surface.py +2 -0
  48. manim/mobject/opengl/opengl_three_dimensions.py +2 -0
  49. manim/mobject/opengl/opengl_vectorized_mobject.py +19 -14
  50. manim/mobject/svg/brace.py +2 -0
  51. manim/mobject/svg/svg_mobject.py +10 -12
  52. manim/mobject/table.py +0 -1
  53. manim/mobject/text/code_mobject.py +2 -0
  54. manim/mobject/text/numbers.py +2 -0
  55. manim/mobject/text/tex_mobject.py +1 -1
  56. manim/mobject/text/text_mobject.py +43 -6
  57. manim/mobject/three_d/three_d_utils.py +4 -4
  58. manim/mobject/three_d/three_dimensions.py +4 -4
  59. manim/mobject/types/image_mobject.py +5 -1
  60. manim/mobject/types/point_cloud_mobject.py +2 -0
  61. manim/mobject/types/vectorized_mobject.py +124 -29
  62. manim/mobject/value_tracker.py +3 -3
  63. manim/mobject/vector_field.py +3 -1
  64. manim/plugins/__init__.py +15 -1
  65. manim/plugins/plugins_flags.py +11 -5
  66. manim/renderer/cairo_renderer.py +12 -2
  67. manim/renderer/opengl_renderer.py +2 -3
  68. manim/renderer/opengl_renderer_window.py +2 -0
  69. manim/renderer/shader_wrapper.py +2 -0
  70. manim/renderer/vectorized_mobject_rendering.py +5 -0
  71. manim/scene/scene.py +22 -6
  72. manim/scene/scene_file_writer.py +3 -1
  73. manim/scene/section.py +2 -0
  74. manim/scene/three_d_scene.py +5 -6
  75. manim/scene/vector_space_scene.py +21 -5
  76. manim/typing.py +567 -67
  77. manim/utils/bezier.py +9 -18
  78. manim/utils/caching.py +2 -0
  79. manim/utils/color/BS381.py +1 -0
  80. manim/utils/color/XKCD.py +1 -0
  81. manim/utils/color/core.py +31 -13
  82. manim/utils/commands.py +8 -1
  83. manim/utils/debug.py +0 -1
  84. manim/utils/deprecation.py +3 -2
  85. manim/utils/docbuild/__init__.py +17 -0
  86. manim/utils/docbuild/autoaliasattr_directive.py +197 -0
  87. manim/utils/docbuild/autocolor_directive.py +9 -4
  88. manim/utils/docbuild/manim_directive.py +18 -9
  89. manim/utils/docbuild/module_parsing.py +198 -0
  90. manim/utils/exceptions.py +6 -0
  91. manim/utils/family.py +2 -0
  92. manim/utils/family_ops.py +5 -0
  93. manim/utils/file_ops.py +6 -2
  94. manim/utils/hashing.py +2 -0
  95. manim/utils/ipython_magic.py +2 -0
  96. manim/utils/module_ops.py +2 -0
  97. manim/utils/opengl.py +14 -0
  98. manim/utils/parameter_parsing.py +31 -0
  99. manim/utils/paths.py +12 -20
  100. manim/utils/rate_functions.py +6 -8
  101. manim/utils/space_ops.py +81 -36
  102. manim/utils/testing/__init__.py +17 -0
  103. manim/utils/testing/frames_comparison.py +7 -5
  104. manim/utils/tex.py +124 -196
  105. manim/utils/tex_file_writing.py +2 -0
  106. manim/utils/tex_templates.py +1 -0
  107. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/LICENSE.community +1 -1
  108. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/METADATA +29 -35
  109. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/RECORD +112 -112
  110. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/WHEEL +1 -1
  111. manim/cli/new/__init__.py +0 -0
  112. manim/cli/new/group.py +0 -189
  113. manim/plugins/import_plugins.py +0 -43
  114. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/LICENSE +0 -0
  115. {manim-0.18.0.dist-info → manim-0.18.1.dist-info}/entry_points.txt +0 -0
manim/mobject/mobject.py CHANGED
@@ -16,10 +16,9 @@ import types
16
16
  import warnings
17
17
  from functools import partialmethod, reduce
18
18
  from pathlib import Path
19
- from typing import TYPE_CHECKING, Callable, Iterable, Literal, TypeVar, Union
19
+ from typing import TYPE_CHECKING, Callable, Iterable, Literal
20
20
 
21
21
  import numpy as np
22
- from typing_extensions import Self, TypeAlias
23
22
 
24
23
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
25
24
 
@@ -39,14 +38,9 @@ from ..utils.iterables import list_update, remove_list_redundancies
39
38
  from ..utils.paths import straight_path
40
39
  from ..utils.space_ops import angle_between_vectors, normalize, rotation_matrix
41
40
 
42
- # TODO: Explain array_attrs
43
-
44
- TimeBasedUpdater: TypeAlias = Callable[["Mobject", float], None]
45
- NonTimeBasedUpdater: TypeAlias = Callable[["Mobject"], None]
46
- Updater: TypeAlias = Union[NonTimeBasedUpdater, TimeBasedUpdater]
47
- T = TypeVar("T", bound="Mobject")
48
-
49
41
  if TYPE_CHECKING:
42
+ from typing_extensions import Self, TypeAlias
43
+
50
44
  from manim.typing import (
51
45
  FunctionOverride,
52
46
  Image,
@@ -56,12 +50,15 @@ if TYPE_CHECKING:
56
50
  PathFuncType,
57
51
  Point3D,
58
52
  Point3D_Array,
59
- Vector,
60
- Vector3,
53
+ Vector3D,
61
54
  )
62
55
 
63
56
  from ..animation.animation import Animation
64
57
 
58
+ TimeBasedUpdater: TypeAlias = Callable[["Mobject", float], object]
59
+ NonTimeBasedUpdater: TypeAlias = Callable[["Mobject"], object]
60
+ Updater: TypeAlias = NonTimeBasedUpdater | TimeBasedUpdater
61
+
65
62
 
66
63
  class Mobject:
67
64
  """Mathematical Object: base class for objects that can be displayed on screen.
@@ -238,7 +235,7 @@ class Mobject:
238
235
  cls.__init__ = cls._original__init__
239
236
 
240
237
  @property
241
- def animate(self) -> _AnimationBuilder | T:
238
+ def animate(self) -> _AnimationBuilder | Self:
242
239
  """Used to animate the application of any method of :code:`self`.
243
240
 
244
241
  Any method called on :code:`animate` is converted to an animation of applying
@@ -883,7 +880,7 @@ class Mobject:
883
880
 
884
881
  Returns
885
882
  -------
886
- class:`bool`
883
+ :class:`bool`
887
884
  ``True`` if at least one updater uses the ``dt`` parameter, ``False``
888
885
  otherwise.
889
886
 
@@ -968,11 +965,11 @@ class Mobject:
968
965
 
969
966
  class DtUpdater(Scene):
970
967
  def construct(self):
971
- line = Square()
968
+ square = Square()
972
969
 
973
- #Let the line rotate 90° per second
974
- line.add_updater(lambda mobject, dt: mobject.rotate(dt*90*DEGREES))
975
- self.add(line)
970
+ #Let the square rotate 90° per second
971
+ square.add_updater(lambda mobject, dt: mobject.rotate(dt*90*DEGREES))
972
+ self.add(square)
976
973
  self.wait(2)
977
974
 
978
975
  See also
@@ -1154,7 +1151,7 @@ class Mobject:
1154
1151
  for mob in self.family_members_with_points():
1155
1152
  func(mob)
1156
1153
 
1157
- def shift(self, *vectors: Vector3) -> Self:
1154
+ def shift(self, *vectors: Vector3D) -> Self:
1158
1155
  """Shift by the given vectors.
1159
1156
 
1160
1157
  Parameters
@@ -1226,14 +1223,14 @@ class Mobject:
1226
1223
  )
1227
1224
  return self
1228
1225
 
1229
- def rotate_about_origin(self, angle: float, axis: Vector3 = OUT, axes=[]) -> Self:
1226
+ def rotate_about_origin(self, angle: float, axis: Vector3D = OUT, axes=[]) -> Self:
1230
1227
  """Rotates the :class:`~.Mobject` about the ORIGIN, which is at [0,0,0]."""
1231
1228
  return self.rotate(angle, axis, about_point=ORIGIN)
1232
1229
 
1233
1230
  def rotate(
1234
1231
  self,
1235
1232
  angle: float,
1236
- axis: Vector3 = OUT,
1233
+ axis: Vector3D = OUT,
1237
1234
  about_point: Point3D | None = None,
1238
1235
  **kwargs,
1239
1236
  ) -> Self:
@@ -1244,7 +1241,7 @@ class Mobject:
1244
1241
  )
1245
1242
  return self
1246
1243
 
1247
- def flip(self, axis: Vector3 = UP, **kwargs) -> Self:
1244
+ def flip(self, axis: Vector3D = UP, **kwargs) -> Self:
1248
1245
  """Flips/Mirrors an mobject about its center.
1249
1246
 
1250
1247
  Examples
@@ -1337,20 +1334,6 @@ class Mobject:
1337
1334
 
1338
1335
  return self.apply_function(R3_func)
1339
1336
 
1340
- def wag(
1341
- self, direction: Vector3 = RIGHT, axis: Vector3 = DOWN, wag_factor: float = 1.0
1342
- ) -> Self:
1343
- for mob in self.family_members_with_points():
1344
- alphas = np.dot(mob.points, np.transpose(axis))
1345
- alphas -= min(alphas)
1346
- alphas /= max(alphas)
1347
- alphas = alphas**wag_factor
1348
- mob.points += np.dot(
1349
- alphas.reshape((len(alphas), 1)),
1350
- np.array(direction).reshape((1, mob.dim)),
1351
- )
1352
- return self
1353
-
1354
1337
  def reverse_points(self) -> Self:
1355
1338
  for mob in self.family_members_with_points():
1356
1339
  mob.apply_over_attr_arrays(lambda arr: np.array(list(reversed(arr))))
@@ -1404,7 +1387,7 @@ class Mobject:
1404
1387
  return self
1405
1388
 
1406
1389
  def align_on_border(
1407
- self, direction: Vector3, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1390
+ self, direction: Vector3D, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1408
1391
  ) -> Self:
1409
1392
  """Direction just needs to be a vector pointing towards side or
1410
1393
  corner in the 2d plane.
@@ -1421,24 +1404,72 @@ class Mobject:
1421
1404
  return self
1422
1405
 
1423
1406
  def to_corner(
1424
- self, corner: Vector3 = DL, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1407
+ self, corner: Vector3D = DL, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1425
1408
  ) -> Self:
1409
+ """Moves this :class:`~.Mobject` to the given corner of the screen.
1410
+
1411
+ Returns
1412
+ -------
1413
+ :class:`.Mobject`
1414
+ The newly positioned mobject.
1415
+
1416
+ Examples
1417
+ --------
1418
+
1419
+ .. manim:: ToCornerExample
1420
+ :save_last_frame:
1421
+
1422
+ class ToCornerExample(Scene):
1423
+ def construct(self):
1424
+ c = Circle()
1425
+ c.to_corner(UR)
1426
+ t = Tex("To the corner!")
1427
+ t2 = MathTex("x^3").shift(DOWN)
1428
+ self.add(c,t,t2)
1429
+ t.to_corner(DL, buff=0)
1430
+ t2.to_corner(UL, buff=1.5)
1431
+ """
1426
1432
  return self.align_on_border(corner, buff)
1427
1433
 
1428
1434
  def to_edge(
1429
- self, edge: Vector3 = LEFT, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1435
+ self, edge: Vector3D = LEFT, buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
1430
1436
  ) -> Self:
1437
+ """Moves this :class:`~.Mobject` to the given edge of the screen,
1438
+ without affecting its position in the other dimension.
1439
+
1440
+ Returns
1441
+ -------
1442
+ :class:`.Mobject`
1443
+ The newly positioned mobject.
1444
+
1445
+ Examples
1446
+ --------
1447
+
1448
+ .. manim:: ToEdgeExample
1449
+ :save_last_frame:
1450
+
1451
+ class ToEdgeExample(Scene):
1452
+ def construct(self):
1453
+ tex_top = Tex("I am at the top!")
1454
+ tex_top.to_edge(UP)
1455
+ tex_side = Tex("I am moving to the side!")
1456
+ c = Circle().shift(2*DOWN)
1457
+ self.add(tex_top, tex_side)
1458
+ tex_side.to_edge(LEFT)
1459
+ c.to_edge(RIGHT, buff=0)
1460
+
1461
+ """
1431
1462
  return self.align_on_border(edge, buff)
1432
1463
 
1433
1464
  def next_to(
1434
1465
  self,
1435
1466
  mobject_or_point: Mobject | Point3D,
1436
- direction: Vector3 = RIGHT,
1467
+ direction: Vector3D = RIGHT,
1437
1468
  buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
1438
- aligned_edge: Vector3 = ORIGIN,
1469
+ aligned_edge: Vector3D = ORIGIN,
1439
1470
  submobject_to_align: Mobject | None = None,
1440
1471
  index_of_submobject_to_align: int | None = None,
1441
- coor_mask: Vector3 = np.array([1, 1, 1]),
1472
+ coor_mask: Vector3D = np.array([1, 1, 1]),
1442
1473
  ) -> Self:
1443
1474
  """Move this :class:`~.Mobject` next to another's :class:`~.Mobject` or Point3D.
1444
1475
 
@@ -1630,22 +1661,22 @@ class Mobject:
1630
1661
 
1631
1662
  return self.rescale_to_fit(depth, 2, stretch=True, **kwargs)
1632
1663
 
1633
- def set_coord(self, value, dim: int, direction: Vector3 = ORIGIN) -> Self:
1664
+ def set_coord(self, value, dim: int, direction: Vector3D = ORIGIN) -> Self:
1634
1665
  curr = self.get_coord(dim, direction)
1635
1666
  shift_vect = np.zeros(self.dim)
1636
1667
  shift_vect[dim] = value - curr
1637
1668
  self.shift(shift_vect)
1638
1669
  return self
1639
1670
 
1640
- def set_x(self, x: float, direction: Vector3 = ORIGIN) -> Self:
1671
+ def set_x(self, x: float, direction: Vector3D = ORIGIN) -> Self:
1641
1672
  """Set x value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
1642
1673
  return self.set_coord(x, 0, direction)
1643
1674
 
1644
- def set_y(self, y: float, direction: Vector3 = ORIGIN) -> Self:
1675
+ def set_y(self, y: float, direction: Vector3D = ORIGIN) -> Self:
1645
1676
  """Set y value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
1646
1677
  return self.set_coord(y, 1, direction)
1647
1678
 
1648
- def set_z(self, z: float, direction: Vector3 = ORIGIN) -> Self:
1679
+ def set_z(self, z: float, direction: Vector3D = ORIGIN) -> Self:
1649
1680
  """Set z value of the center of the :class:`~.Mobject` (``int`` or ``float``)"""
1650
1681
  return self.set_coord(z, 2, direction)
1651
1682
 
@@ -1658,8 +1689,8 @@ class Mobject:
1658
1689
  def move_to(
1659
1690
  self,
1660
1691
  point_or_mobject: Point3D | Mobject,
1661
- aligned_edge: Vector3 = ORIGIN,
1662
- coor_mask: Vector3 = np.array([1, 1, 1]),
1692
+ aligned_edge: Vector3D = ORIGIN,
1693
+ coor_mask: Vector3D = np.array([1, 1, 1]),
1663
1694
  ) -> Self:
1664
1695
  """Move center of the :class:`~.Mobject` to certain Point3D."""
1665
1696
  if isinstance(point_or_mobject, Mobject):
@@ -1703,7 +1734,8 @@ class Mobject:
1703
1734
  curr_start, curr_end = self.get_start_and_end()
1704
1735
  curr_vect = curr_end - curr_start
1705
1736
  if np.all(curr_vect == 0):
1706
- raise Exception("Cannot position endpoints of closed loop")
1737
+ self.points = start
1738
+ return self
1707
1739
  target_vect = np.array(end) - np.array(start)
1708
1740
  axis = (
1709
1741
  normalize(np.cross(curr_vect, target_vect))
@@ -1872,7 +1904,17 @@ class Mobject:
1872
1904
  return self
1873
1905
 
1874
1906
  def get_color(self) -> ManimColor:
1875
- """Returns the color of the :class:`~.Mobject`"""
1907
+ """Returns the color of the :class:`~.Mobject`
1908
+
1909
+ Examples
1910
+ --------
1911
+ ::
1912
+
1913
+ >>> from manim import Square, RED
1914
+ >>> Square(color=RED).get_color() == RED
1915
+ True
1916
+
1917
+ """
1876
1918
  return self.color
1877
1919
 
1878
1920
  ##
@@ -1964,7 +2006,7 @@ class Mobject:
1964
2006
  else:
1965
2007
  return np.max(values)
1966
2008
 
1967
- def get_critical_point(self, direction: Vector3) -> Point3D:
2009
+ def get_critical_point(self, direction: Vector3D) -> Point3D:
1968
2010
  """Picture a box bounding the :class:`~.Mobject`. Such a box has
1969
2011
  9 'critical points': 4 corners, 4 edge center, the
1970
2012
  center. This returns one of them, along the given direction.
@@ -1993,11 +2035,11 @@ class Mobject:
1993
2035
 
1994
2036
  # Pseudonyms for more general get_critical_point method
1995
2037
 
1996
- def get_edge_center(self, direction: Vector3) -> Point3D:
2038
+ def get_edge_center(self, direction: Vector3D) -> Point3D:
1997
2039
  """Get edge Point3Ds for certain direction."""
1998
2040
  return self.get_critical_point(direction)
1999
2041
 
2000
- def get_corner(self, direction: Vector3) -> Point3D:
2042
+ def get_corner(self, direction: Vector3D) -> Point3D:
2001
2043
  """Get corner Point3Ds for certain direction."""
2002
2044
  return self.get_critical_point(direction)
2003
2045
 
@@ -2008,7 +2050,7 @@ class Mobject:
2008
2050
  def get_center_of_mass(self) -> Point3D:
2009
2051
  return np.apply_along_axis(np.mean, 0, self.get_all_points())
2010
2052
 
2011
- def get_boundary_point(self, direction: Vector3) -> Point3D:
2053
+ def get_boundary_point(self, direction: Vector3D) -> Point3D:
2012
2054
  all_points = self.get_points_defining_boundary()
2013
2055
  index = np.argmax(np.dot(all_points, np.array(direction).T))
2014
2056
  return all_points[index]
@@ -2067,19 +2109,19 @@ class Mobject:
2067
2109
  dim,
2068
2110
  ) - self.reduce_across_dimension(min, dim)
2069
2111
 
2070
- def get_coord(self, dim: int, direction: Vector3 = ORIGIN):
2112
+ def get_coord(self, dim: int, direction: Vector3D = ORIGIN):
2071
2113
  """Meant to generalize ``get_x``, ``get_y`` and ``get_z``"""
2072
2114
  return self.get_extremum_along_dim(dim=dim, key=direction[dim])
2073
2115
 
2074
- def get_x(self, direction: Vector3 = ORIGIN) -> ManimFloat:
2116
+ def get_x(self, direction: Vector3D = ORIGIN) -> ManimFloat:
2075
2117
  """Returns x Point3D of the center of the :class:`~.Mobject` as ``float``"""
2076
2118
  return self.get_coord(0, direction)
2077
2119
 
2078
- def get_y(self, direction: Vector3 = ORIGIN) -> ManimFloat:
2120
+ def get_y(self, direction: Vector3D = ORIGIN) -> ManimFloat:
2079
2121
  """Returns y Point3D of the center of the :class:`~.Mobject` as ``float``"""
2080
2122
  return self.get_coord(1, direction)
2081
2123
 
2082
- def get_z(self, direction: Vector3 = ORIGIN) -> ManimFloat:
2124
+ def get_z(self, direction: Vector3D = ORIGIN) -> ManimFloat:
2083
2125
  """Returns z Point3D of the center of the :class:`~.Mobject` as ``float``"""
2084
2126
  return self.get_coord(2, direction)
2085
2127
 
@@ -2150,7 +2192,7 @@ class Mobject:
2150
2192
  return self.match_dim_size(mobject, 2, **kwargs)
2151
2193
 
2152
2194
  def match_coord(
2153
- self, mobject: Mobject, dim: int, direction: Vector3 = ORIGIN
2195
+ self, mobject: Mobject, dim: int, direction: Vector3D = ORIGIN
2154
2196
  ) -> Self:
2155
2197
  """Match the Point3Ds with the Point3Ds of another :class:`~.Mobject`."""
2156
2198
  return self.set_coord(
@@ -2174,7 +2216,7 @@ class Mobject:
2174
2216
  def align_to(
2175
2217
  self,
2176
2218
  mobject_or_point: Mobject | Point3D,
2177
- direction: Vector3 = ORIGIN,
2219
+ direction: Vector3D = ORIGIN,
2178
2220
  ) -> Self:
2179
2221
  """Aligns mobject to another :class:`~.Mobject` in a certain direction.
2180
2222
 
@@ -2229,7 +2271,7 @@ class Mobject:
2229
2271
 
2230
2272
  def arrange(
2231
2273
  self,
2232
- direction: Vector3 = RIGHT,
2274
+ direction: Vector3D = RIGHT,
2233
2275
  buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
2234
2276
  center: bool = True,
2235
2277
  **kwargs,
@@ -2262,7 +2304,7 @@ class Mobject:
2262
2304
  rows: int | None = None,
2263
2305
  cols: int | None = None,
2264
2306
  buff: float | tuple[float, float] = MED_SMALL_BUFF,
2265
- cell_alignment: Vector3 = ORIGIN,
2307
+ cell_alignment: Vector3D = ORIGIN,
2266
2308
  row_alignments: str | None = None, # "ucd"
2267
2309
  col_alignments: str | None = None, # "lcr"
2268
2310
  row_heights: Iterable[float | None] | None = None,
@@ -2667,13 +2709,13 @@ class Mobject:
2667
2709
 
2668
2710
  def add_n_more_submobjects(self, n: int) -> Self | None:
2669
2711
  if n == 0:
2670
- return
2712
+ return None
2671
2713
 
2672
2714
  curr = len(self.submobjects)
2673
2715
  if curr == 0:
2674
2716
  # If empty, simply add n point mobjects
2675
2717
  self.submobjects = [self.get_point_mobject() for k in range(n)]
2676
- return
2718
+ return None
2677
2719
 
2678
2720
  target = curr + n
2679
2721
  # TODO, factor this out to utils so as to reuse
@@ -2728,7 +2770,6 @@ class Mobject:
2728
2770
  def become(
2729
2771
  self,
2730
2772
  mobject: Mobject,
2731
- copy_submobjects: bool = True,
2732
2773
  match_height: bool = False,
2733
2774
  match_width: bool = False,
2734
2775
  match_depth: bool = False,
@@ -2741,20 +2782,25 @@ class Mobject:
2741
2782
  .. note::
2742
2783
 
2743
2784
  If both match_height and match_width are ``True`` then the transformed :class:`~.Mobject`
2744
- will match the height first and then the width
2785
+ will match the height first and then the width.
2745
2786
 
2746
2787
  Parameters
2747
2788
  ----------
2748
2789
  match_height
2749
- If ``True``, then the transformed :class:`~.Mobject` will match the height of the original
2790
+ Whether or not to preserve the height of the original
2791
+ :class:`~.Mobject`.
2750
2792
  match_width
2751
- If ``True``, then the transformed :class:`~.Mobject` will match the width of the original
2793
+ Whether or not to preserve the width of the original
2794
+ :class:`~.Mobject`.
2752
2795
  match_depth
2753
- If ``True``, then the transformed :class:`~.Mobject` will match the depth of the original
2796
+ Whether or not to preserve the depth of the original
2797
+ :class:`~.Mobject`.
2754
2798
  match_center
2755
- If ``True``, then the transformed :class:`~.Mobject` will match the center of the original
2799
+ Whether or not to preserve the center of the original
2800
+ :class:`~.Mobject`.
2756
2801
  stretch
2757
- If ``True``, then the transformed :class:`~.Mobject` will stretch to fit the proportions of the original
2802
+ Whether or not to stretch the target mobject to match the
2803
+ the proportions of the original :class:`~.Mobject`.
2758
2804
 
2759
2805
  Examples
2760
2806
  --------
@@ -2768,8 +2814,65 @@ class Mobject:
2768
2814
  self.wait(0.5)
2769
2815
  circ.become(square)
2770
2816
  self.wait(0.5)
2771
- """
2772
2817
 
2818
+
2819
+ The following examples illustrate how mobject measurements
2820
+ change when using the ``match_...`` and ``stretch`` arguments.
2821
+ We start with a rectangle that is 2 units high and 4 units wide,
2822
+ which we want to turn into a circle of radius 3::
2823
+
2824
+ >>> from manim import Rectangle, Circle
2825
+ >>> import numpy as np
2826
+ >>> rect = Rectangle(height=2, width=4)
2827
+ >>> circ = Circle(radius=3)
2828
+
2829
+ With ``stretch=True``, the target circle is deformed to match
2830
+ the proportions of the rectangle, which results in the target
2831
+ mobject being an ellipse with height 2 and width 4. We can
2832
+ check that the resulting points satisfy the ellipse equation
2833
+ :math:`x^2/a^2 + y^2/b^2 = 1` with :math:`a = 4/2` and :math:`b = 2/2`
2834
+ being the semi-axes::
2835
+
2836
+ >>> result = rect.copy().become(circ, stretch=True)
2837
+ >>> result.height, result.width
2838
+ (2.0, 4.0)
2839
+ >>> ellipse_points = np.array(result.get_anchors())
2840
+ >>> ellipse_eq = np.sum(ellipse_points**2 * [1/4, 1, 0], axis=1)
2841
+ >>> np.allclose(ellipse_eq, 1)
2842
+ True
2843
+
2844
+ With ``match_height=True`` and ``match_width=True`` the circle is
2845
+ scaled such that the height or the width of the rectangle will
2846
+ be preserved, respectively.
2847
+ The points of the resulting mobject satisfy the circle equation
2848
+ :math:`x^2 + y^2 = r^2` for the corresponding radius :math:`r`::
2849
+
2850
+ >>> result = rect.copy().become(circ, match_height=True)
2851
+ >>> result.height, result.width
2852
+ (2.0, 2.0)
2853
+ >>> circle_points = np.array(result.get_anchors())
2854
+ >>> circle_eq = np.sum(circle_points**2, axis=1)
2855
+ >>> np.allclose(circle_eq, 1)
2856
+ True
2857
+ >>> result = rect.copy().become(circ, match_width=True)
2858
+ >>> result.height, result.width
2859
+ (4.0, 4.0)
2860
+ >>> circle_points = np.array(result.get_anchors())
2861
+ >>> circle_eq = np.sum(circle_points**2, axis=1)
2862
+ >>> np.allclose(circle_eq, 2**2)
2863
+ True
2864
+
2865
+ With ``match_center=True``, the resulting mobject is moved such that
2866
+ its center is the same as the center of the original mobject::
2867
+
2868
+ >>> rect = rect.shift(np.array([0, 1, 0]))
2869
+ >>> np.allclose(rect.get_center(), circ.get_center())
2870
+ False
2871
+ >>> result = rect.copy().become(circ, match_center=True)
2872
+ >>> np.allclose(rect.get_center(), result.get_center())
2873
+ True
2874
+ """
2875
+ mobject = mobject.copy()
2773
2876
  if stretch:
2774
2877
  mobject.stretch_to_fit_height(self.height)
2775
2878
  mobject.stretch_to_fit_width(self.width)
@@ -2825,7 +2928,7 @@ class Mobject:
2825
2928
  self,
2826
2929
  z_index_value: float,
2827
2930
  family: bool = True,
2828
- ) -> T:
2931
+ ) -> Self:
2829
2932
  """Sets the :class:`~.Mobject`'s :attr:`z_index` to the value specified in `z_index_value`.
2830
2933
 
2831
2934
  Parameters
@@ -10,6 +10,8 @@ from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
10
10
 
11
11
  from ...constants import RendererType
12
12
 
13
+ __all__ = ["ConvertToOpenGL"]
14
+
13
15
 
14
16
  class ConvertToOpenGL(ABCMeta):
15
17
  """Metaclass for swapping (V)Mobject with its OpenGL counterpart at runtime
@@ -23,11 +23,36 @@ from manim.utils.space_ops import (
23
23
  )
24
24
 
25
25
  DEFAULT_DOT_RADIUS = 0.08
26
- DEFAULT_SMALL_DOT_RADIUS = 0.04
27
26
  DEFAULT_DASH_LENGTH = 0.05
28
27
  DEFAULT_ARROW_TIP_LENGTH = 0.35
29
28
  DEFAULT_ARROW_TIP_WIDTH = 0.35
30
29
 
30
+ __all__ = [
31
+ "OpenGLTipableVMobject",
32
+ "OpenGLArc",
33
+ "OpenGLArcBetweenPoints",
34
+ "OpenGLCurvedArrow",
35
+ "OpenGLCurvedDoubleArrow",
36
+ "OpenGLCircle",
37
+ "OpenGLDot",
38
+ "OpenGLEllipse",
39
+ "OpenGLAnnularSector",
40
+ "OpenGLSector",
41
+ "OpenGLAnnulus",
42
+ "OpenGLLine",
43
+ "OpenGLDashedLine",
44
+ "OpenGLTangentLine",
45
+ "OpenGLElbow",
46
+ "OpenGLArrow",
47
+ "OpenGLVector",
48
+ "OpenGLDoubleArrow",
49
+ "OpenGLCubicBezier",
50
+ "OpenGLPolygon",
51
+ "OpenGLRegularPolygon",
52
+ "OpenGLTriangle",
53
+ "OpenGLArrowTip",
54
+ ]
55
+
31
56
 
32
57
  class OpenGLTipableVMobject(OpenGLVMobject):
33
58
  """
@@ -13,6 +13,8 @@ from PIL.Image import Resampling
13
13
  from manim.mobject.opengl.opengl_surface import OpenGLSurface, OpenGLTexturedSurface
14
14
  from manim.utils.images import get_full_raster_image_path
15
15
 
16
+ __all__ = ["OpenGLImageMobject"]
17
+
16
18
 
17
19
  class OpenGLImageMobject(OpenGLTexturedSurface):
18
20
  def __init__(
@@ -56,6 +56,9 @@ def affects_shader_info_id(func):
56
56
  return wrapper
57
57
 
58
58
 
59
+ __all__ = ["OpenGLMobject", "OpenGLGroup", "OpenGLPoint", "_AnimationBuilder"]
60
+
61
+
59
62
  class OpenGLMobject:
60
63
  """Mathematical Object: base class for objects that can be displayed on screen.
61
64
 
@@ -12,6 +12,8 @@ from manim.utils.color import BLACK, WHITE, YELLOW, color_gradient, color_to_rgb
12
12
  from manim.utils.config_ops import _Uniforms
13
13
  from manim.utils.iterables import resize_with_interpolation
14
14
 
15
+ __all__ = ["OpenGLPMobject", "OpenGLPGroup", "OpenGLPMPoint"]
16
+
15
17
 
16
18
  class OpenGLPMobject(OpenGLMobject):
17
19
  shader_folder = "true_dot"
@@ -17,6 +17,8 @@ from manim.utils.images import change_to_rgba_array, get_full_raster_image_path
17
17
  from manim.utils.iterables import listify
18
18
  from manim.utils.space_ops import normalize_along_axis
19
19
 
20
+ __all__ = ["OpenGLSurface", "OpenGLTexturedSurface"]
21
+
20
22
 
21
23
  class OpenGLSurface(OpenGLMobject):
22
24
  r"""Creates a Surface.
@@ -5,6 +5,8 @@ import numpy as np
5
5
  from manim.mobject.opengl.opengl_surface import OpenGLSurface
6
6
  from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVGroup, OpenGLVMobject
7
7
 
8
+ __all__ = ["OpenGLSurfaceMesh"]
9
+
8
10
 
9
11
  class OpenGLSurfaceMesh(OpenGLVGroup):
10
12
  def __init__(
@@ -34,6 +34,15 @@ from manim.utils.space_ops import (
34
34
  z_to_vector,
35
35
  )
36
36
 
37
+ __all__ = [
38
+ "triggers_refreshed_triangulation",
39
+ "OpenGLVMobject",
40
+ "OpenGLVGroup",
41
+ "OpenGLVectorizedPoint",
42
+ "OpenGLCurvesAsSubmobjects",
43
+ "OpenGLDashedVMobject",
44
+ ]
45
+
37
46
 
38
47
  def triggers_refreshed_triangulation(func):
39
48
  @wraps(func)
@@ -944,7 +953,9 @@ class OpenGLVMobject(OpenGLMobject):
944
953
 
945
954
  curves_and_lengths = tuple(self.get_curve_functions_with_lengths())
946
955
 
947
- target_length = alpha * np.sum(length for _, length in curves_and_lengths)
956
+ target_length = alpha * np.sum(
957
+ np.fromiter((length for _, length in curves_and_lengths), dtype=np.float64)
958
+ )
948
959
  current_length = 0
949
960
 
950
961
  for curve, length in curves_and_lengths:
@@ -1014,7 +1025,7 @@ class OpenGLVMobject(OpenGLMobject):
1014
1025
 
1015
1026
  return alpha
1016
1027
 
1017
- def get_anchors_and_handles(self):
1028
+ def get_anchors_and_handles(self) -> Iterable[np.ndarray]:
1018
1029
  """
1019
1030
  Returns anchors1, handles, anchors2,
1020
1031
  where (anchors1[i], handles[i], anchors2[i])
@@ -1046,27 +1057,21 @@ class OpenGLVMobject(OpenGLMobject):
1046
1057
  nppc = self.n_points_per_curve
1047
1058
  return self.points[nppc - 1 :: nppc]
1048
1059
 
1049
- def get_anchors(self) -> np.ndarray:
1060
+ def get_anchors(self) -> Iterable[np.ndarray]:
1050
1061
  """Returns the anchors of the curves forming the OpenGLVMobject.
1051
1062
 
1052
1063
  Returns
1053
1064
  -------
1054
- np.ndarray
1065
+ Iterable[np.ndarray]
1055
1066
  The anchors.
1056
1067
  """
1057
1068
  points = self.points
1058
1069
  if len(points) == 1:
1059
1070
  return points
1060
- return np.array(
1061
- list(
1062
- it.chain(
1063
- *zip(
1064
- self.get_start_anchors(),
1065
- self.get_end_anchors(),
1066
- )
1067
- ),
1068
- ),
1069
- )
1071
+
1072
+ s = self.get_start_anchors()
1073
+ e = self.get_end_anchors()
1074
+ return list(it.chain.from_iterable(zip(s, e)))
1070
1075
 
1071
1076
  def get_points_without_null_curves(self, atol=1e-9):
1072
1077
  nppc = self.n_points_per_curve
@@ -24,6 +24,8 @@ from ...mobject.types.vectorized_mobject import VMobject
24
24
  from ...utils.color import BLACK
25
25
  from ..svg.svg_mobject import VMobjectFromSVGPath
26
26
 
27
+ __all__ = ["Brace", "BraceBetweenPoints", "BraceLabel", "ArcBrace"]
28
+
27
29
 
28
30
  class Brace(VMobjectFromSVGPath):
29
31
  """Takes a mobject and draws a brace adjacent to it.