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
@@ -44,7 +44,7 @@ __all__ = [
44
44
 
45
45
  import itertools
46
46
  import warnings
47
- from typing import TYPE_CHECKING
47
+ from typing import TYPE_CHECKING, cast
48
48
 
49
49
  import numpy as np
50
50
  from typing_extensions import Self
@@ -63,11 +63,19 @@ from manim.utils.space_ops import (
63
63
  )
64
64
 
65
65
  if TYPE_CHECKING:
66
+ from collections.abc import Iterable
67
+ from typing import Any
68
+
66
69
  import manim.mobject.geometry.tips as tips
67
70
  from manim.mobject.mobject import Mobject
68
71
  from manim.mobject.text.tex_mobject import SingleStringMathTex, Tex
69
72
  from manim.mobject.text.text_mobject import Text
70
- from manim.typing import CubicBezierPoints, Point3D, QuadraticBezierPoints, Vector
73
+ from manim.typing import (
74
+ Point3D,
75
+ Point3DLike,
76
+ QuadraticSpline,
77
+ Vector3D,
78
+ )
71
79
 
72
80
 
73
81
  class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
@@ -91,12 +99,12 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
91
99
  def __init__(
92
100
  self,
93
101
  tip_length: float = DEFAULT_ARROW_TIP_LENGTH,
94
- normal_vector: Vector = OUT,
102
+ normal_vector: Vector3D = OUT,
95
103
  tip_style: dict = {},
96
- **kwargs,
104
+ **kwargs: Any,
97
105
  ) -> None:
98
106
  self.tip_length: float = tip_length
99
- self.normal_vector: Vector = normal_vector
107
+ self.normal_vector: Vector3D = normal_vector
100
108
  self.tip_style: dict = tip_style
101
109
  super().__init__(**kwargs)
102
110
 
@@ -126,10 +134,10 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
126
134
  def create_tip(
127
135
  self,
128
136
  tip_shape: type[tips.ArrowTip] | None = None,
129
- tip_length: float = None,
130
- tip_width: float = None,
137
+ tip_length: float | None = None,
138
+ tip_width: float | None = None,
131
139
  at_start: bool = False,
132
- ):
140
+ ) -> tips.ArrowTip:
133
141
  """Stylises the tip, positions it spatially, and returns
134
142
  the newly instantiated tip to the caller.
135
143
  """
@@ -142,13 +150,13 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
142
150
  tip_shape: type[tips.ArrowTip] | None = None,
143
151
  tip_length: float | None = None,
144
152
  tip_width: float | None = None,
145
- ):
153
+ ) -> tips.ArrowTip | tips.ArrowTriangleFilledTip:
146
154
  """Returns a tip that has been stylistically configured,
147
155
  but has not yet been given a position in space.
148
156
  """
149
157
  from manim.mobject.geometry.tips import ArrowTriangleFilledTip
150
158
 
151
- style = {}
159
+ style: dict[str, Any] = {}
152
160
 
153
161
  if tip_shape is None:
154
162
  tip_shape = ArrowTriangleFilledTip
@@ -166,7 +174,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
166
174
  tip = tip_shape(length=tip_length, **style)
167
175
  return tip
168
176
 
169
- def position_tip(self, tip: tips.ArrowTip, at_start: bool = False):
177
+ def position_tip(self, tip: tips.ArrowTip, at_start: bool = False) -> tips.ArrowTip:
170
178
  # Last two control points, defining both
171
179
  # the end, and the tangency direction
172
180
  if at_start:
@@ -175,16 +183,18 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
175
183
  else:
176
184
  handle = self.get_last_handle()
177
185
  anchor = self.get_end()
178
- angles = cartesian_to_spherical(handle - anchor)
186
+ angles = cartesian_to_spherical((handle - anchor).tolist())
179
187
  tip.rotate(
180
188
  angles[1] - PI - tip.tip_angle,
181
189
  ) # Rotates the tip along the azimuthal
182
190
  if not hasattr(self, "_init_positioning_axis"):
