manim 0.17.3__py3-none-any.whl → 0.18.0.post0__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 (84) hide show
  1. manim/__init__.py +1 -0
  2. manim/__main__.py +2 -0
  3. manim/_config/__init__.py +0 -1
  4. manim/_config/logger_utils.py +1 -0
  5. manim/_config/utils.py +14 -5
  6. manim/animation/changing.py +9 -5
  7. manim/animation/creation.py +8 -3
  8. manim/animation/indication.py +4 -4
  9. manim/animation/speedmodifier.py +2 -4
  10. manim/animation/updaters/mobject_update_utils.py +134 -16
  11. manim/camera/camera.py +31 -17
  12. manim/cli/checkhealth/__init__.py +0 -0
  13. manim/cli/checkhealth/checks.py +173 -0
  14. manim/cli/checkhealth/commands.py +81 -0
  15. manim/cli/render/global_options.py +6 -0
  16. manim/constants.py +58 -54
  17. manim/mobject/geometry/__init__.py +1 -0
  18. manim/mobject/geometry/arc.py +126 -91
  19. manim/mobject/geometry/boolean_ops.py +6 -10
  20. manim/mobject/geometry/labeled.py +155 -0
  21. manim/mobject/geometry/line.py +66 -50
  22. manim/mobject/geometry/polygram.py +23 -15
  23. manim/mobject/geometry/shape_matchers.py +24 -15
  24. manim/mobject/geometry/tips.py +62 -40
  25. manim/mobject/graph.py +3 -4
  26. manim/mobject/graphing/coordinate_systems.py +190 -139
  27. manim/mobject/graphing/number_line.py +5 -2
  28. manim/mobject/graphing/probability.py +4 -3
  29. manim/mobject/graphing/scale.py +7 -7
  30. manim/mobject/logo.py +108 -22
  31. manim/mobject/matrix.py +33 -37
  32. manim/mobject/mobject.py +327 -260
  33. manim/mobject/opengl/opengl_image_mobject.py +1 -1
  34. manim/mobject/opengl/opengl_mobject.py +18 -12
  35. manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
  36. manim/mobject/opengl/opengl_surface.py +1 -1
  37. manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
  38. manim/mobject/svg/brace.py +3 -1
  39. manim/mobject/svg/svg_mobject.py +9 -11
  40. manim/mobject/table.py +50 -54
  41. manim/mobject/text/numbers.py +48 -6
  42. manim/mobject/text/tex_mobject.py +8 -12
  43. manim/mobject/text/text_mobject.py +32 -24
  44. manim/mobject/three_d/three_d_utils.py +13 -8
  45. manim/mobject/three_d/three_dimensions.py +61 -43
  46. manim/mobject/types/image_mobject.py +5 -4
  47. manim/mobject/types/point_cloud_mobject.py +8 -6
  48. manim/mobject/types/vectorized_mobject.py +385 -258
  49. manim/mobject/vector_field.py +19 -11
  50. manim/plugins/import_plugins.py +1 -1
  51. manim/plugins/plugins_flags.py +1 -6
  52. manim/renderer/shader.py +2 -2
  53. manim/scene/scene.py +15 -7
  54. manim/scene/scene_file_writer.py +1 -2
  55. manim/scene/three_d_scene.py +1 -1
  56. manim/scene/vector_space_scene.py +17 -7
  57. manim/typing.py +133 -0
  58. manim/utils/bezier.py +267 -83
  59. manim/utils/color/AS2700.py +234 -0
  60. manim/utils/color/BS381.py +315 -0
  61. manim/utils/color/X11.py +530 -0
  62. manim/utils/color/XKCD.py +949 -0
  63. manim/utils/color/__init__.py +58 -0
  64. manim/utils/color/core.py +1036 -0
  65. manim/utils/color/manim_colors.py +220 -0
  66. manim/utils/docbuild/autocolor_directive.py +92 -0
  67. manim/utils/docbuild/manim_directive.py +40 -6
  68. manim/utils/file_ops.py +1 -1
  69. manim/utils/hashing.py +1 -1
  70. manim/utils/iterables.py +1 -1
  71. manim/utils/rate_functions.py +33 -0
  72. manim/utils/simple_functions.py +0 -18
  73. manim/utils/space_ops.py +55 -42
  74. manim/utils/testing/frames_comparison.py +9 -0
  75. manim/utils/tex.py +2 -0
  76. manim/utils/tex_file_writing.py +29 -2
  77. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
  78. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
  79. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
  80. manim/communitycolors.py +0 -9
  81. manim/utils/color.py +0 -552
  82. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
  83. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
  84. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
