manim 0.18.0.post0__py3-none-any.whl → 0.19.0__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 (146) hide show
  1. manim/__init__.py +3 -6
  2. manim/__main__.py +61 -20
  3. manim/_config/__init__.py +6 -3
  4. manim/_config/cli_colors.py +16 -8
  5. manim/_config/default.cfg +1 -3
  6. manim/_config/logger_utils.py +14 -8
  7. manim/_config/utils.py +651 -472
  8. manim/animation/animation.py +152 -5
  9. manim/animation/composition.py +80 -39
  10. manim/animation/creation.py +196 -14
  11. manim/animation/fading.py +5 -9
  12. manim/animation/indication.py +103 -47
  13. manim/animation/movement.py +22 -5
  14. manim/animation/rotation.py +3 -2
  15. manim/animation/specialized.py +4 -6
  16. manim/animation/speedmodifier.py +10 -5
  17. manim/animation/transform.py +4 -5
  18. manim/animation/transform_matching_parts.py +1 -1
  19. manim/animation/updaters/mobject_update_utils.py +17 -14
  20. manim/camera/camera.py +15 -6
  21. manim/cli/__init__.py +17 -0
  22. manim/cli/cfg/group.py +70 -44
  23. manim/cli/checkhealth/checks.py +93 -75
  24. manim/cli/checkhealth/commands.py +14 -5
  25. manim/cli/default_group.py +157 -25
  26. manim/cli/init/commands.py +32 -24
  27. manim/cli/plugins/commands.py +16 -3
  28. manim/cli/render/commands.py +72 -60
  29. manim/cli/render/ease_of_access_options.py +4 -3
  30. manim/cli/render/global_options.py +51 -15
  31. manim/cli/render/output_options.py +6 -5
  32. manim/cli/render/render_options.py +97 -32
  33. manim/constants.py +65 -19
  34. manim/gui/gui.py +2 -0
  35. manim/mobject/frame.py +0 -1
  36. manim/mobject/geometry/arc.py +112 -78
  37. manim/mobject/geometry/boolean_ops.py +32 -25
  38. manim/mobject/geometry/labeled.py +300 -77
  39. manim/mobject/geometry/line.py +132 -64
  40. manim/mobject/geometry/polygram.py +126 -30
  41. manim/mobject/geometry/shape_matchers.py +35 -15
  42. manim/mobject/geometry/tips.py +38 -29
  43. manim/mobject/graph.py +414 -133
  44. manim/mobject/graphing/coordinate_systems.py +126 -64
  45. manim/mobject/graphing/functions.py +25 -15
  46. manim/mobject/graphing/number_line.py +24 -10
  47. manim/mobject/graphing/probability.py +2 -10
  48. manim/mobject/graphing/scale.py +6 -5
  49. manim/mobject/matrix.py +17 -19
  50. manim/mobject/mobject.py +314 -165
  51. manim/mobject/opengl/opengl_compatibility.py +2 -0
  52. manim/mobject/opengl/opengl_geometry.py +30 -9
  53. manim/mobject/opengl/opengl_image_mobject.py +2 -0
  54. manim/mobject/opengl/opengl_mobject.py +509 -343
  55. manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
  56. manim/mobject/opengl/opengl_surface.py +3 -2
  57. manim/mobject/opengl/opengl_three_dimensions.py +2 -0
  58. manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
  59. manim/mobject/svg/brace.py +63 -13
  60. manim/mobject/svg/svg_mobject.py +4 -3
  61. manim/mobject/table.py +11 -13
  62. manim/mobject/text/code_mobject.py +186 -548
  63. manim/mobject/text/numbers.py +9 -7
  64. manim/mobject/text/tex_mobject.py +23 -14
  65. manim/mobject/text/text_mobject.py +70 -24
  66. manim/mobject/three_d/polyhedra.py +98 -1
  67. manim/mobject/three_d/three_d_utils.py +4 -4
  68. manim/mobject/three_d/three_dimensions.py +62 -34
  69. manim/mobject/types/image_mobject.py +42 -24
  70. manim/mobject/types/point_cloud_mobject.py +105 -67
  71. manim/mobject/types/vectorized_mobject.py +496 -228
  72. manim/mobject/value_tracker.py +5 -4
  73. manim/mobject/vector_field.py +5 -5
  74. manim/opengl/__init__.py +3 -3
  75. manim/plugins/__init__.py +14 -1
  76. manim/plugins/plugins_flags.py +14 -8
  77. manim/renderer/cairo_renderer.py +20 -10
  78. manim/renderer/opengl_renderer.py +21 -23
  79. manim/renderer/opengl_renderer_window.py +2 -0
  80. manim/renderer/shader.py +2 -3
  81. manim/renderer/shader_wrapper.py +5 -2
  82. manim/renderer/vectorized_mobject_rendering.py +5 -0
  83. manim/scene/moving_camera_scene.py +23 -0
  84. manim/scene/scene.py +90 -43
  85. manim/scene/scene_file_writer.py +316 -165
  86. manim/scene/section.py +17 -15
  87. manim/scene/three_d_scene.py +13 -21
  88. manim/scene/vector_space_scene.py +22 -9
  89. manim/typing.py +830 -70
  90. manim/utils/bezier.py +1667 -399
  91. manim/utils/caching.py +13 -5
  92. manim/utils/color/AS2700.py +2 -0
  93. manim/utils/color/BS381.py +3 -0
  94. manim/utils/color/DVIPSNAMES.py +96 -0
  95. manim/utils/color/SVGNAMES.py +179 -0
  96. manim/utils/color/X11.py +3 -0
  97. manim/utils/color/XKCD.py +3 -0
  98. manim/utils/color/__init__.py +8 -5
  99. manim/utils/color/core.py +844 -309
  100. manim/utils/color/manim_colors.py +7 -9
  101. manim/utils/commands.py +48 -20
  102. manim/utils/config_ops.py +18 -13
  103. manim/utils/debug.py +8 -7
  104. manim/utils/deprecation.py +90 -40
  105. manim/utils/docbuild/__init__.py +17 -0
  106. manim/utils/docbuild/autoaliasattr_directive.py +234 -0
  107. manim/utils/docbuild/autocolor_directive.py +21 -17
  108. manim/utils/docbuild/manim_directive.py +50 -35
  109. manim/utils/docbuild/module_parsing.py +245 -0
  110. manim/utils/exceptions.py +6 -0
  111. manim/utils/family.py +5 -3
  112. manim/utils/family_ops.py +17 -4
  113. manim/utils/file_ops.py +26 -16
  114. manim/utils/hashing.py +9 -7
  115. manim/utils/images.py +10 -4
  116. manim/utils/ipython_magic.py +14 -8
  117. manim/utils/iterables.py +161 -119
  118. manim/utils/module_ops.py +57 -19
  119. manim/utils/opengl.py +83 -24
  120. manim/utils/parameter_parsing.py +32 -0
  121. manim/utils/paths.py +21 -23
  122. manim/utils/polylabel.py +168 -0
  123. manim/utils/qhull.py +218 -0
  124. manim/utils/rate_functions.py +74 -39
  125. manim/utils/simple_functions.py +24 -15
  126. manim/utils/sounds.py +7 -1
  127. manim/utils/space_ops.py +125 -69
  128. manim/utils/testing/__init__.py +17 -0
  129. manim/utils/testing/_frames_testers.py +13 -8
  130. manim/utils/testing/_show_diff.py +5 -3
  131. manim/utils/testing/_test_class_makers.py +33 -18
  132. manim/utils/testing/frames_comparison.py +27 -19
  133. manim/utils/tex.py +127 -197
  134. manim/utils/tex_file_writing.py +47 -45
  135. manim/utils/tex_templates.py +2 -1
  136. manim/utils/unit.py +6 -5
  137. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
  138. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
  139. manim-0.19.0.dist-info/RECORD +221 -0
  140. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
  141. manim/cli/new/__init__.py +0 -0
  142. manim/cli/new/group.py +0 -189
  143. manim/plugins/import_plugins.py +0 -43
  144. manim-0.18.0.post0.dist-info/RECORD +0 -217
  145. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
  146. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