183
- axis = [
184
- np.sin(angles[1]),
185
- -np.cos(angles[1]),
186
- 0,
187
- ] # Obtains the perpendicular of the tip
191
+ axis = np.array(
192
+ [
193
+ np.sin(angles[1]),
194
+ -np.cos(angles[1]),
195
+ 0,
196
+ ]
197
+ ) # Obtains the perpendicular of the tip
188
198
  tip.rotate(
189
199
  -angles[2] + PI / 2,
190
200
  axis=axis,
@@ -244,23 +254,33 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
244
254
  result.add(self.start_tip)
245
255
  return result
246
256
 
247
- def get_tip(self):
257
+ def get_tip(self) -> VMobject:
248
258
  """Returns the TipableVMobject instance's (first) tip,
249
- otherwise throws an exception."""
259
+ otherwise throws an exception.
260
+ """
250
261
  tips = self.get_tips()
251
262
  if len(tips) == 0:
252
263
  raise Exception("tip not found")
253
264
  else:
254
- return tips[0]
265
+ tip: VMobject = tips[0]
266
+ return tip
255
267
 
256
268
  def get_default_tip_length(self) -> float:
257
269
  return self.tip_length
258
270
 
259
271
  def get_first_handle(self) -> Point3D:
260
- return self.points[1]
272
+ # Type inference of extracting an element from a list, is not
273
+ # supported by numpy, see this numpy issue
274
+ # https://github.com/numpy/numpy/issues/16544
275
+ first_handle: Point3D = self.points[1]
276
+ return first_handle
261
277
 
262
278
  def get_last_handle(self) -> Point3D:
263
- return self.points[-2]
279
+ # Type inference of extracting an element from a list, is not
280
+ # supported by numpy, see this numpy issue
281
+ # https://github.com/numpy/numpy/issues/16544
282
+ last_handle: Point3D = self.points[-2]
283
+ return last_handle
264
284
 
265
285
  def get_end(self) -> Point3D:
266
286
  if self.has_tip():
@@ -274,9 +294,9 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
274
294
  else:
275
295
  return super().get_start()
276
296
 
277
- def get_length(self) -> np.floating:
297
+ def get_length(self) -> float:
278
298
  start, end = self.get_start_and_end()
279
- return np.linalg.norm(start - end)
299
+ return float(np.linalg.norm(start - end))
280
300
 
281
301
 
282
302
  class Arc(TipableVMobject):
@@ -296,20 +316,20 @@ class Arc(TipableVMobject):
296
316
 
297
317
  def __init__(
298
318
  self,
299
- radius: float = 1.0,
319
+ radius: float | None = 1.0,
300
320
  start_angle: float = 0,
301
321
  angle: float = TAU / 4,
302
322
  num_components: int = 9,
303
- arc_center: Point3D = ORIGIN,
304
- **kwargs,
323
+ arc_center: Point3DLike = ORIGIN,
324
+ **kwargs: Any,
305
325
  ):
306
326
  if radius is None: # apparently None is passed by ArcBetweenPoints
307
327
  radius = 1.0
308
328
  self.radius = radius
309
- self.num_components: int = num_components
310
- self.arc_center: Point3D = arc_center
311
- self.start_angle: float = start_angle
312
- self.angle: float = angle
329
+ self.num_components = num_components
330
+ self.arc_center: Point3D = np.asarray(arc_center)
331
+ self.start_angle = start_angle
332
+ self.angle = angle
313
333
  self._failed_to_get_center: bool = False
314
334
  super().__init__(**kwargs)
315
335
 
@@ -335,7 +355,7 @@ class Arc(TipableVMobject):
335
355
  @staticmethod
336
356
  def _create_quadratic_bezier_points(
337
357
  angle: float, start_angle: float = 0, n_components: int = 8
338
- ) -> QuadraticBezierPoints:
358
+ ) -> QuadraticSpline:
339
359
  samples = np.array(
340
360
  [
341
361
  [np.cos(a), np.sin(a), 0]
@@ -374,8 +394,9 @@ class Arc(TipableVMobject):
374
394
  tangent_vectors[:, 1] = anchors[:, 0]
375
395
  tangent_vectors[:, 0] = -anchors[:, 1]
376
396
  # Use tangent vectors to deduce anchors
377
- handles1 = anchors[:-1] + (d_theta / 3) * tangent_vectors[:-1]
378
- handles2 = anchors[1:] - (d_theta / 3) * tangent_vectors[1:]
397
+ factor = 4 / 3 * np.tan(d_theta / 4)
398
+ handles1 = anchors[:-1] + factor * tangent_vectors[:-1]
399
+ handles2 = anchors[1:] - factor * tangent_vectors[1:]
379
400
  self.set_anchors_and_handles(anchors[:-1], handles1, handles2, anchors[1:])
380
401
 
381
402
  def get_arc_center(self, warning: bool = True) -> Point3D:
@@ -389,7 +410,7 @@ class Arc(TipableVMobject):
389
410
  # For a1 and a2 to lie at the same point arc radius
390
411
  # must be zero. Thus arc_center will also lie at
391
412
  # that point.
392
- return a1
413
+ return np.copy(a1)
393
414
  # Tangent vectors
394
415
  t1 = h1 - a1
395
416
  t2 = h2 - a2
@@ -400,16 +421,21 @@ class Arc(TipableVMobject):
400
421
  return line_intersection(line1=(a1, a1 + n1), line2=(a2, a2 + n2))
401
422
  except Exception:
402
423
  if warning:
403
- warnings.warn("Can't find Arc center, using ORIGIN instead")
424
+ warnings.warn(
425
+ "Can't find Arc center, using ORIGIN instead", stacklevel=1
426
+ )
404
427
  self._failed_to_get_center = True
405
428
  return np.array(ORIGIN)
406
429
 
407
- def move_arc_center_to(self, point: Point3D) -> Self:
430
+ def move_arc_center_to(self, point: Point3DLike) -> Self:
408
431
  self.shift(point - self.get_arc_center())
409
432
  return self
410
433
 
411
434
  def stop_angle(self) -> float:
412
- return angle_of_vector(self.points[-1] - self.get_arc_center()) % TAU
435
+ return cast(
436
+ float,
437
+ angle_of_vector(self.points[-1] - self.get_arc_center()) % TAU,
438
+ )
413
439
 
414
440
 
415
441
  class ArcBetweenPoints(Arc):
@@ -433,11 +459,11 @@ class ArcBetweenPoints(Arc):
433
459
 
434
460
  def __init__(
435
461
  self,
436
- start: Point3D,
437
- end: Point3D,
462
+ start: Point3DLike,
463
+ end: Point3DLike,
438
464
  angle: float = TAU / 4,
439
- radius: float = None,
440
- **kwargs,
465
+ radius: float | None = None,
466
+ **kwargs: Any,
441
467
  ) -> None:
442
468
  if radius is not None:
443
469
  self.radius = radius
@@ -457,19 +483,24 @@ class ArcBetweenPoints(Arc):
457
483
 
458
484
  super().__init__(radius=radius, angle=angle, **kwargs)
459
485
  if angle == 0:
460
- self.set_points_as_corners([LEFT, RIGHT])
486
+ self.set_points_as_corners(np.array([LEFT, RIGHT]))
461
487
  self.put_start_and_end_on(start, end)
462
488
 
463
489
  if radius is None:
464
490
  center = self.get_arc_center(warning=False)
465
491
  if not self._failed_to_get_center:
466
- self.radius = np.linalg.norm(np.array(start) - np.array(center))
492
+ # np.linalg.norm returns floating[Any] which is not compatible with float
493
+ self.radius = cast(
494
+ float, np.linalg.norm(np.array(start) - np.array(center))
495
+ )
467
496
  else:
468
497
  self.radius = np.inf
469
498
 
470
499
 
471
500
  class CurvedArrow(ArcBetweenPoints):
472
- def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
501
+ def __init__(
502
+ self, start_point: Point3DLike, end_point: Point3DLike, **kwargs: Any
503
+ ) -> None:
473
504
  from manim.mobject.geometry.tips import ArrowTriangleFilledTip
474
505
 
475
506
  tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
@@ -478,7 +509,9 @@ class CurvedArrow(ArcBetweenPoints):
478
509
 
479
510
 
480
511
  class CurvedDoubleArrow(CurvedArrow):
481
- def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
512
+ def __init__(
513
+ self, start_point: Point3DLike, end_point: Point3DLike, **kwargs: Any
514
+ ) -> None:
482
515
  if "tip_shape_end" in kwargs:
483
516
  kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
484
517
  from manim.mobject.geometry.tips import ArrowTriangleFilledTip
@@ -517,7 +550,7 @@ class Circle(Arc):
517
550
  self,
518
551
  radius: float | None = None,
519
552
  color: ParsableManimColor = RED,
520
- **kwargs,
553
+ **kwargs: Any,
521
554
  ) -> None:
522
555
  super().__init__(
523
556
  radius=radius,
@@ -569,7 +602,6 @@ class Circle(Arc):
569
602
  group = Group(group1, group2, group3).arrange(buff=1)
570
603
  self.add(group)
571
604
  """
572
-
573
605
  # Ignores dim_to_match and stretch; result will always be a circle
574
606
  # TODO: Perhaps create an ellipse class to handle single-dimension stretching
575
607
 
@@ -609,14 +641,15 @@ class Circle(Arc):
609
641
  self.add(circle, s1, s2)
610
642
 
611
643
  """
612
-
613
644
  start_angle = angle_of_vector(self.points[0] - self.get_center())
614
645
  proportion = (angle - start_angle) / TAU
615
646
  proportion -= np.floor(proportion)
616
647
  return self.point_from_proportion(proportion)
617
648
 
618
649
  @staticmethod
619
- def from_three_points(p1: Point3D, p2: Point3D, p3: Point3D, **kwargs) -> Self:
650
+ def from_three_points(
651
+ p1: Point3DLike, p2: Point3DLike, p3: Point3DLike, **kwargs: Any
652
+ ) -> Circle:
620
653
  """Returns a circle passing through the specified
621
654
  three points.
622
655
 
@@ -636,10 +669,11 @@ class Circle(Arc):
636
669
  self.add(NumberPlane(), circle, dots)
637
670
  """
638
671
  center = line_intersection(
639
- perpendicular_bisector([p1, p2]),
640
- perpendicular_bisector([p2, p3]),
672
+ perpendicular_bisector([np.asarray(p1), np.asarray(p2)]),
673
+ perpendicular_bisector([np.asarray(p2), np.asarray(p3)]),
641
674
  )
642
- radius = np.linalg.norm(p1 - center)
675
+ # np.linalg.norm returns floating[Any] which is not compatible with float
676
+ radius = cast(float, np.linalg.norm(p1 - center))
643
677
  return Circle(radius=radius, **kwargs).shift(center)
644
678
 
645
679
 
@@ -676,12 +710,12 @@ class Dot(Circle):
676
710
 
677
711
  def __init__(
678
712
  self,
679
- point: Point3D = ORIGIN,
713
+ point: Point3DLike = ORIGIN,
680
714
  radius: float = DEFAULT_DOT_RADIUS,
681
715
  stroke_width: float = 0,
682
716
  fill_opacity: float = 1.0,
683
717
  color: ParsableManimColor = WHITE,
684
- **kwargs,
718
+ **kwargs: Any,
685
719
  ) -> None:
686
720
  super().__init__(
687
721
  arc_center=point,
@@ -702,7 +736,7 @@ class AnnotationDot(Dot):
702
736
  stroke_width: float = 5,
703
737
  stroke_color: ParsableManimColor = WHITE,
704
738
  fill_color: ParsableManimColor = BLUE,
705
- **kwargs,
739
+ **kwargs: Any,
706
740
  ) -> None:
707
741
  super().__init__(
708
742
  radius=radius,
@@ -751,12 +785,12 @@ class LabeledDot(Dot):
751
785
  self,
752
786
  label: str | SingleStringMathTex | Text | Tex,
753
787
  radius: float | None = None,
754
- **kwargs,
788
+ **kwargs: Any,
755
789
  ) -> None:
756
790
  if isinstance(label, str):
757
791
  from manim import MathTex
758
792
 
759
- rendered_label = MathTex(label, color=BLACK)
793
+ rendered_label: VMobject = MathTex(label, color=BLACK)
760
794
  else:
761
795
  rendered_label = label
762
796
 
@@ -792,7 +826,7 @@ class Ellipse(Circle):
792
826
  self.add(ellipse_group)
793
827
  """
794
828
 
795
- def __init__(self, width: float = 2, height: float = 1, **kwargs) -> None:
829
+ def __init__(self, width: float = 2, height: float = 1, **kwargs: Any) -> None:
796
830
  super().__init__(**kwargs)
797
831
  self.stretch_to_fit_width(width)
798
832
  self.stretch_to_fit_height(height)
@@ -853,7 +887,7 @@ class AnnularSector(Arc):
853
887
  fill_opacity: float = 1,
854
888
  stroke_width: float = 0,
855
889
  color: ParsableManimColor = WHITE,
856
- **kwargs,
890
+ **kwargs: Any,
857
891
  ) -> None:
