manim 0.17.0__py3-none-any.whl → 0.19.1__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.
- manim/__init__.py +11 -6
- manim/__main__.py +62 -19
- manim/_config/__init__.py +10 -9
- manim/_config/cli_colors.py +26 -9
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +23 -13
- manim/_config/utils.py +662 -468
- manim/animation/animation.py +164 -18
- manim/animation/changing.py +34 -23
- manim/animation/composition.py +265 -67
- manim/animation/creation.py +208 -26
- manim/animation/fading.py +16 -18
- manim/animation/growing.py +35 -15
- manim/animation/indication.py +150 -76
- manim/animation/movement.py +56 -22
- manim/animation/numbers.py +64 -6
- manim/animation/rotation.py +78 -7
- manim/animation/specialized.py +6 -7
- manim/animation/speedmodifier.py +13 -10
- manim/animation/transform.py +14 -11
- manim/animation/transform_matching_parts.py +3 -4
- manim/animation/updaters/mobject_update_utils.py +152 -30
- manim/animation/updaters/update.py +10 -7
- manim/camera/camera.py +182 -118
- manim/camera/mapping_camera.py +34 -3
- manim/camera/moving_camera.py +95 -74
- manim/camera/multi_camera.py +23 -15
- manim/camera/three_d_camera.py +70 -52
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +76 -44
- manim/cli/checkhealth/checks.py +192 -0
- manim/cli/checkhealth/commands.py +90 -0
- manim/cli/default_group.py +158 -25
- manim/cli/init/commands.py +33 -25
- manim/cli/plugins/commands.py +16 -3
- manim/cli/render/commands.py +72 -60
- manim/cli/render/ease_of_access_options.py +4 -3
- manim/cli/render/global_options.py +59 -17
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +98 -33
- manim/constants.py +109 -59
- manim/data_structures.py +31 -0
- manim/mobject/frame.py +8 -5
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +277 -135
- manim/mobject/geometry/boolean_ops.py +32 -31
- manim/mobject/geometry/labeled.py +376 -0
- manim/mobject/geometry/line.py +192 -87
- manim/mobject/geometry/polygram.py +224 -58
- manim/mobject/geometry/shape_matchers.py +61 -25
- manim/mobject/geometry/tips.py +122 -48
- manim/mobject/graph.py +1027 -419
- manim/mobject/graphing/coordinate_systems.py +533 -278
- manim/mobject/graphing/functions.py +53 -32
- manim/mobject/graphing/number_line.py +123 -65
- manim/mobject/graphing/probability.py +88 -62
- manim/mobject/graphing/scale.py +33 -19
- manim/mobject/logo.py +118 -28
- manim/mobject/matrix.py +87 -83
- manim/mobject/mobject.py +912 -442
- manim/mobject/opengl/dot_cloud.py +16 -5
- manim/mobject/opengl/opengl_compatibility.py +4 -2
- manim/mobject/opengl/opengl_geometry.py +254 -153
- manim/mobject/opengl/opengl_image_mobject.py +3 -1
- manim/mobject/opengl/opengl_mobject.py +779 -482
- manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
- manim/mobject/opengl/opengl_surface.py +14 -92
- manim/mobject/opengl/opengl_three_dimensions.py +12 -8
- manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
- manim/mobject/svg/brace.py +173 -41
- manim/mobject/svg/svg_mobject.py +139 -53
- manim/mobject/table.py +61 -68
- manim/mobject/text/code_mobject.py +193 -539
- manim/mobject/text/numbers.py +81 -34
- manim/mobject/text/tex_mobject.py +130 -78
- manim/mobject/text/text_mobject.py +288 -164
- manim/mobject/three_d/polyhedra.py +111 -13
- manim/mobject/three_d/three_d_utils.py +17 -8
- manim/mobject/three_d/three_dimensions.py +239 -106
- manim/mobject/types/image_mobject.py +50 -30
- manim/mobject/types/point_cloud_mobject.py +120 -75
- manim/mobject/types/vectorized_mobject.py +841 -408
- manim/mobject/value_tracker.py +105 -38
- manim/mobject/vector_field.py +50 -31
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +10 -14
- manim/renderer/cairo_renderer.py +65 -50
- manim/renderer/opengl_renderer.py +89 -69
- manim/renderer/opengl_renderer_window.py +39 -18
- manim/renderer/shader.py +123 -87
- manim/renderer/shader_wrapper.py +44 -28
- manim/renderer/vectorized_mobject_rendering.py +38 -10
- manim/scene/moving_camera_scene.py +32 -3
- manim/scene/scene.py +507 -242
- manim/scene/scene_file_writer.py +371 -220
- manim/scene/section.py +20 -16
- manim/scene/three_d_scene.py +14 -22
- manim/scene/vector_space_scene.py +223 -129
- manim/scene/zoomed_scene.py +46 -41
- manim/typing.py +990 -0
- manim/utils/bezier.py +1823 -371
- manim/utils/caching.py +12 -5
- manim/utils/color/AS2700.py +236 -0
- manim/utils/color/BS381.py +318 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +533 -0
- manim/utils/color/XKCD.py +952 -0
- manim/utils/color/__init__.py +61 -0
- manim/utils/color/core.py +1667 -0
- manim/utils/color/manim_colors.py +218 -0
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +39 -19
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +86 -39
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +236 -0
- manim/utils/docbuild/autocolor_directive.py +99 -0
- manim/utils/docbuild/manim_directive.py +94 -41
- manim/utils/docbuild/module_parsing.py +245 -0
- manim/utils/exceptions.py +6 -0
- manim/utils/family.py +5 -3
- manim/utils/family_ops.py +17 -4
- manim/utils/file_ops.py +27 -17
- manim/utils/hashing.py +55 -45
- manim/utils/images.py +13 -7
- manim/utils/ipython_magic.py +13 -7
- manim/utils/iterables.py +163 -120
- manim/utils/module_ops.py +66 -24
- manim/utils/opengl.py +77 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +30 -33
- manim/utils/polylabel.py +235 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +98 -32
- manim/utils/simple_functions.py +25 -33
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +188 -115
- manim/utils/testing/__init__.py +17 -0
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +34 -18
- manim/utils/testing/frames_comparison.py +37 -19
- manim/utils/tex.py +130 -198
- manim/utils/tex_file_writing.py +77 -47
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
- manim-0.19.1.dist-info/RECORD +220 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
- manim-0.19.1.dist-info/entry_points.txt +3 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
- manim/cli/new/group.py +0 -189
- manim/communitycolors.py +0 -9
- manim/gui/__init__.py +0 -0
- manim/gui/gui.py +0 -82
- manim/plugins/import_plugins.py +0 -43
- manim/utils/color.py +0 -552
- manim-0.17.0.dist-info/RECORD +0 -206
- manim-0.17.0.dist-info/entry_points.txt +0 -4
- /manim/cli/{new → checkhealth}/__init__.py +0 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
manim/animation/indication.py
CHANGED
|
@@ -25,27 +25,32 @@ Examples
|
|
|
25
25
|
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
28
30
|
__all__ = [
|
|
29
31
|
"FocusOn",
|
|
30
32
|
"Indicate",
|
|
31
33
|
"Flash",
|
|
32
34
|
"ShowPassingFlash",
|
|
33
35
|
"ShowPassingFlashWithThinningStrokeWidth",
|
|
34
|
-
"ShowCreationThenFadeOut",
|
|
35
36
|
"ApplyWave",
|
|
36
37
|
"Circumscribe",
|
|
37
38
|
"Wiggle",
|
|
39
|
+
"Blink",
|
|
38
40
|
]
|
|
39
41
|
|
|
40
|
-
from
|
|
42
|
+
from collections.abc import Iterable
|
|
43
|
+
from typing import Any
|
|
41
44
|
|
|
42
45
|
import numpy as np
|
|
43
|
-
from
|
|
46
|
+
from typing_extensions import Self
|
|
44
47
|
|
|
45
48
|
from manim.mobject.geometry.arc import Circle, Dot
|
|
46
49
|
from manim.mobject.geometry.line import Line
|
|
47
50
|
from manim.mobject.geometry.polygram import Rectangle
|
|
48
51
|
from manim.mobject.geometry.shape_matchers import SurroundingRectangle
|
|
52
|
+
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
53
|
+
from manim.scene.scene import Scene
|
|
49
54
|
|
|
50
55
|
from .. import config
|
|
51
56
|
from ..animation.animation import Animation
|
|
@@ -54,13 +59,14 @@ from ..animation.creation import Create, ShowPartial, Uncreate
|
|
|
54
59
|
from ..animation.fading import FadeIn, FadeOut
|
|
55
60
|
from ..animation.movement import Homotopy
|
|
56
61
|
from ..animation.transform import Transform
|
|
62
|
+
from ..animation.updaters.update import UpdateFromFunc
|
|
57
63
|
from ..constants import *
|
|
58
64
|
from ..mobject.mobject import Mobject
|
|
59
65
|
from ..mobject.types.vectorized_mobject import VGroup, VMobject
|
|
66
|
+
from ..typing import Point3D, Point3DLike, Vector3DLike
|
|
60
67
|
from ..utils.bezier import interpolate, inverse_interpolate
|
|
61
|
-
from ..utils.color import GREY, YELLOW
|
|
62
|
-
from ..utils.
|
|
63
|
-
from ..utils.rate_functions import smooth, there_and_back, wiggle
|
|
68
|
+
from ..utils.color import GREY, YELLOW, ParsableManimColor
|
|
69
|
+
from ..utils.rate_functions import RateFunction, smooth, there_and_back, wiggle
|
|
64
70
|
from ..utils.space_ops import normalize
|
|
65
71
|
|
|
66
72
|
|
|
@@ -77,8 +83,6 @@ class FocusOn(Transform):
|
|
|
77
83
|
The color of the spotlight.
|
|
78
84
|
run_time
|
|
79
85
|
The duration of the animation.
|
|
80
|
-
kwargs
|
|
81
|
-
Additional arguments to be passed to the :class:`~.Succession` constructor
|
|
82
86
|
|
|
83
87
|
Examples
|
|
84
88
|
--------
|
|
@@ -94,12 +98,12 @@ class FocusOn(Transform):
|
|
|
94
98
|
|
|
95
99
|
def __init__(
|
|
96
100
|
self,
|
|
97
|
-
focus_point:
|
|
101
|
+
focus_point: Point3DLike | Mobject,
|
|
98
102
|
opacity: float = 0.2,
|
|
99
|
-
color:
|
|
103
|
+
color: ParsableManimColor = GREY,
|
|
100
104
|
run_time: float = 2,
|
|
101
|
-
**kwargs
|
|
102
|
-
)
|
|
105
|
+
**kwargs: Any,
|
|
106
|
+
):
|
|
103
107
|
self.focus_point = focus_point
|
|
104
108
|
self.color = color
|
|
105
109
|
self.opacity = opacity
|
|
@@ -131,7 +135,7 @@ class Indicate(Transform):
|
|
|
131
135
|
color
|
|
132
136
|
The color the mobject temporally takes.
|
|
133
137
|
rate_func
|
|
134
|
-
The function
|
|
138
|
+
The function defining the animation progress at every point in time.
|
|
135
139
|
kwargs
|
|
136
140
|
Additional arguments to be passed to the :class:`~.Succession` constructor
|
|
137
141
|
|
|
@@ -148,17 +152,17 @@ class Indicate(Transform):
|
|
|
148
152
|
|
|
149
153
|
def __init__(
|
|
150
154
|
self,
|
|
151
|
-
mobject:
|
|
155
|
+
mobject: Mobject,
|
|
152
156
|
scale_factor: float = 1.2,
|
|
153
|
-
color:
|
|
154
|
-
rate_func:
|
|
155
|
-
**kwargs
|
|
156
|
-
)
|
|
157
|
+
color: ParsableManimColor = YELLOW,
|
|
158
|
+
rate_func: RateFunction = there_and_back,
|
|
159
|
+
**kwargs: Any,
|
|
160
|
+
):
|
|
157
161
|
self.color = color
|
|
158
162
|
self.scale_factor = scale_factor
|
|
159
163
|
super().__init__(mobject, rate_func=rate_func, **kwargs)
|
|
160
164
|
|
|
161
|
-
def create_target(self) ->
|
|
165
|
+
def create_target(self) -> Mobject | OpenGLMobject:
|
|
162
166
|
target = self.mobject.copy()
|
|
163
167
|
target.scale(self.scale_factor)
|
|
164
168
|
target.set_color(self.color)
|
|
@@ -218,20 +222,20 @@ class Flash(AnimationGroup):
|
|
|
218
222
|
|
|
219
223
|
def __init__(
|
|
220
224
|
self,
|
|
221
|
-
point:
|
|
225
|
+
point: Point3DLike | Mobject,
|
|
222
226
|
line_length: float = 0.2,
|
|
223
227
|
num_lines: int = 12,
|
|
224
228
|
flash_radius: float = 0.1,
|
|
225
229
|
line_stroke_width: int = 3,
|
|
226
|
-
color:
|
|
230
|
+
color: ParsableManimColor = YELLOW,
|
|
227
231
|
time_width: float = 1,
|
|
228
232
|
run_time: float = 1.0,
|
|
229
|
-
**kwargs
|
|
230
|
-
)
|
|
233
|
+
**kwargs: Any,
|
|
234
|
+
):
|
|
231
235
|
if isinstance(point, Mobject):
|
|
232
|
-
self.point = point.get_center()
|
|
236
|
+
self.point: Point3D = point.get_center()
|
|
233
237
|
else:
|
|
234
|
-
self.point = point
|
|
238
|
+
self.point = np.asarray(point)
|
|
235
239
|
self.color = color
|
|
236
240
|
self.line_length = line_length
|
|
237
241
|
self.num_lines = num_lines
|
|
@@ -256,7 +260,7 @@ class Flash(AnimationGroup):
|
|
|
256
260
|
lines.set_stroke(width=self.line_stroke_width)
|
|
257
261
|
return lines
|
|
258
262
|
|
|
259
|
-
def create_line_anims(self) -> Iterable[
|
|
263
|
+
def create_line_anims(self) -> Iterable[ShowPassingFlash]:
|
|
260
264
|
return [
|
|
261
265
|
ShowPassingFlash(
|
|
262
266
|
line,
|
|
@@ -269,7 +273,7 @@ class Flash(AnimationGroup):
|
|
|
269
273
|
|
|
270
274
|
|
|
271
275
|
class ShowPassingFlash(ShowPartial):
|
|
272
|
-
"""Show only a sliver of the VMobject each frame.
|
|
276
|
+
r"""Show only a sliver of the VMobject each frame.
|
|
273
277
|
|
|
274
278
|
Parameters
|
|
275
279
|
----------
|
|
@@ -289,7 +293,7 @@ class ShowPassingFlash(ShowPartial):
|
|
|
289
293
|
self.add(p, lbl)
|
|
290
294
|
p = p.copy().set_color(BLUE)
|
|
291
295
|
for time_width in [0.2, 0.5, 1, 2]:
|
|
292
|
-
lbl.become(Tex(r"
|
|
296
|
+
lbl.become(Tex(r"\texttt{time\_width={{%.1f}}}"%time_width))
|
|
293
297
|
self.play(ShowPassingFlash(
|
|
294
298
|
p.copy().set_color(BLUE),
|
|
295
299
|
run_time=2,
|
|
@@ -302,11 +306,13 @@ class ShowPassingFlash(ShowPartial):
|
|
|
302
306
|
|
|
303
307
|
"""
|
|
304
308
|
|
|
305
|
-
def __init__(
|
|
309
|
+
def __init__(
|
|
310
|
+
self, mobject: VMobject, time_width: float = 0.1, **kwargs: Any
|
|
311
|
+
) -> None:
|
|
306
312
|
self.time_width = time_width
|
|
307
313
|
super().__init__(mobject, remover=True, introducer=True, **kwargs)
|
|
308
314
|
|
|
309
|
-
def _get_bounds(self, alpha: float) ->
|
|
315
|
+
def _get_bounds(self, alpha: float) -> tuple[float, float]:
|
|
310
316
|
tw = self.time_width
|
|
311
317
|
upper = interpolate(0, 1 + tw, alpha)
|
|
312
318
|
lower = upper - tw
|
|
@@ -314,14 +320,21 @@ class ShowPassingFlash(ShowPartial):
|
|
|
314
320
|
lower = max(lower, 0)
|
|
315
321
|
return (lower, upper)
|
|
316
322
|
|
|
317
|
-
def clean_up_from_scene(self, scene:
|
|
323
|
+
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
318
324
|
super().clean_up_from_scene(scene)
|
|
319
325
|
for submob, start in self.get_all_families_zipped():
|
|
320
326
|
submob.pointwise_become_partial(start, 0, 1)
|
|
321
327
|
|
|
322
328
|
|
|
323
329
|
class ShowPassingFlashWithThinningStrokeWidth(AnimationGroup):
|
|
324
|
-
def __init__(
|
|
330
|
+
def __init__(
|
|
331
|
+
self,
|
|
332
|
+
vmobject: VMobject,
|
|
333
|
+
n_segments: int = 10,
|
|
334
|
+
time_width: float = 0.1,
|
|
335
|
+
remover: bool = True,
|
|
336
|
+
**kwargs: Any,
|
|
337
|
+
):
|
|
325
338
|
self.n_segments = n_segments
|
|
326
339
|
self.time_width = time_width
|
|
327
340
|
self.remover = remover
|
|
@@ -342,16 +355,6 @@ class ShowPassingFlashWithThinningStrokeWidth(AnimationGroup):
|
|
|
342
355
|
)
|
|
343
356
|
|
|
344
357
|
|
|
345
|
-
@deprecated(
|
|
346
|
-
since="v0.15.0",
|
|
347
|
-
until="v0.16.0",
|
|
348
|
-
message="Use Create then FadeOut to achieve this effect.",
|
|
349
|
-
)
|
|
350
|
-
class ShowCreationThenFadeOut(Succession):
|
|
351
|
-
def __init__(self, mobject: "Mobject", remover: bool = True, **kwargs) -> None:
|
|
352
|
-
super().__init__(Create(mobject), FadeOut(mobject), remover=remover, **kwargs)
|
|
353
|
-
|
|
354
|
-
|
|
355
358
|
class ApplyWave(Homotopy):
|
|
356
359
|
"""Send a wave through the Mobject distorting it temporarily.
|
|
357
360
|
|
|
@@ -397,25 +400,25 @@ class ApplyWave(Homotopy):
|
|
|
397
400
|
|
|
398
401
|
def __init__(
|
|
399
402
|
self,
|
|
400
|
-
mobject:
|
|
401
|
-
direction:
|
|
403
|
+
mobject: Mobject,
|
|
404
|
+
direction: Vector3DLike = UP,
|
|
402
405
|
amplitude: float = 0.2,
|
|
403
|
-
wave_func:
|
|
406
|
+
wave_func: RateFunction = smooth,
|
|
404
407
|
time_width: float = 1,
|
|
405
408
|
ripples: int = 1,
|
|
406
409
|
run_time: float = 2,
|
|
407
|
-
**kwargs
|
|
408
|
-
)
|
|
410
|
+
**kwargs: Any,
|
|
411
|
+
):
|
|
409
412
|
x_min = mobject.get_left()[0]
|
|
410
413
|
x_max = mobject.get_right()[0]
|
|
411
414
|
vect = amplitude * normalize(direction)
|
|
412
415
|
|
|
413
|
-
def wave(t):
|
|
416
|
+
def wave(t: float) -> float:
|
|
414
417
|
# Creates a wave with n ripples from a simple rate_func
|
|
415
418
|
# This wave is build up as follows:
|
|
416
419
|
# The time is split into 2*ripples phases. In every phase the amplitude
|
|
417
420
|
# either rises to one or goes down to zero. Consecutive ripples will have
|
|
418
|
-
# their amplitudes in
|
|
421
|
+
# their amplitudes in opposing directions (first ripple from 0 to 1 to 0,
|
|
419
422
|
# second from 0 to -1 to 0 and so on). This is how two ripples would be
|
|
420
423
|
# divided into phases:
|
|
421
424
|
|
|
@@ -454,7 +457,7 @@ class ApplyWave(Homotopy):
|
|
|
454
457
|
return wave_func(t * phases)
|
|
455
458
|
elif phase == phases - 1:
|
|
456
459
|
# last ripple. Rising or falling depending on the number of ripples
|
|
457
|
-
# The (ripples % 2)-term is used to make this
|
|
460
|
+
# The (ripples % 2)-term is used to make this distinction.
|
|
458
461
|
t -= phase / phases # Time relative to the phase
|
|
459
462
|
return (1 - wave_func(t * phases)) * (2 * (ripples % 2) - 1)
|
|
460
463
|
else:
|
|
@@ -470,13 +473,14 @@ class ApplyWave(Homotopy):
|
|
|
470
473
|
y: float,
|
|
471
474
|
z: float,
|
|
472
475
|
t: float,
|
|
473
|
-
) ->
|
|
476
|
+
) -> tuple[float, float, float]:
|
|
474
477
|
upper = interpolate(0, 1 + time_width, t)
|
|
475
478
|
lower = upper - time_width
|
|
476
479
|
relative_x = inverse_interpolate(x_min, x_max, x)
|
|
477
480
|
wave_phase = inverse_interpolate(lower, upper, relative_x)
|
|
478
481
|
nudge = wave(wave_phase) * vect
|
|
479
|
-
|
|
482
|
+
return_value: tuple[float, float, float] = np.array([x, y, z]) + nudge
|
|
483
|
+
return return_value
|
|
480
484
|
|
|
481
485
|
super().__init__(homotopy, mobject, run_time=run_time, **kwargs)
|
|
482
486
|
|
|
@@ -516,38 +520,42 @@ class Wiggle(Animation):
|
|
|
516
520
|
|
|
517
521
|
def __init__(
|
|
518
522
|
self,
|
|
519
|
-
mobject:
|
|
523
|
+
mobject: Mobject,
|
|
520
524
|
scale_value: float = 1.1,
|
|
521
525
|
rotation_angle: float = 0.01 * TAU,
|
|
522
526
|
n_wiggles: int = 6,
|
|
523
|
-
scale_about_point:
|
|
524
|
-
rotate_about_point:
|
|
527
|
+
scale_about_point: Point3DLike | None = None,
|
|
528
|
+
rotate_about_point: Point3DLike | None = None,
|
|
525
529
|
run_time: float = 2,
|
|
526
|
-
**kwargs
|
|
527
|
-
)
|
|
530
|
+
**kwargs: Any,
|
|
531
|
+
):
|
|
528
532
|
self.scale_value = scale_value
|
|
529
533
|
self.rotation_angle = rotation_angle
|
|
530
534
|
self.n_wiggles = n_wiggles
|
|
531
535
|
self.scale_about_point = scale_about_point
|
|
536
|
+
if scale_about_point is not None:
|
|
537
|
+
self.scale_about_point = np.array(scale_about_point)
|
|
532
538
|
self.rotate_about_point = rotate_about_point
|
|
539
|
+
if rotate_about_point is not None:
|
|
540
|
+
self.rotate_about_point = np.array(rotate_about_point)
|
|
533
541
|
super().__init__(mobject, run_time=run_time, **kwargs)
|
|
534
542
|
|
|
535
|
-
def get_scale_about_point(self) ->
|
|
543
|
+
def get_scale_about_point(self) -> Point3D:
|
|
536
544
|
if self.scale_about_point is None:
|
|
537
545
|
return self.mobject.get_center()
|
|
538
546
|
return self.scale_about_point
|
|
539
547
|
|
|
540
|
-
def get_rotate_about_point(self) ->
|
|
548
|
+
def get_rotate_about_point(self) -> Point3D:
|
|
541
549
|
if self.rotate_about_point is None:
|
|
542
550
|
return self.mobject.get_center()
|
|
543
551
|
return self.rotate_about_point
|
|
544
552
|
|
|
545
553
|
def interpolate_submobject(
|
|
546
554
|
self,
|
|
547
|
-
submobject:
|
|
548
|
-
starting_submobject:
|
|
555
|
+
submobject: Mobject,
|
|
556
|
+
starting_submobject: Mobject,
|
|
549
557
|
alpha: float,
|
|
550
|
-
) ->
|
|
558
|
+
) -> Self:
|
|
551
559
|
submobject.points[:, :] = starting_submobject.points
|
|
552
560
|
submobject.scale(
|
|
553
561
|
interpolate(1, self.scale_value, there_and_back(alpha)),
|
|
@@ -557,17 +565,18 @@ class Wiggle(Animation):
|
|
|
557
565
|
wiggle(alpha, self.n_wiggles) * self.rotation_angle,
|
|
558
566
|
about_point=self.get_rotate_about_point(),
|
|
559
567
|
)
|
|
568
|
+
return self
|
|
560
569
|
|
|
561
570
|
|
|
562
571
|
class Circumscribe(Succession):
|
|
563
|
-
"""Draw a temporary line surrounding the mobject.
|
|
572
|
+
r"""Draw a temporary line surrounding the mobject.
|
|
564
573
|
|
|
565
574
|
Parameters
|
|
566
575
|
----------
|
|
567
576
|
mobject
|
|
568
577
|
The mobject to be circumscribed.
|
|
569
578
|
shape
|
|
570
|
-
The shape with which to
|
|
579
|
+
The shape with which to surround the given mobject. Should be either
|
|
571
580
|
:class:`~.Rectangle` or :class:`~.Circle`
|
|
572
581
|
fade_in
|
|
573
582
|
Whether to make the surrounding shape to fade in. It will be drawn otherwise.
|
|
@@ -591,7 +600,7 @@ class Circumscribe(Succession):
|
|
|
591
600
|
|
|
592
601
|
class UsingCircumscribe(Scene):
|
|
593
602
|
def construct(self):
|
|
594
|
-
lbl = Tex(r"Circum
|
|
603
|
+
lbl = Tex(r"Circum-\\scribe").scale(2)
|
|
595
604
|
self.add(lbl)
|
|
596
605
|
self.play(Circumscribe(lbl))
|
|
597
606
|
self.play(Circumscribe(lbl, Circle))
|
|
@@ -604,21 +613,21 @@ class Circumscribe(Succession):
|
|
|
604
613
|
def __init__(
|
|
605
614
|
self,
|
|
606
615
|
mobject: Mobject,
|
|
607
|
-
shape:
|
|
608
|
-
fade_in=False,
|
|
609
|
-
fade_out=False,
|
|
610
|
-
time_width=0.3,
|
|
616
|
+
shape: type[Rectangle] | type[Circle] = Rectangle,
|
|
617
|
+
fade_in: bool = False,
|
|
618
|
+
fade_out: bool = False,
|
|
619
|
+
time_width: float = 0.3,
|
|
611
620
|
buff: float = SMALL_BUFF,
|
|
612
|
-
color:
|
|
613
|
-
run_time=1,
|
|
614
|
-
stroke_width=DEFAULT_STROKE_WIDTH,
|
|
615
|
-
**kwargs
|
|
621
|
+
color: ParsableManimColor = YELLOW,
|
|
622
|
+
run_time: float = 1,
|
|
623
|
+
stroke_width: float = DEFAULT_STROKE_WIDTH,
|
|
624
|
+
**kwargs: Any,
|
|
616
625
|
):
|
|
617
626
|
if shape is Rectangle:
|
|
618
|
-
frame = SurroundingRectangle(
|
|
627
|
+
frame: SurroundingRectangle | Circle = SurroundingRectangle(
|
|
619
628
|
mobject,
|
|
620
|
-
color,
|
|
621
|
-
buff,
|
|
629
|
+
color=color,
|
|
630
|
+
buff=buff,
|
|
622
631
|
stroke_width=stroke_width,
|
|
623
632
|
)
|
|
624
633
|
elif shape is Circle:
|
|
@@ -654,3 +663,68 @@ class Circumscribe(Succession):
|
|
|
654
663
|
super().__init__(
|
|
655
664
|
ShowPassingFlash(frame, time_width, run_time=run_time), **kwargs
|
|
656
665
|
)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
class Blink(Succession):
|
|
669
|
+
"""Blink the mobject.
|
|
670
|
+
|
|
671
|
+
Parameters
|
|
672
|
+
----------
|
|
673
|
+
mobject
|
|
674
|
+
The mobject to be blinked.
|
|
675
|
+
time_on
|
|
676
|
+
The duration that the mobject is shown for one blink.
|
|
677
|
+
time_off
|
|
678
|
+
The duration that the mobject is hidden for one blink.
|
|
679
|
+
blinks
|
|
680
|
+
The number of blinks
|
|
681
|
+
hide_at_end
|
|
682
|
+
Whether to hide the mobject at the end of the animation.
|
|
683
|
+
kwargs
|
|
684
|
+
Additional arguments to be passed to the :class:`~.Succession` constructor.
|
|
685
|
+
|
|
686
|
+
Examples
|
|
687
|
+
--------
|
|
688
|
+
|
|
689
|
+
.. manim:: BlinkingExample
|
|
690
|
+
|
|
691
|
+
class BlinkingExample(Scene):
|
|
692
|
+
def construct(self):
|
|
693
|
+
text = Text("Blinking").scale(1.5)
|
|
694
|
+
self.add(text)
|
|
695
|
+
self.play(Blink(text, blinks=3))
|
|
696
|
+
|
|
697
|
+
"""
|
|
698
|
+
|
|
699
|
+
def __init__(
|
|
700
|
+
self,
|
|
701
|
+
mobject: Mobject,
|
|
702
|
+
time_on: float = 0.5,
|
|
703
|
+
time_off: float = 0.5,
|
|
704
|
+
blinks: int = 1,
|
|
705
|
+
hide_at_end: bool = False,
|
|
706
|
+
**kwargs: Any,
|
|
707
|
+
):
|
|
708
|
+
animations = [
|
|
709
|
+
UpdateFromFunc(
|
|
710
|
+
mobject,
|
|
711
|
+
update_function=lambda mob: mob.set_opacity(1.0),
|
|
712
|
+
run_time=time_on,
|
|
713
|
+
),
|
|
714
|
+
UpdateFromFunc(
|
|
715
|
+
mobject,
|
|
716
|
+
update_function=lambda mob: mob.set_opacity(0.0),
|
|
717
|
+
run_time=time_off,
|
|
718
|
+
),
|
|
719
|
+
] * blinks
|
|
720
|
+
|
|
721
|
+
if not hide_at_end:
|
|
722
|
+
animations.append(
|
|
723
|
+
UpdateFromFunc(
|
|
724
|
+
mobject,
|
|
725
|
+
update_function=lambda mob: mob.set_opacity(1.0),
|
|
726
|
+
run_time=time_on,
|
|
727
|
+
),
|
|
728
|
+
)
|
|
729
|
+
|
|
730
|
+
super().__init__(*animations, **kwargs)
|
manim/animation/movement.py
CHANGED
|
@@ -18,7 +18,13 @@ from ..animation.animation import Animation
|
|
|
18
18
|
from ..utils.rate_functions import linear
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
|
-
from
|
|
21
|
+
from typing_extensions import Self
|
|
22
|
+
|
|
23
|
+
from manim.mobject.types.vectorized_mobject import VMobject
|
|
24
|
+
from manim.typing import MappingFunction, Point3D
|
|
25
|
+
from manim.utils.rate_functions import RateFunction
|
|
26
|
+
|
|
27
|
+
from ..mobject.mobject import Mobject
|
|
22
28
|
|
|
23
29
|
|
|
24
30
|
class Homotopy(Animation):
|
|
@@ -44,6 +50,26 @@ class Homotopy(Animation):
|
|
|
44
50
|
Keyword arguments propagated to :meth:`.Mobject.apply_function`.
|
|
45
51
|
kwargs
|
|
46
52
|
Further keyword arguments passed to the parent class.
|
|
53
|
+
|
|
54
|
+
Examples
|
|
55
|
+
--------
|
|
56
|
+
|
|
57
|
+
.. manim:: HomotopyExample
|
|
58
|
+
|
|
59
|
+
class HomotopyExample(Scene):
|
|
60
|
+
def construct(self):
|
|
61
|
+
square = Square()
|
|
62
|
+
|
|
63
|
+
def homotopy(x, y, z, t):
|
|
64
|
+
if t <= 0.25:
|
|
65
|
+
progress = t / 0.25
|
|
66
|
+
return (x, y + progress * 0.2 * np.sin(x), z)
|
|
67
|
+
else:
|
|
68
|
+
wave_progress = (t - 0.25) / 0.75
|
|
69
|
+
return (x, y + 0.2 * np.sin(x + 10 * wave_progress), z)
|
|
70
|
+
|
|
71
|
+
self.play(Homotopy(homotopy, square, rate_func= linear, run_time=2))
|
|
72
|
+
|
|
47
73
|
"""
|
|
48
74
|
|
|
49
75
|
def __init__(
|
|
@@ -52,27 +78,33 @@ class Homotopy(Animation):
|
|
|
52
78
|
mobject: Mobject,
|
|
53
79
|
run_time: float = 3,
|
|
54
80
|
apply_function_kwargs: dict[str, Any] | None = None,
|
|
55
|
-
**kwargs,
|
|
56
|
-
)
|
|
81
|
+
**kwargs: Any,
|
|
82
|
+
):
|
|
57
83
|
self.homotopy = homotopy
|
|
58
84
|
self.apply_function_kwargs = (
|
|
59
85
|
apply_function_kwargs if apply_function_kwargs is not None else {}
|
|
60
86
|
)
|
|
61
87
|
super().__init__(mobject, run_time=run_time, **kwargs)
|
|
62
88
|
|
|
63
|
-
def function_at_time_t(self, t: float) ->
|
|
64
|
-
|
|
89
|
+
def function_at_time_t(self, t: float) -> MappingFunction:
|
|
90
|
+
def mapping_function(p: Point3D) -> Point3D:
|
|
91
|
+
x, y, z = p
|
|
92
|
+
return np.array(self.homotopy(x, y, z, t))
|
|
93
|
+
|
|
94
|
+
return mapping_function
|
|
65
95
|
|
|
66
96
|
def interpolate_submobject(
|
|
67
97
|
self,
|
|
68
98
|
submobject: Mobject,
|
|
69
99
|
starting_submobject: Mobject,
|
|
70
100
|
alpha: float,
|
|
71
|
-
) ->
|
|
101
|
+
) -> Self:
|
|
72
102
|
submobject.points = starting_submobject.points
|
|
73
103
|
submobject.apply_function(
|
|
74
|
-
self.function_at_time_t(alpha),
|
|
104
|
+
self.function_at_time_t(alpha),
|
|
105
|
+
**self.apply_function_kwargs,
|
|
75
106
|
)
|
|
107
|
+
return self
|
|
76
108
|
|
|
77
109
|
|
|
78
110
|
class SmoothedVectorizedHomotopy(Homotopy):
|
|
@@ -81,18 +113,21 @@ class SmoothedVectorizedHomotopy(Homotopy):
|
|
|
81
113
|
submobject: Mobject,
|
|
82
114
|
starting_submobject: Mobject,
|
|
83
115
|
alpha: float,
|
|
84
|
-
) ->
|
|
116
|
+
) -> Self:
|
|
117
|
+
assert isinstance(submobject, VMobject)
|
|
85
118
|
super().interpolate_submobject(submobject, starting_submobject, alpha)
|
|
86
119
|
submobject.make_smooth()
|
|
120
|
+
return self
|
|
87
121
|
|
|
88
122
|
|
|
89
123
|
class ComplexHomotopy(Homotopy):
|
|
90
124
|
def __init__(
|
|
91
|
-
self,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
self,
|
|
126
|
+
complex_homotopy: Callable[[complex, float], float],
|
|
127
|
+
mobject: Mobject,
|
|
128
|
+
**kwargs: Any,
|
|
129
|
+
):
|
|
130
|
+
"""Complex Homotopy a function Cx[0, 1] to C"""
|
|
96
131
|
|
|
97
132
|
def homotopy(
|
|
98
133
|
x: float,
|
|
@@ -113,9 +148,9 @@ class PhaseFlow(Animation):
|
|
|
113
148
|
mobject: Mobject,
|
|
114
149
|
virtual_time: float = 1,
|
|
115
150
|
suspend_mobject_updating: bool = False,
|
|
116
|
-
rate_func:
|
|
117
|
-
**kwargs,
|
|
118
|
-
)
|
|
151
|
+
rate_func: RateFunction = linear,
|
|
152
|
+
**kwargs: Any,
|
|
153
|
+
):
|
|
119
154
|
self.virtual_time = virtual_time
|
|
120
155
|
self.function = function
|
|
121
156
|
super().__init__(
|
|
@@ -131,13 +166,12 @@ class PhaseFlow(Animation):
|
|
|
131
166
|
self.rate_func(alpha) - self.rate_func(self.last_alpha)
|
|
132
167
|
)
|
|
133
168
|
self.mobject.apply_function(lambda p: p + dt * self.function(p))
|
|
134
|
-
self.last_alpha = alpha
|
|
169
|
+
self.last_alpha: float = alpha
|
|
135
170
|
|
|
136
171
|
|
|
137
172
|
class MoveAlongPath(Animation):
|
|
138
173
|
"""Make one mobject move along the path of another mobject.
|
|
139
|
-
|
|
140
|
-
--------
|
|
174
|
+
|
|
141
175
|
.. manim:: MoveAlongPathExample
|
|
142
176
|
|
|
143
177
|
class MoveAlongPathExample(Scene):
|
|
@@ -154,9 +188,9 @@ class MoveAlongPath(Animation):
|
|
|
154
188
|
self,
|
|
155
189
|
mobject: Mobject,
|
|
156
190
|
path: VMobject,
|
|
157
|
-
suspend_mobject_updating: bool
|
|
158
|
-
**kwargs,
|
|
159
|
-
)
|
|
191
|
+
suspend_mobject_updating: bool = False,
|
|
192
|
+
**kwargs: Any,
|
|
193
|
+
):
|
|
160
194
|
self.path = path
|
|
161
195
|
super().__init__(
|
|
162
196
|
mobject, suspend_mobject_updating=suspend_mobject_updating, **kwargs
|