@@ -4,6 +4,8 @@ from __future__ import annotations
4
4
 
5
5
  __all__ = ["PMobject", "Mobject1D", "Mobject2D", "PGroup", "PointCloudDot", "Point"]
6
6
 
7
+ from typing import TYPE_CHECKING
8
+
7
9
  import numpy as np
8
10
 
9
11
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
@@ -17,12 +19,24 @@ from ...utils.color import (
17
19
  WHITE,
18
20
  YELLOW,
19
21
  ManimColor,
22
+ ParsableManimColor,
20
23
  color_gradient,
21
24
  color_to_rgba,
22
25
  rgba_to_color,
23
26
  )
24
27
  from ...utils.iterables import stretch_array_to_length
25
28
 
29
+ __all__ = ["PMobject", "Mobject1D", "Mobject2D", "PGroup", "PointCloudDot", "Point"]
30
+
31
+ if TYPE_CHECKING:
32
+ from collections.abc import Callable
33
+ from typing import Any
34
+
35
+ import numpy.typing as npt
36
+ from typing_extensions import Self
37
+
38
+ from manim.typing import ManimFloat, Point3DLike, Vector3D
39
+
26
40
 
27
41
  class PMobject(Mobject, metaclass=ConvertToOpenGL):
28
42
  """A disc made of a cloud of Dots
@@ -53,19 +67,25 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
53
67
 
54
68
  """