@@ -12,6 +12,8 @@ r"""Mobjects representing text rendered using LaTeX.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
+ from manim.utils.color import ManimColor
16
+
15
17
  __all__ = [
16
18
  "SingleStringMathTex",
17
19
  "MathTex",
@@ -26,9 +28,7 @@ import operator as op
26
28
  import re
27
29
  from functools import reduce
28
30
  from textwrap import dedent
29
- from typing import Dict, Iterable, Optional
30
-
31
- from colour import Color
31
+ from typing import Iterable
32
32
 
33
33
  from manim import config, logger
34
34
  from manim.constants import *
@@ -38,8 +38,6 @@ from manim.mobject.types.vectorized_mobject import VectorizedPoint, VGroup, VMob
38
38
  from manim.utils.tex import TexTemplate
39
39
  from manim.utils.tex_file_writing import tex_to_svg_file
40
40
 
41
- SCALE_FACTOR_PER_FONT_POINT = 1 / 960
42
-
43
41
  tex_string_to_mob_map = {}
44
42
 
45
43
 
@@ -255,7 +253,7 @@ class MathTex(SingleStringMathTex):
255
253
  *tex_strings,
256
254
  arg_separator: str = " ",
257
255
  substrings_to_isolate: Iterable[str] | None = None,
258
- tex_to_color_map: dict[str, Color] = None,
256
+ tex_to_color_map: dict[str, ManimColor] = None,
259
257
  tex_environment: str = "align*",
260
258
  **kwargs,
261
259
  ):
@@ -346,10 +344,6 @@ class MathTex(SingleStringMathTex):
346
344
  curr_index + num_submobs + len("".join(self.arg_separator.split()))
347
345
  )
348
346
  if num_submobs == 0:
349
- # For cases like empty tex_strings, we want the corresponding
350
- # part of the whole MathTex to be a VectorizedPoint
351
- # positioned in the right part of the MathTex
352
- sub_tex_mob.submobjects = [VectorizedPoint()]
353
347
  last_submob_index = min(curr_index, len(self.submobjects) - 1)
354
348
  sub_tex_mob.move_to(self.submobjects[last_submob_index], RIGHT)
355
349
  else:
@@ -455,7 +449,8 @@ class Tex(MathTex):
455
449
 
456
450
 
457
451
  class BulletedList(Tex):
458
- """
452
+ """A bulleted list.
453
+
459
454
  Examples
460
455
  --------
461
456
 
@@ -508,7 +503,8 @@ class BulletedList(Tex):
508
503
 
509
504
 
510
505
  class Title(Tex):
511
- """
506
+ """A mobject representing an underlined title.
507
+
512
508
  Examples
513
509
  --------
514
510
  .. manim:: TitleExample
@@ -63,7 +63,6 @@ from typing import Iterable, Sequence
63
63
 
64
64
  import manimpango
65
65
  import numpy as np
66
- from colour import Color
67
66
  from manimpango import MarkupUtils, PangoUtils, TextSetting
68
67
 
69
68
  from manim import config, logger
@@ -71,7 +70,7 @@ from manim.constants import *
71
70
  from manim.mobject.geometry.arc import Dot
72
71
  from manim.mobject.svg.svg_mobject import SVGMobject
73
72
  from manim.mobject.types.vectorized_mobject import VGroup, VMobject
74
- from manim.utils.color import Colors, color_gradient
73
+ from manim.utils.color import ManimColor, ParsableManimColor, color_gradient
75
74
  from manim.utils.deprecation import deprecated
76
75
 
77
76
  TEXT_MOB_SCALE_FACTOR = 0.05
@@ -148,7 +147,7 @@ class Paragraph(VGroup):
148
147
  self,
149
148
  *text: Sequence[str],
150
149
  line_spacing: float = -1,
151
- alignment: Optional[str] = None,
150
+ alignment: str | None = None,
152
151
  **kwargs,
153
152
  ) -> None:
154
153
  self.line_spacing = line_spacing
@@ -413,7 +412,7 @@ class Text(SVGMobject):
413
412
  text: str,
414
413
  fill_opacity: float = 1.0,
415
414
  stroke_width: float = 0,
416
- color: Color | str | None = None,
415
+ color: ParsableManimColor | None = None,
417
416
  font_size: float = DEFAULT_FONT_SIZE,
418
417
  line_spacing: float = -1,
419
418
  font: str = "",
@@ -463,7 +462,7 @@ class Text(SVGMobject):
463
462
  t2g = kwargs.pop("text2gradient", t2g)
464
463
  t2s = kwargs.pop("text2slant", t2s)
465
464
  t2w = kwargs.pop("text2weight", t2w)
466
- self.t2c = t2c
465
+ self.t2c = {k: ManimColor(v).to_hex() for k, v in t2c.items()}
467
466
  self.t2f = t2f
468
467
  self.t2g = t2g
469
468
  self.t2s = t2s
@@ -482,8 +481,8 @@ class Text(SVGMobject):
482
481
  else:
483
482
  self.line_spacing = self._font_size + self._font_size * self.line_spacing
484
483
 
485
- color = Color(color) if color else VMobject().color
486
- file_name = self._text2svg(color)
484
+ color: ManimColor = ManimColor(color) if color else VMobject().color
485
+ file_name = self._text2svg(color.to_hex())
487
486
  PangoUtils.remove_last_M(file_name)
488
487
  super().__init__(
489
488
  file_name,
@@ -643,10 +642,10 @@ class Text(SVGMobject):
643
642
  for start, end in self._find_indexes(word, self.text):
644
643
  self.chars[start:end].set_color_by_gradient(*gradient)
645
644
 
646
- def _text2hash(self, color: Color):
645
+ def _text2hash(self, color: ManimColor):
647
646
  """Generates ``sha256`` hash for file name."""
648
647
  settings = (
649
- "PANGO" + self.font + self.slant + self.weight + color.hex_l
648
+ "PANGO" + self.font + self.slant + self.weight + str(color)
650
649
  ) # to differentiate Text and CairoText
651
650
  settings += str(self.t2f) + str(self.t2s) + str(self.t2w) + str(self.t2c)
652
651
  settings += str(self.line_spacing) + str(self._font_size)
@@ -691,7 +690,9 @@ class Text(SVGMobject):
691
690
  t2xwords = set(chain(*([*t2x.keys()] for t2x, _ in t2xs)))
692
691
  for word in t2xwords:
693
692
  setting_args = {
694
- arg: t2x[word] if word in t2x else default_args[arg]
693
+ arg: str(t2x[word]) if word in t2x else default_args[arg]
694
+ # NOTE: when t2x[word] is a ManimColor, str will yield the
695
+ # hex representation
695
696
  for t2x, arg in t2xs
696
697
  }
697
698
 
@@ -707,13 +708,13 @@ class Text(SVGMobject):
707
708
  if self.gradient:
708
709
  colors = color_gradient(self.gradient, len(self.text))
709
710
  for i in range(len(self.text)):
710
- args["color"] = colors[i].hex
711
+ args["color"] = colors[i].to_hex()
711
712
  settings.append(TextSetting(i, i + 1, **args))
712
713
 
713
714
  for word, gradient in self.t2g.items():
714
715
  if isinstance(gradient, str) or len(gradient) == 1:
715
716
  color = gradient if isinstance(gradient, str) else gradient[0]
716
- gradient = [Color(color)]
717
+ gradient = [ManimColor(color)]
717
718
  colors = (
718
719
  color_gradient(gradient, len(word))
719
720
  if len(gradient) != 1
@@ -721,11 +722,11 @@ class Text(SVGMobject):
721
722
  )
722
723
  for start, end in self._find_indexes(word, self.text):
723
724
  for i in range(start, end):
724
- args["color"] = colors[i - start].hex
725
+ args["color"] = colors[i - start].to_hex()
725
726
  settings.append(TextSetting(i, i + 1, **args))
726
727
  return settings
727
728
 
728
- def _text2settings(self, color: Color):
729
+ def _text2settings(self, color: str):
729
730
  """Converts the texts and styles to a setting for parsing."""
730
731
  t2xs = [
731
732
  (self.t2f, "font"),
@@ -734,8 +735,9 @@ class Text(SVGMobject):
734
735
  (self.t2c, "color"),
735
736
  ]
736
737
  # setting_args requires values to be strings
738
+
737
739
  default_args = {
738
- arg: getattr(self, arg) if arg != "color" else str(color) for _, arg in t2xs
740
+ arg: getattr(self, arg) if arg != "color" else color for _, arg in t2xs
739
741
  }
740
742
 
741
743
  settings = self._get_settings_from_t2xs(t2xs, default_args)
@@ -791,7 +793,7 @@ class Text(SVGMobject):
791
793
 
792
794
  return settings
793
795
 
794
- def _text2svg(self, color: Color):
796
+ def _text2svg(self, color: ManimColor):
795
797
  """Convert the text to SVG using Pango."""
796
798
  size = self._font_size
797
799
  line_spacing = self.line_spacing
@@ -1136,7 +1138,7 @@ class MarkupText(SVGMobject):
1136
1138
  text: str,
1137
1139
  fill_opacity: float = 1,
1138
1140
  stroke_width: float = 0,
1139
- color: Color | None = None,
1141
+ color: ParsableManimColor | None = None,
1140
1142
  font_size: float = DEFAULT_FONT_SIZE,
1141
1143
  line_spacing: int = -1,
1142
1144
  font: str = "",
@@ -1189,7 +1191,7 @@ class MarkupText(SVGMobject):
1189
1191
  else:
1190
1192
  self.line_spacing = self._font_size + self._font_size * self.line_spacing
1191
1193
 
1192
- color = Color(color) if color else VMobject().color
1194
+ color: ManimColor = ManimColor(color) if color else VMobject().color
1193
1195
  file_name = self._text2svg(color)
1194
1196
 
1195
1197
  PangoUtils.remove_last_M(file_name)
@@ -1305,10 +1307,14 @@ class MarkupText(SVGMobject):
1305
1307
  else:
1306
1308
  self.scale(font_val / self.font_size)
1307
1309
 
1308
- def _text2hash(self, color: Color):
1310
+ def _text2hash(self, color: ParsableManimColor):
1309
1311
  """Generates ``sha256`` hash for file name."""
1310
1312
  settings = (
1311
- "MARKUPPANGO" + self.font + self.slant + self.weight + color.hex_l
1313
+ "MARKUPPANGO"
1314
+ + self.font
1315
+ + self.slant
1316
+ + self.weight
1317
+ + ManimColor(color).to_hex().lower()
1312
1318
  ) # to differentiate from classical Pango Text
1313
1319
  settings += str(self.line_spacing) + str(self._font_size)
1314
1320
  settings += str(self.disable_ligatures)
@@ -1318,23 +1324,25 @@ class MarkupText(SVGMobject):
1318
1324
  hasher.update(id_str.encode())
1319
1325
  return hasher.hexdigest()[:16]
1320
1326
 
1321
- def _text2svg(self, color: Color | None):
1327
+ def _text2svg(self, color: ParsableManimColor | None):
1322
1328
  """Convert the text to SVG using Pango."""
1329
+ color = ManimColor(color)
1323
1330
  size = self._font_size
1324
1331
  line_spacing = self.line_spacing
1325
1332
  size /= TEXT2SVG_ADJUSTMENT_FACTOR
1326
1333
  line_spacing /= TEXT2SVG_ADJUSTMENT_FACTOR
1327
1334
 
1328
1335
  dir_name = config.get_dir("text_dir")
1329
- if not dir_name.exists():
1336
+ if not dir_name.is_dir():
1330
1337
  dir_name.mkdir(parents=True)
1331
1338
  hash_name = self._text2hash(color)
1332
1339
  file_name = dir_name / (hash_name + ".svg")
1340
+
1333
1341
  if file_name.exists():
1334
1342
  svg_file = str(file_name.resolve())
1335
1343
  else:
1336
1344
  final_text = (
1337
- f'<span foreground="{color}">{self.text}</span>'
1345
+ f'<span foreground="{color.to_hex()}">{self.text}</span>'
1338
1346
  if color is not None
1339
1347
  else self.text
1340
1348
  )
@@ -1412,7 +1420,7 @@ class MarkupText(SVGMobject):
1412
1420
  if re.match("#[0-9a-f]{6}", col):
1413
1421
  return col
1414
1422
  else:
1415
- return Colors[col.lower()].value
1423
+ return ManimColor(col).to_hex()
1416
1424
 
1417
1425
  def _extract_color_tags(self):
1418
1426
  """Used to determine which parts (if any) of the string should be formatted