858
892
  self.inner_radius = inner_radius
859
893
  self.outer_radius = outer_radius
@@ -895,17 +929,15 @@ class Sector(AnnularSector):
895
929
 
896
930
  class ExampleSector(Scene):
897
931
  def construct(self):
898
- sector = Sector(outer_radius=2, inner_radius=1)
899
- sector2 = Sector(outer_radius=2.5, inner_radius=0.8).move_to([-3, 0, 0])
932
+ sector = Sector(radius=2)
933
+ sector2 = Sector(radius=2.5, angle=60*DEGREES).move_to([-3, 0, 0])
900
934
  sector.set_color(RED)
901
935
  sector2.set_color(PINK)
902
936
  self.add(sector, sector2)
903
937
  """
904
938
 
905
- def __init__(
906
- self, outer_radius: float = 1, inner_radius: float = 0, **kwargs
907
- ) -> None:
908
- super().__init__(inner_radius=inner_radius, outer_radius=outer_radius, **kwargs)
939
+ def __init__(self, radius: float = 1, **kwargs: Any) -> None:
940
+ super().__init__(inner_radius=0, outer_radius=radius, **kwargs)
909
941
 
910
942
 
911
943
  class Annulus(Circle):
@@ -934,13 +966,13 @@ class Annulus(Circle):
934
966
 
935
967
  def __init__(
936
968
  self,
937
- inner_radius: float | None = 1,
938
- outer_radius: float | None = 2,
969
+ inner_radius: float = 1,
970
+ outer_radius: float = 2,
939
971
  fill_opacity: float = 1,
940
972
  stroke_width: float = 0,
941
973
  color: ParsableManimColor = WHITE,
942
974
  mark_paths_closed: bool = False,
943
- **kwargs,
975
+ **kwargs: Any,
944
976
  ) -> None:
945
977
  self.mark_paths_closed = mark_paths_closed # is this even used?
946
978
  self.inner_radius = inner_radius
@@ -986,11 +1018,11 @@ class CubicBezier(VMobject, metaclass=ConvertToOpenGL):
986
1018
 
987
1019
  def __init__(
988
1020
  self,
989
- start_anchor: CubicBezierPoints,
990
- start_handle: CubicBezierPoints,
991
- end_handle: CubicBezierPoints,
992
- end_anchor: CubicBezierPoints,
993
- **kwargs,
1021
+ start_anchor: Point3DLike,
1022
+ start_handle: Point3DLike,
1023
+ end_handle: Point3DLike,
1024
+ end_anchor: Point3DLike,
1025
+ **kwargs: Any,
994
1026
  ) -> None:
995
1027
  super().__init__(**kwargs)
996
1028
  self.add_cubic_bezier_curve(start_anchor, start_handle, end_handle, end_anchor)
@@ -1077,18 +1109,20 @@ class ArcPolygon(VMobject, metaclass=ConvertToOpenGL):
1077
1109
 
1078
1110
  def __init__(
1079
1111
  self,
1080
- *vertices: Point3D,
1112
+ *vertices: Point3DLike,
1081
1113
  angle: float = PI / 4,
1082
1114
  radius: float | None = None,
1083
1115
  arc_config: list[dict] | None = None,
1084
- **kwargs,
1116
+ **kwargs: Any,
1085
1117
  ) -> None:
1086
1118
  n = len(vertices)
1087
1119
  point_pairs = [(vertices[k], vertices[(k + 1) % n]) for k in range(n)]
1088
1120
 
1089
1121
  if not arc_config:
1090
1122
  if radius:
1091
- all_arc_configs = itertools.repeat({"radius": radius}, len(point_pairs))
1123
+ all_arc_configs: Iterable[dict] = itertools.repeat(
1124
+ {"radius": radius}, len(point_pairs)
1125
+ )
1092
1126
  else:
1093
1127
  all_arc_configs = itertools.repeat({"angle": angle}, len(point_pairs))
1094
1128
  elif isinstance(arc_config, dict):
@@ -1220,7 +1254,7 @@ class ArcPolygonFromArcs(VMobject, metaclass=ConvertToOpenGL):
1220
1254
  self.wait(2)
1221
1255
  """