55
69
 
56
- def __init__(self, stroke_width=DEFAULT_STROKE_WIDTH, **kwargs):
70
+ def __init__(self, stroke_width: int = DEFAULT_STROKE_WIDTH, **kwargs: Any) -> None:
57
71
  self.stroke_width = stroke_width
58
72
  super().__init__(**kwargs)
59
73
 
60
- def reset_points(self):
74
+ def reset_points(self) -> Self:
61
75
  self.rgbas = np.zeros((0, 4))
62
76
  self.points = np.zeros((0, 3))
63
77
  return self
64
78
 
65
- def get_array_attrs(self):
79
+ def get_array_attrs(self) -> list[str]:
66
80
  return super().get_array_attrs() + ["rgbas"]
67
81
 
68
- def add_points(self, points, rgbas=None, color=None, alpha=1):
82
+ def add_points(
83
+ self,
84
+ points: npt.NDArray,
85
+ rgbas: npt.NDArray | None = None,
86
+ color: ParsableManimColor | None = None,
87
+ alpha: float = 1,
88
+ ) -> Self:
69
89
  """Add points.
70
90
 
71
91
  Points must be a Nx3 numpy array.
@@ -83,24 +103,26 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
83
103
  self.rgbas = np.append(self.rgbas, rgbas, axis=0)
84
104
  return self
85
105
 
86
- def set_color(self, color=YELLOW, family=True):
106
+ def set_color(
107
+ self, color: ParsableManimColor = YELLOW, family: bool = True
108
+ ) -> Self:
87
109
  rgba = color_to_rgba(color)
88
110
  mobs = self.family_members_with_points() if family else [self]
89
111
  for mob in mobs:
90
112
  mob.rgbas[:, :] = rgba
91
- self.color = color
113
+ self.color = ManimColor.parse(color)
92
114
  return self
93
115
 
94
- def get_stroke_width(self):
116
+ def get_stroke_width(self) -> int:
95
117
  return self.stroke_width
96
118
 
97
- def set_stroke_width(self, width, family=True):
119
+ def set_stroke_width(self, width: int, family: bool = True) -> Self:
98
120
  mobs = self.family_members_with_points() if family else [self]
99
121
  for mob in mobs:
100
122
  mob.stroke_width = width
101
123
  return self
102
124
 
103
- def set_color_by_gradient(self, *colors):
125
+ def set_color_by_gradient(self, *colors: ParsableManimColor) -> Self:
104
126
  self.rgbas = np.array(
105
127
  list(map(color_to_rgba, color_gradient(*colors, len(self.points)))),
106
128
  )
@@ -108,11 +130,11 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
108
130
 
109
131
  def set_colors_by_radial_gradient(
110
132
  self,
111
- center=None,
112
- radius=1,
113
- inner_color=WHITE,
114
- outer_color=BLACK,
115
- ):
133
+ center: Point3DLike | None = None,
134
+ radius: float = 1,
135
+ inner_color: ParsableManimColor = WHITE,
136
+ outer_color: ParsableManimColor = BLACK,
137
+ ) -> Self:
116
138
  start_rgba, end_rgba = list(map(color_to_rgba, [inner_color, outer_color]))
117
139
  if center is None:
118
140
  center = self.get_center()
@@ -127,48 +149,48 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
127
149
  )
128
150
  return self
129
151
 
130
- def match_colors(self, mobject):
152
+ def match_colors(self, mobject: Mobject) -> Self:
131
153
  Mobject.align_data(self, mobject)
132
154
  self.rgbas = np.array(mobject.rgbas)
133
155
  return self
134
156
 
135
- def filter_out(self, condition):
157
+ def filter_out(self, condition: npt.NDArray) -> Self:
136
158
  for mob in self.family_members_with_points():
137
159
  to_eliminate = ~np.apply_along_axis(condition, 1, mob.points)
138
160
  mob.points = mob.points[to_eliminate]
139
161
  mob.rgbas = mob.rgbas[to_eliminate]
140
162
  return self
141
163
 
142
- def thin_out(self, factor=5):
143
- """
144
- Removes all but every nth point for n = factor
145
- """
164
+ def thin_out(self, factor: int = 5) -> Self:
165
+ """Removes all but every nth point for n = factor"""
146
166
  for mob in self.family_members_with_points():
147
167
  num_points = self.get_num_points()
148
168
  mob.apply_over_attr_arrays(
149
- lambda arr: arr[np.arange(0, num_points, factor)],
169
+ lambda arr, n=num_points: arr[np.arange(0, n, factor)],
150
170
  )
151
171
  return self
152
172
 
153
- def sort_points(self, function=lambda p: p[0]):
154
- """
155
- Function is any map from R^3 to R
156
- """
173
+ def sort_points(
174
+ self, function: Callable[[npt.NDArray[ManimFloat]], float] = lambda p: p[0]
175
+ ) -> Self:
176
+ """Function is any map from R^3 to R"""
157
177
  for mob in self.family_members_with_points():
158
178
  indices = np.argsort(np.apply_along_axis(function, 1, mob.points))
159
- mob.apply_over_attr_arrays(lambda arr: arr[indices])
179
+ mob.apply_over_attr_arrays(lambda arr, idx=indices: arr[idx])
160
180
  return self
161
181
 
162
- def fade_to(self, color, alpha, family=True):
182
+ def fade_to(
183
+ self, color: ParsableManimColor, alpha: float, family: bool = True
184
+ ) -> Self:
163
185
  self.rgbas = interpolate(self.rgbas, color_to_rgba(color), alpha)
164
186
  for mob in self.submobjects:
165
187
  mob.fade_to(color, alpha, family)
166
188
  return self
167
189
 
168
- def get_all_rgbas(self):
190
+ def get_all_rgbas(self) -> npt.NDArray:
169
191
  return self.get_merged_array("rgbas")
170
192
 
171
- def ingest_submobjects(self):
193
+ def ingest_submobjects(self) -> Self:
172
194
  attrs = self.get_array_attrs()
173
195
  arrays = list(map(self.get_merged_array, attrs))
174
196
  for attr, array in zip(attrs, arrays):
@@ -176,30 +198,32 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
176
198
  self.submobjects = []
177
199
  return self
178
200
 
179
- def get_color(self):
201
+ def get_color(self) -> ManimColor:
180
202
  return rgba_to_color(self.rgbas[0, :])
181
203
 
182
- def point_from_proportion(self, alpha):
204
+ def point_from_proportion(self, alpha: float) -> Any:
183
205
  index = alpha * (self.get_num_points() - 1)
184
- return self.points[index]
206
+ return self.points[np.floor(index)]
185
207
 
186
208
  @staticmethod
187
- def get_mobject_type_class():
209
+ def get_mobject_type_class() -> type[PMobject]:
188
210
  return PMobject
189
211
 
190
212
  # Alignment
191
- def align_points_with_larger(self, larger_mobject):
213
+ def align_points_with_larger(self, larger_mobject: Mobject) -> None:
192
214
  assert isinstance(larger_mobject, PMobject)
193
215
  self.apply_over_attr_arrays(
194
216
  lambda a: stretch_array_to_length(a, larger_mobject.get_num_points()),
195
217
  )
196
218
 
197
- def get_point_mobject(self, center=None):
219
+ def get_point_mobject(self, center: Point3DLike | None = None) -> Point:
198
220
  if center is None:
199
221
  center = self.get_center()
200
222
  return Point(center)
201
223
 
202
- def interpolate_color(self, mobject1, mobject2, alpha):
224
+ def interpolate_color(
225
+ self, mobject1: Mobject, mobject2: Mobject, alpha: float
226
+ ) -> Self:
203
227
  self.rgbas = interpolate(mobject1.rgbas, mobject2.rgbas, alpha)
204
228
  self.set_stroke_width(
205
229
  interpolate(
@@ -210,7 +234,7 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
210
234
  )
211
235
  return self
212
236
 
213
- def pointwise_become_partial(self, mobject, a, b):
237
+ def pointwise_become_partial(self, mobject: Mobject, a: float, b: float) -> None:
214
238
  lower_index, upper_index = (int(x * mobject.get_num_points()) for x in (a, b))
215
239
  for attr in self.get_array_attrs():
216
240
  full_array = getattr(mobject, attr)
@@ -220,24 +244,31 @@ class PMobject(Mobject, metaclass=ConvertToOpenGL):
220
244
 
221
245
  # TODO, Make the two implementations below non-redundant
222
246
  class Mobject1D(PMobject, metaclass=ConvertToOpenGL):
223
- def __init__(self, density=DEFAULT_POINT_DENSITY_1D, **kwargs):
247
+ def __init__(self, density: int = DEFAULT_POINT_DENSITY_1D, **kwargs: Any) -> None:
224
248
  self.density = density
225
249
  self.epsilon = 1.0 / self.density
226
250
  super().__init__(**kwargs)
227
251
 
228
- def add_line(self, start, end, color=None):
252
+ def add_line(
253
+ self,
254
+ start: npt.NDArray,
255
+ end: npt.NDArray,
256
+ color: ParsableManimColor | None = None,
257
+ ) -> None:
229
258
  start, end = list(map(np.array, [start, end]))
230
259
  length = np.linalg.norm(end - start)
231
260
  if length == 0:
232
- points = [start]
261
+ points = np.array([start])
233
262
  else:
234
263
  epsilon = self.epsilon / length
235
- points = [interpolate(start, end, t) for t in np.arange(0, 1, epsilon)]
264
+ points = np.array(
265
+ [interpolate(start, end, t) for t in np.arange(0, 1, epsilon)]
266
+ )
236
267
  self.add_points(points, color=color)
237
268
 
238
269
 
239
270
  class Mobject2D(PMobject, metaclass=ConvertToOpenGL):
240
- def __init__(self, density=DEFAULT_POINT_DENSITY_2D, **kwargs):
271
+ def __init__(self, density: int = DEFAULT_POINT_DENSITY_2D, **kwargs: Any) -> None:
241
272
  self.density = density
242
273
  self.epsilon = 1.0 / self.density
243
274
  super().__init__(**kwargs)
@@ -266,7 +297,7 @@ class PGroup(PMobject):
266
297
 
267
298
  """