@@ -14,40 +14,45 @@ __all__ = [
14
14
  ]
15
15
 
16
16
 
17
+ from typing import TYPE_CHECKING, Literal
18
+
17
19
  import numpy as np
18
20
 
19
21
  from manim.constants import ORIGIN, UP
20
22
  from manim.utils.space_ops import get_unit_normal
21
23
 
24
+ if TYPE_CHECKING:
25
+ from manim.typing import Point3D, Vector
26
+
22
27
 
23
- def get_3d_vmob_gradient_start_and_end_points(vmob):
28
+ def get_3d_vmob_gradient_start_and_end_points(vmob) -> tuple[Point3D, Point3D]:
24
29
  return (
25
30
  get_3d_vmob_start_corner(vmob),
26
31
  get_3d_vmob_end_corner(vmob),
27
32
  )
28
33
 
29
34
 
30
- def get_3d_vmob_start_corner_index(vmob):
35
+ def get_3d_vmob_start_corner_index(vmob) -> Literal[0]:
31
36
  return 0
32
37
 
33
38
 
34
- def get_3d_vmob_end_corner_index(vmob):
39
+ def get_3d_vmob_end_corner_index(vmob) -> int:
35
40
  return ((len(vmob.points) - 1) // 6) * 3
36
41
 
37
42
 
38
- def get_3d_vmob_start_corner(vmob):
43
+ def get_3d_vmob_start_corner(vmob) -> Point3D:
39
44
  if vmob.get_num_points() == 0:
40
45
  return np.array(ORIGIN)
41
46
  return vmob.points[get_3d_vmob_start_corner_index(vmob)]
42
47
 
43
48
 
44
- def get_3d_vmob_end_corner(vmob):
49
+ def get_3d_vmob_end_corner(vmob) -> Point3D:
45
50
  if vmob.get_num_points() == 0:
46
51
  return np.array(ORIGIN)
47
52
  return vmob.points[get_3d_vmob_end_corner_index(vmob)]
48
53
 
49
54
 
50
- def get_3d_vmob_unit_normal(vmob, point_index):
55
+ def get_3d_vmob_unit_normal(vmob, point_index: int) -> Vector:
51
56
  n_points = vmob.get_num_points()
52
57
  if len(vmob.get_anchors()) <= 2:
53
58
  return np.array(UP)
@@ -63,9 +68,9 @@ def get_3d_vmob_unit_normal(vmob, point_index):
63
68
  return unit_normal
64
69
 
65
70
 
66
- def get_3d_vmob_start_corner_unit_normal(vmob):
71
+ def get_3d_vmob_start_corner_unit_normal(vmob) -> Vector:
67
72
  return get_3d_vmob_unit_normal(vmob, get_3d_vmob_start_corner_index(vmob))
68
73
 
69
74
 
70
- def get_3d_vmob_end_corner_unit_normal(vmob):
75
+ def get_3d_vmob_end_corner_unit_normal(vmob) -> Vector:
71
76
  return get_3d_vmob_unit_normal(vmob, get_3d_vmob_end_corner_index(vmob))
@@ -2,6 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from manim.typing import Point3D, Vector3
6
+ from manim.utils.color import BLUE, BLUE_D, BLUE_E, LIGHT_GREY, WHITE, interpolate_color
7
+
5
8
  __all__ = [
6
9
  "ThreeDVMobject",
7
10
  "Surface",
@@ -16,9 +19,10 @@ __all__ = [
16
19
  "Torus",
17
20
  ]
18
21
 
19
- from typing import TYPE_CHECKING
22
+ from typing import Any, Callable, Iterable, Sequence
20
23
 
21
24
  import numpy as np
25
+ from typing_extensions import Self
22
26
 
23
27
  from manim import config, logger
24
28
  from manim.constants import *
@@ -28,15 +32,19 @@ from manim.mobject.mobject import *
28
32
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
29
33
  from manim.mobject.opengl.opengl_mobject import OpenGLMobject
30
34
  from manim.mobject.types.vectorized_mobject import VGroup, VMobject
31
- from manim.utils.color import *
35
+ from manim.utils.color import (
36
+ BLUE,
37
+ BLUE_D,
38
+ BLUE_E,
39
+ LIGHT_GREY,
40
+ WHITE,
41
+ ManimColor,
42
+ ParsableManimColor,
43
+ interpolate_color,
44
+ )
32
45
  from manim.utils.iterables import tuplify
33
46
  from manim.utils.space_ops import normalize, perpendicular_bisector, z_to_vector
34
47
 
35
- if TYPE_CHECKING:
36
- from typing import *
37
-
38
- from colour import Color
39
-
40
48
 
41
49
  class ThreeDVMobject(VMobject, metaclass=ConvertToOpenGL):
42
50
  def __init__(self, shade_in_3d: bool = True, **kwargs):
@@ -102,24 +110,29 @@ class Surface(VGroup, metaclass=ConvertToOpenGL):
102
110
  v_range: Sequence[float] = [0, 1],
103
111
  resolution: Sequence[int] = 32,
104
112
  surface_piece_config: dict = {},
105
- fill_color: Color = BLUE_D,
113
+ fill_color: ParsableManimColor = BLUE_D,
106
114
  fill_opacity: float = 1.0,
107
- checkerboard_colors: Sequence[Color] = [BLUE_D, BLUE_E],
108
- stroke_color: Color = LIGHT_GREY,
115
+ checkerboard_colors: Sequence[ParsableManimColor] | bool = [BLUE_D, BLUE_E],
116
+ stroke_color: ParsableManimColor = LIGHT_GREY,
109
117
  stroke_width: float = 0.5,
110
118
  should_make_jagged: bool = False,
111
119
  pre_function_handle_to_anchor_scale_factor: float = 0.00001,
112
- **kwargs,
120
+ **kwargs: Any,
113
121
  ) -> None:
114
122
  self.u_range = u_range
115
123
  self.v_range = v_range
116
124
  super().__init__(**kwargs)
117
125
  self.resolution = resolution
118
126
  self.surface_piece_config = surface_piece_config
119
- self.fill_color = fill_color
127
+ self.fill_color: ManimColor = ManimColor(fill_color)
120
128
  self.fill_opacity = fill_opacity
121
- self.checkerboard_colors = checkerboard_colors
122
- self.stroke_color = stroke_color
129
+ if checkerboard_colors:
130
+ self.checkerboard_colors: list[ManimColor] = [
131
+ ManimColor(x) for x in checkerboard_colors
132
+ ]
133
+ else:
134
+ self.checkerboard_colors = checkerboard_colors
135
+ self.stroke_color: ManimColor = ManimColor(stroke_color)
123
136
  self.stroke_width = stroke_width
124
137
  self.should_make_jagged = should_make_jagged
125
138
  self.pre_function_handle_to_anchor_scale_factor = (
@@ -132,16 +145,9 @@ class Surface(VGroup, metaclass=ConvertToOpenGL):
132
145
  self.make_jagged()
133
146
 
134
147
  def func(self, u: float, v: float) -> np.ndarray:
135
- """The z values defining the :class:`Surface` being plotted.
136
-
137
- Returns
138
- -------
139
- :class:`numpy.array`
140
- The z values defining the :class:`Surface`.
141
- """
142
148
  return self._func(u, v)
143
149
 
144
- def _get_u_values_and_v_values(self):
150
+ def _get_u_values_and_v_values(self) -> tuple[np.ndarray, np.ndarray]:
145
151
  res = tuplify(self.resolution)
146
152
  if len(res) == 1:
147
153
  u_res = v_res = res[0]
@@ -153,7 +159,7 @@ class Surface(VGroup, metaclass=ConvertToOpenGL):
153
159
 
154
160
  return u_values, v_values
155
161
 
156
- def _setup_in_uv_space(self):
162
+ def _setup_in_uv_space(self) -> None:
157
163
  u_values, v_values = self._get_u_values_and_v_values()
158
164
  faces = VGroup()
159
165
  for i in range(len(u_values) - 1):
@@ -188,8 +194,8 @@ class Surface(VGroup, metaclass=ConvertToOpenGL):
188
194
  self.set_fill_by_checkerboard(*self.checkerboard_colors)
189
195
 
190
196
  def set_fill_by_checkerboard(
191
- self, *colors: Sequence[Color], opacity: float = None
192
- ) -> Mobject:
197
+ self, *colors: Iterable[ParsableManimColor], opacity: float | None = None
198
+ ) -> Self:
193
199
  """Sets the fill_color of each face of :class:`Surface` in
194
200
  an alternating pattern.
195
201
 
@@ -215,10 +221,10 @@ class Surface(VGroup, metaclass=ConvertToOpenGL):
215
221
  def set_fill_by_value(
216
222
  self,
217
223
  axes: Mobject,
218
- colorscale: Union[Iterable[Color], Color] | None = None,
224
+ colorscale: list[ParsableManimColor] | ParsableManimColor | None = None,
219
225
  axis: int = 2,
220
226
  **kwargs,
221
- ) -> Mobject:
227
+ ) -> Self:
222
228
  """Sets the color of each mobject of a parametric surface to a color
223
229
  relative to its axis-value.
224
230
 
@@ -372,9 +378,9 @@ class Sphere(Surface):
372
378
 
373
379
  def __init__(
374
380
  self,
375
- center: Sequence[float] = ORIGIN,
381
+ center: Point3D = ORIGIN,
376
382
  radius: float = 1,
377
- resolution: Sequence[int] = None,
383
+ resolution: Sequence[int] | None = None,
378
384
  u_range: Sequence[float] = (0, TAU),
379
385
  v_range: Sequence[float] = (0, PI),
380
386
  **kwargs,
@@ -449,8 +455,8 @@ class Dot3D(Sphere):
449
455
  self,
450
456
  point: list | np.ndarray = ORIGIN,
451
457
  radius: float = DEFAULT_DOT_RADIUS,
452
- color: Color = WHITE,
453
- resolution: Sequence[int] = (8, 8),
458
+ color: ParsableManimColor = WHITE,
459
+ resolution: tuple[int, int] = (8, 8),
454
460
  **kwargs,
455
461
  ) -> None:
456
462
  super().__init__(center=point, radius=radius, resolution=resolution, **kwargs)
@@ -491,7 +497,7 @@ class Cube(VGroup):
491
497
  self,
492
498
  side_length: float = 2,
493
499
  fill_opacity: float = 0.75,
494
- fill_color: Color = BLUE,
500
+ fill_color: ParsableManimColor = BLUE,
495
501
  stroke_width: float = 0,
496
502
  **kwargs,
497
503
  ) -> None:
