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
@@ -1,40 +1,105 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
3
4
  import re
5
+ import sys
6
+ from typing import TYPE_CHECKING
4
7
 
5
8
  from cloup import Choice, option, option_group
6
9
 
7
10
  from manim.constants import QUALITIES, RendererType
8
11
 
9
- from ... import logger
12
+ if TYPE_CHECKING:
13
+ from click import Context, Option
10
14
 
11
15
  __all__ = ["render_options"]
12
16
 
17
+ logger = logging.getLogger("manim")
18
+
19
+
20
+ def validate_scene_range(
21
+ ctx: Context, param: Option, value: str | None
22
+ ) -> tuple[int] | tuple[int, int] | None:
23
+ """If the ``value`` string is given, extract from it the scene range, which
24
+ should be in any of these formats: 'start', 'start;end', 'start,end' or
25
+ 'start-end'. Otherwise, return ``None``.
26
+
27
+ Parameters
28
+ ----------
29
+ ctx
30
+ The Click context.
31
+ param
32
+ A Click option.
33
+ value
34
+ The optional string which will be parsed.
35
+
36
+ Returns
37
+ -------
38
+ tuple[int] | tuple[int, int] | None
39
+ If ``value`` is ``None``, the return value is ``None``. Otherwise, it's
40
+ the scene range, given by a tuple which may contain a single value
41
+ ``start`` or two values ``start`` and ``end``.
42
+
43
+ Raises
44
+ ------
45
+ ValueError
46
+ If ``value`` has an invalid format.
47
+ """
48
+ if value is None:
49
+ return None
13
50
 
14
- def validate_scene_range(ctx, param, value):
15
51
  try:
16
52
  start = int(value)
17
53
  return (start,)
18
54
  except Exception:
19
55
  pass
20
56
 
21
- if value:
22
- try:
23
- start, end = map(int, re.split(r"[;,\-]", value))
24
- return start, end
25
- except Exception:
26
- logger.error("Couldn't determine a range for -n option.")
27
- exit()
57
+ try:
58
+ start, end = map(int, re.split(r"[;,\-]", value))
59
+ except Exception:
60
+ logger.error("Couldn't determine a range for -n option.")
61
+ sys.exit()
62
+
63
+ return start, end
28
64
 
29
65
 
30
- def validate_resolution(ctx, param, value):
31
- if value:
32
- try:
33
- start, end = map(int, re.split(r"[;,\-]", value))
34
- return (start, end)
35
- except Exception:
36
- logger.error("Resolution option is invalid.")
37
- exit()
66
+ def validate_resolution(
67
+ ctx: Context, param: Option, value: str | None
68
+ ) -> tuple[int, int] | None:
69
+ """If the ``value`` string is given, extract from it the resolution, which
70
+ should be in any of these formats: 'W;H', 'W,H' or 'W-H'. Otherwise, return
71
+ ``None``.
72
+
73
+ Parameters
74
+ ----------
75
+ ctx
76
+ The Click context.
77
+ param
78
+ A Click option.
79
+ value
80
+ The optional string which will be parsed.
81
+
82
+ Returns
83
+ -------
84
+ tuple[int, int] | None
85
+ If ``value`` is ``None``, the return value is ``None``. Otherwise, it's
86
+ the resolution as a ``(W, H)`` tuple.
87
+
88
+ Raises
89
+ ------
90
+ ValueError
91
+ If ``value`` has an invalid format.
92
+ """
93
+ if value is None:
94
+ return None
95
+
96
+ try:
97
+ width, height = map(int, re.split(r"[;,\-]", value))
98
+ except Exception:
99
+ logger.error("Resolution option is invalid.")
100
+ sys.exit()
101
+
102
+ return width, height
38
103
 
39
104
 
40
105
  render_options = option_group(
@@ -71,14 +136,14 @@ render_options = option_group(
71
136
  "--quality",
72
137
  default=None,
73
138
  type=Choice(
74
- list(reversed([q["flag"] for q in QUALITIES.values() if q["flag"]])), # type: ignore
139
+ list(reversed([q["flag"] for q in QUALITIES.values() if q["flag"]])),
75
140
  case_sensitive=False,
76
141
  ),
77
142
  help="Render quality at the follow resolution framerates, respectively: "
78
143
  + ", ".join(
79
144
  reversed(
80
145
  [
81
- f'{q["pixel_width"]}x{q["pixel_height"]} {q["frame_rate"]}FPS'
146
+ f"{q['pixel_width']}x{q['pixel_height']} {q['frame_rate']}FPS"
82
147
  for q in QUALITIES.values()
83
148
  if q["flag"]
84
149
  ]
manim/constants.py CHANGED
@@ -1,10 +1,9 @@
1
- """
2
- Constant definitions.
3
- """
1
+ """Constant definitions."""
4
2
 
5
3
  from __future__ import annotations
6
4
 
7
5
  from enum import Enum
6
+ from typing import TypedDict
8
7
 
9
8
  import numpy as np
10
9
  from cloup import Context
@@ -199,8 +198,16 @@ TAU = 2 * PI
199
198
  DEGREES = TAU / 360
200
199
  """The exchange rate between radians and degrees."""
201
200
 
201
+
202
+ class QualityDict(TypedDict):
203
+ flag: str | None
204
+ pixel_height: int
205
+ pixel_width: int
206
+ frame_rate: int
207
+
208
+
202
209
  # Video qualities
203
- QUALITIES: dict[str, dict[str, str | int | None]] = {
210
+ QUALITIES: dict[str, QualityDict] = {
204
211
  "fourk_quality": {
205
212
  "flag": "k",
206
213
  "pixel_height": 2160,
manim/mobject/frame.py CHANGED
@@ -24,7 +24,6 @@ class ScreenRectangle(Rectangle):
24
24
  When set, the width is stretched to accommodate
25
25
  the new aspect ratio.
26
26
  """
27
-
28
27
  return self.width / self.height
29
28
 
30
29
  @aspect_ratio.setter
@@ -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, Vector3D
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):
@@ -93,7 +101,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
93
101
  tip_length: float = DEFAULT_ARROW_TIP_LENGTH,
94
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
107
  self.normal_vector: Vector3D = normal_vector
@@ -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:
@@ -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",