1222
1256
 
1223
- def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs) -> None:
1257
+ def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs: Any) -> None:
1224
1258
  if not all(isinstance(m, (Arc, ArcBetweenPoints)) for m in arcs):
1225
1259
  raise ValueError(
1226
1260
  "All ArcPolygon submobjects must be of type Arc/ArcBetweenPoints",
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from typing import TYPE_CHECKING
6
+
5
7
  import numpy as np
6
8
  from pathops import Path as SkiaPath
7
9
  from pathops import PathVerb, difference, intersection, union, xor
@@ -9,7 +11,11 @@ from pathops import PathVerb, difference, intersection, union, xor
9
11
  from manim import config
10
12
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
11
13
  from manim.mobject.types.vectorized_mobject import VMobject
12
- from manim.typing import Point2D_Array
14
+
15
+ if TYPE_CHECKING:
16
+ from typing import Any
17
+
18
+ from manim.typing import Point2DLike_Array, Point3D_Array, Point3DLike_Array
13
19
 
14
20
  from ...constants import RendererType
15
21
 
@@ -24,36 +30,37 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
24
30
 
25
31
  def _convert_2d_to_3d_array(
26
32
  self,
27
- points: Point2D_Array,
33
+ points: Point2DLike_Array | Point3DLike_Array,
28
34
  z_dim: float = 0.0,
29
- ) -> list[np.ndarray]:
30
- """Converts an iterable with coordinates in 2d to 3d by adding
31
- :attr:`z_dim` as the z coordinate.
35
+ ) -> Point3D_Array:
36
+ """Converts an iterable with coordinates in 2D to 3D by adding
37
+ :attr:`z_dim` as the Z coordinate.
32
38
 
33
39
  Parameters
34
40
  ----------
35
- points:
36
- An iterable which has the coordinates.
37
- z_dim:
38
- The default value of z coordinate.
41
+ points
42
+ An iterable of points.
43
+ z_dim
44
+ Default value for the Z coordinate.
39
45
 
40
46
  Returns
41
47
  -------
42
- Point2D_Array
43
- A list of array converted to 3d.
48
+ Point3D_Array
49
+ A list of the points converted to 3D.
44
50
 
45
51
  Example
46
52
  -------
47
53
  >>> a = _BooleanOps()
48
54
  >>> p = [(1, 2), (3, 4)]
49
55
  >>> a._convert_2d_to_3d_array(p)
50
- [array([1., 2., 0.]), array([3., 4., 0.])]
56
+ array([[1., 2., 0.],
57
+ [3., 4., 0.]])
51
58
  """
52
- points = list(points)
53
- for i, point in enumerate(points):
59
+ list_of_points = list(points)
60
+ for i, point in enumerate(list_of_points):
54
61
  if len(point) == 2:
55
- points[i] = np.array(list(point) + [z_dim])
56
- return points
62
+ list_of_points[i] = np.array(list(point) + [z_dim])
63
+ return np.asarray(list_of_points)
57
64
 
58
65
  def _convert_vmobject_to_skia_path(self, vmobject: VMobject) -> SkiaPath:
59
66
  """Converts a :class:`~.VMobject` to SkiaPath. This method only works for
@@ -66,7 +73,7 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
66
73
 
67
74
  Returns
68
75
  -------
69
- SkiaPath:
76
+ SkiaPath
70
77
  The converted path.
71
78
  """
72
79
  path = SkiaPath()
@@ -86,17 +93,17 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
86
93
  quads = vmobject.get_bezier_tuples_from_points(subpath)
87
94
  start = subpath[0]
88
95
  path.moveTo(*start[:2])
89
- for p0, p1, p2 in quads:
96
+ for _p0, p1, p2 in quads:
90
97
  path.quadTo(*p1[:2], *p2[:2])
91
98
  if vmobject.consider_points_equals(subpath[0], subpath[-1]):
92
99
  path.close()
93
100
  elif config.renderer == RendererType.CAIRO:
94
- subpaths = vmobject.gen_subpaths_from_points_2d(points)
101
+ subpaths = vmobject.gen_subpaths_from_points_2d(points) # type: ignore[assignment]
95
102
  for subpath in subpaths:
96
103
  quads = vmobject.gen_cubic_bezier_tuples_from_points(subpath)
97
104
  start = subpath[0]
98
105
  path.moveTo(*start[:2])
99
- for p0, p1, p2, p3 in quads:
106
+ for _p0, p1, p2, p3 in quads:
100
107
  path.cubicTo(*p1[:2], *p2[:2], *p3[:2])
101
108
 
102
109
  if vmobject.consider_points_equals_2d(subpath[0], subpath[-1]):
@@ -138,7 +145,7 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
138
145
  n1, n2 = self._convert_2d_to_3d_array(points)
139
146
  vmobject.add_quadratic_bezier_curve_to(n1, n2)
140
147
  else:
141
- raise Exception("Unsupported: %s" % path_verb)
148
+ raise Exception(f"Unsupported: {path_verb}")
142
149
  return vmobject
143
150
 
144
151
 
@@ -173,7 +180,7 @@ class Union(_BooleanOps):
173
180
 
174
181
  """
175
182
 
176
- def __init__(self, *vmobjects: VMobject, **kwargs) -> None:
183
+ def __init__(self, *vmobjects: VMobject, **kwargs: Any) -> None:
177
184
  if len(vmobjects) < 2:
178
185
  raise ValueError("At least 2 mobjects needed for Union.")
179
186
  super().__init__(**kwargs)
@@ -212,7 +219,7 @@ class Difference(_BooleanOps):
212
219
 
213
220
  """
214
221
 
215
- def __init__(self, subject: VMobject, clip: VMobject, **kwargs) -> None:
222
+ def __init__(self, subject: VMobject, clip: VMobject, **kwargs: Any) -> None:
216
223
  super().__init__(**kwargs)
217
224
  outpen = SkiaPath()
218
225
  difference(
@@ -254,7 +261,7 @@ class Intersection(_BooleanOps):
254
261
 
255
262
  """
256
263
 
257
- def __init__(self, *vmobjects: VMobject, **kwargs) -> None:
264
+ def __init__(self, *vmobjects: VMobject, **kwargs: Any) -> None:
258
265
  if len(vmobjects) < 2:
259
266
  raise ValueError("At least 2 mobjects needed for Intersection.")
260
267
 
@@ -307,7 +314,7 @@ class Exclusion(_BooleanOps):
307
314
 
308
315
  """
309
316
 
310
- def __init__(self, subject: VMobject, clip: VMobject, **kwargs) -> None:
317
+ def __init__(self, subject: VMobject, clip: VMobject, **kwargs: Any) -> None:
311
318
  super().__init__(**kwargs)
312
319
  outpen = SkiaPath()
313
320
  xor(