@@ -542,7 +548,9 @@ class Prism(Cube):
542
548
  self.add(prismSmall, prismLarge)
543
549
  """
544
550
 
545
- def __init__(self, dimensions: Sequence[int] = [3, 2, 1], **kwargs) -> None:
551
+ def __init__(
552
+ self, dimensions: tuple[float, float, float] | np.ndarray = [3, 2, 1], **kwargs
553
+ ) -> None:
546
554
  self.dimensions = dimensions
547
555
  super().__init__(**kwargs)
548
556
 
@@ -600,8 +608,8 @@ class Cone(Surface):
600
608
  v_range: Sequence[float] = [0, TAU],
601
609
  u_min: float = 0,
602
610
  checkerboard_colors: bool = False,
603
- **kwargs,
604
- ):
611
+ **kwargs: Any,
612
+ ) -> None:
605
613
  self.direction = direction
606
614
  self.theta = PI - np.arctan(base_radius / height)
607
615
 
@@ -653,7 +661,7 @@ class Cone(Surface):
653
661
  ],
654
662
  )
655
663
 
656
- def _rotate_to_direction(self):
664
+ def _rotate_to_direction(self) -> None:
657
665
  x, y, z = self.direction
658
666
 
659
667
  r = np.sqrt(x**2 + y**2 + z**2)
@@ -812,7 +820,7 @@ class Cylinder(Surface):
812
820
  self.base_bottom.shift(self.u_range[0] * IN)
813
821
  self.add(self.base_top, self.base_bottom)
814
822
 
815
- def _rotate_to_direction(self):
823
+ def _rotate_to_direction(self) -> None:
816
824
  x, y, z = self.direction
817
825
 
818
826
  r = np.sqrt(x**2 + y**2 + z**2)
@@ -901,7 +909,7 @@ class Line3D(Cylinder):
901
909
  start: np.ndarray = LEFT,
902
910
  end: np.ndarray = RIGHT,
903
911
  thickness: float = 0.02,
904
- color: Color = None,
912
+ color: ParsableManimColor | None = None,
905
913
  **kwargs,
906
914
  ):
907
915
  self.thickness = thickness
@@ -943,7 +951,9 @@ class Line3D(Cylinder):
943
951
  self.shift((self.start + self.end) / 2)
944
952
 
945
953
  def pointify(
946
- self, mob_or_point: Mobject | float, direction: np.ndarray = None
954
+ self,
955
+ mob_or_point: Mobject | Point3D,
956
+ direction: Vector3 = None,
947
957
  ) -> np.ndarray:
948
958
  """Gets a point representing the center of the :class:`Mobjects <.Mobject>`.