268
299
 
269
- def __init__(self, *pmobs, **kwargs):
300
+ def __init__(self, *pmobs: Any, **kwargs: Any) -> None:
270
301
  if not all(isinstance(m, (PMobject, OpenGLPMobject)) for m in pmobs):
271
302
  raise ValueError(
272
303
  "All submobjects must be of type PMobject or OpenGLPMObject"
@@ -275,10 +306,13 @@ class PGroup(PMobject):
275
306
  super().__init__(**kwargs)
276
307
  self.add(*pmobs)
277
308
 
278
- def fade_to(self, color, alpha, family=True):
309
+ def fade_to(
310
+ self, color: ParsableManimColor, alpha: float, family: bool = True
311
+ ) -> Self:
279
312
  if family:
280
313
  for mob in self.submobjects:
281
314
  mob.fade_to(color, alpha, family)
315
+ return self
282
316
 
283
317
 
284
318
  class PointCloudDot(Mobject1D):
@@ -315,13 +349,13 @@ class PointCloudDot(Mobject1D):
315
349
 
316
350
  def __init__(
317
351
  self,
318
- center=ORIGIN,
319
- radius=2.0,
320
- stroke_width=2,
321
- density=DEFAULT_POINT_DENSITY_1D,
322
- color=YELLOW,
323
- **kwargs,
324
- ):
352
+ center: Vector3D = ORIGIN,
353
+ radius: float = 2.0,
354
+ stroke_width: int = 2,
355
+ density: int = DEFAULT_POINT_DENSITY_1D,
356
+ color: ManimColor = YELLOW,
357
+ **kwargs: Any,
358
+ ) -> None:
325
359
  self.radius = radius
