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