949
959
 
@@ -989,7 +999,11 @@ class Line3D(Cylinder):
989
999
 
990
1000
  @classmethod
991
1001
  def parallel_to(
992
- cls, line: Line3D, point: Sequence[float] = ORIGIN, length: float = 5, **kwargs
1002
+ cls,
1003
+ line: Line3D,
1004
+ point: Vector3 = ORIGIN,
1005
+ length: float = 5,
1006
+ **kwargs,
993
1007
  ) -> Line3D:
994
1008
  """Returns a line parallel to another line going through
995
1009
  a given point.
@@ -1033,7 +1047,11 @@ class Line3D(Cylinder):
1033
1047
 
1034
1048
  @classmethod
1035
1049
  def perpendicular_to(
1036
- cls, line: Line3D, point: Sequence[float] = ORIGIN, length: float = 5, **kwargs
1050
+ cls,
1051
+ line: Line3D,
1052
+ point: Vector3 = ORIGIN,
1053
+ length: float = 5,
1054
+ **kwargs,
1037
1055
  ) -> Line3D:
1038
1056
  """Returns a line perpendicular to another line going through
1039
1057
  a given point.
@@ -1124,7 +1142,7 @@ class Arrow3D(Line3D):
1124
1142
  thickness: float = 0.02,
1125
1143
  height: float = 0.3,
