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.
- manim/__init__.py +1 -0
- manim/__main__.py +2 -0
- manim/_config/__init__.py +0 -1
- manim/_config/logger_utils.py +1 -0
- manim/_config/utils.py +14 -5
- manim/animation/changing.py +9 -5
- manim/animation/creation.py +8 -3
- manim/animation/indication.py +4 -4
- manim/animation/speedmodifier.py +2 -4
- manim/animation/updaters/mobject_update_utils.py +134 -16
- manim/camera/camera.py +31 -17
- manim/cli/checkhealth/__init__.py +0 -0
- manim/cli/checkhealth/checks.py +173 -0
- manim/cli/checkhealth/commands.py +81 -0
- manim/cli/render/global_options.py +6 -0
- manim/constants.py +58 -54
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +126 -91
- manim/mobject/geometry/boolean_ops.py +6 -10
- manim/mobject/geometry/labeled.py +155 -0
- manim/mobject/geometry/line.py +66 -50
- manim/mobject/geometry/polygram.py +23 -15
- manim/mobject/geometry/shape_matchers.py +24 -15
- manim/mobject/geometry/tips.py +62 -40
- manim/mobject/graph.py +3 -4
- manim/mobject/graphing/coordinate_systems.py +190 -139
- manim/mobject/graphing/number_line.py +5 -2
- manim/mobject/graphing/probability.py +4 -3
- manim/mobject/graphing/scale.py +7 -7
- manim/mobject/logo.py +108 -22
- manim/mobject/matrix.py +33 -37
- manim/mobject/mobject.py +327 -260
- manim/mobject/opengl/opengl_image_mobject.py +1 -1
- manim/mobject/opengl/opengl_mobject.py +18 -12
- manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
- manim/mobject/opengl/opengl_surface.py +1 -1
- manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
- manim/mobject/svg/brace.py +3 -1
- manim/mobject/svg/svg_mobject.py +9 -11
- manim/mobject/table.py +50 -54
- manim/mobject/text/numbers.py +48 -6
- manim/mobject/text/tex_mobject.py +8 -12
- manim/mobject/text/text_mobject.py +32 -24
- manim/mobject/three_d/three_d_utils.py +13 -8
- manim/mobject/three_d/three_dimensions.py +61 -43
- manim/mobject/types/image_mobject.py +5 -4
- manim/mobject/types/point_cloud_mobject.py +8 -6
- manim/mobject/types/vectorized_mobject.py +385 -258
- manim/mobject/vector_field.py +19 -11
- manim/plugins/import_plugins.py +1 -1
- manim/plugins/plugins_flags.py +1 -6
- manim/renderer/shader.py +2 -2
- manim/scene/scene.py +15 -7
- manim/scene/scene_file_writer.py +1 -2
- manim/scene/three_d_scene.py +1 -1
- manim/scene/vector_space_scene.py +17 -7
- manim/typing.py +133 -0
- manim/utils/bezier.py +267 -83
- manim/utils/color/AS2700.py +234 -0
- manim/utils/color/BS381.py +315 -0
- manim/utils/color/X11.py +530 -0
- manim/utils/color/XKCD.py +949 -0
- manim/utils/color/__init__.py +58 -0
- manim/utils/color/core.py +1036 -0
- manim/utils/color/manim_colors.py +220 -0
- manim/utils/docbuild/autocolor_directive.py +92 -0
- manim/utils/docbuild/manim_directive.py +40 -6
- manim/utils/file_ops.py +1 -1
- manim/utils/hashing.py +1 -1
- manim/utils/iterables.py +1 -1
- manim/utils/rate_functions.py +33 -0
- manim/utils/simple_functions.py +0 -18
- manim/utils/space_ops.py +55 -42
- manim/utils/testing/frames_comparison.py +9 -0
- manim/utils/tex.py +2 -0
- manim/utils/tex_file_writing.py +29 -2
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
- manim/communitycolors.py +0 -9
- manim/utils/color.py +0 -552
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
- {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
|
|
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,
|
|
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
|
|
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:
|
|
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:
|
|
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 =
|
|
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:
|
|
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
|
|
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].
|
|
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 = [
|
|
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].
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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 =
|
|
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:
|
|
1310
|
+
def _text2hash(self, color: ParsableManimColor):
|
|
1309
1311
|
"""Generates ``sha256`` hash for file name."""
|
|
1310
1312
|
settings = (
|
|
1311
|
-
"MARKUPPANGO"
|
|
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:
|
|
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.
|
|
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
|
|
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
|
|
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:
|
|
113
|
+
fill_color: ParsableManimColor = BLUE_D,
|
|
106
114
|
fill_opacity: float = 1.0,
|
|
107
|
-
checkerboard_colors: Sequence[
|
|
108
|
-
stroke_color:
|
|
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
|
-
|
|
122
|
-
|
|
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:
|
|
192
|
-
) ->
|
|
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:
|
|
224
|
+
colorscale: list[ParsableManimColor] | ParsableManimColor | None = None,
|
|
219
225
|
axis: int = 2,
|
|
220
226
|
**kwargs,
|
|
221
|
-
) ->
|
|
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:
|
|
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:
|
|
453
|
-
resolution:
|
|
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:
|
|
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__(
|
|
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:
|
|
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,
|
|
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,
|
|
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,
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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":
|
|
280
|
+
"fill_color": ManimColor(self.color.get_rgb()).to_hex(),
|
|
280
281
|
"fill_opacity": self.fill_opacity,
|
|
281
282
|
}
|
|
282
283
|
|