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