326
360
  self.epsilon = 1.0 / density
327
361
  super().__init__(
@@ -329,22 +363,24 @@ class PointCloudDot(Mobject1D):
329
363
  )
330
364
  self.shift(center)
331
365
 
332
- def init_points(self):
366
+ def init_points(self) -> None:
333
367
  self.reset_points()
334
368
  self.generate_points()
335
369
 
336
- def generate_points(self):
370
+ def generate_points(self) -> None:
337
371
  self.add_points(
338
- [
339
- r * (np.cos(theta) * RIGHT + np.sin(theta) * UP)
340
- for r in np.arange(self.epsilon, self.radius, self.epsilon)
341
- # Num is equal to int(stop - start)/ (step + 1) reformulated.
342
- for theta in np.linspace(
343
- 0,
344
- 2 * np.pi,
345
- num=int(2 * np.pi * (r + self.epsilon) / self.epsilon),
346
- )
347
- ],
372
+ np.array(
373
+ [
374
+ r * (np.cos(theta) * RIGHT + np.sin(theta) * UP)
375
+ for r in np.arange(self.epsilon, self.radius, self.epsilon)
376
+ # Num is equal to int(stop - start)/ (step + 1) reformulated.
377
+ for theta in np.linspace(
378
+ 0,
379
+ 2 * np.pi,
380
+ num=int(2 * np.pi * (r + self.epsilon) / self.epsilon),
381
+ )
382
+ ]
383
+ ),
348
384
  )
349
385
 
350
386
 
@@ -369,14 +405,16 @@ class Point(PMobject):
369
405
  self.add(point)
370
406
  """
371
407
 
372
- def __init__(self, location=ORIGIN, color=BLACK, **kwargs):
408
+ def __init__(
409
+ self, location: Vector3D = ORIGIN, color: ManimColor = BLACK, **kwargs: Any
410
+ ) -> None:
373
411
  self.location = location
374
412
  super().__init__(color=color, **kwargs)
375
413
 
376
- def init_points(self):
414
+ def init_points(self) -> None:
377
415
  self.reset_points()
378
416
  self.generate_points()
379
417
  self.set_points([self.location])
380
418
 
381
- def generate_points(self):
382
- self.add_points([self.location])
419
+ def generate_points(self) -> None:
420
+ self.add_points(np.array([self.location]))