1126
1144
  base_radius: float = 0.08,
1127
- color: Color = WHITE,
1145
+ color: ParsableManimColor = WHITE,
1128
1146
  **kwargs,
1129
1147
  ) -> None:
1130
1148
  super().__init__(
@@ -1182,7 +1200,7 @@ class Torus(Surface):
1182
1200
  minor_radius: float = 1,
1183
1201
  u_range: Sequence[float] = (0, TAU),
1184
1202
  v_range: Sequence[float] = (0, TAU),
1185
- resolution: Sequence[int] = None,
1203
+ resolution: tuple[int, int] | None = None,
1186
1204
  **kwargs,
1187
1205
  ) -> None:
1188
1206
  if config.renderer == RendererType.OPENGL:
@@ -6,7 +6,6 @@ __all__ = ["AbstractImageMobject", "ImageMobject", "ImageMobjectFromCamera"]
6
6
 
7
7
  import pathlib
8
8
 
9
- import colour
10
9
  import numpy as np
11
10
  from PIL import Image
12
11
  from PIL.Image import Resampling
@@ -17,7 +16,7 @@ from ... import config
17
16
  from ...constants import *
18
17
  from ...mobject.mobject import Mobject
19
18
  from ...utils.bezier import interpolate
20
- from ...utils.color import WHITE, color_to_int_rgb
19
+ from ...utils.color import WHITE, ManimColor, color_to_int_rgb
21
20
  from ...utils.images import change_to_rgba_array, get_full_raster_image_path
22
21
 
23
22
 
@@ -84,14 +83,16 @@ class AbstractImageMobject(Mobject):
84
83
  "Available algorithms: 'bicubic', 'nearest', 'box', 'bilinear', "
85
84
  "'hamming', 'lanczos'.",
86
85
  )
86
+ return self
87
87
 
88
88
  def reset_points(self):
89
- # Corresponding corners of image are fixed to these 3 points
89
+ """Sets :attr:`points` to be the four image corners."""
90
90
  self.points = np.array(
91
91
  [
92
92
  UP + LEFT,
93
93
  UP + RIGHT,
94
94
  DOWN + LEFT,
95
+ DOWN + RIGHT,
95
96
  ],
96
97
  )
97
98
  self.center()
@@ -276,7 +277,7 @@ class ImageMobject(AbstractImageMobject):
276
277
 
277
278
  def get_style(self):
278
279
  return {
279
- "fill_color": colour.rgb2hex(self.color.get_rgb()),
280
+ "fill_color": ManimColor(self.color.get_rgb()).to_hex(),
280
281
  "fill_opacity": self.fill_opacity,
281
282
  }
282
283