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
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"""Colors included in the global name space.
|
|
2
|
+
|
|
3
|
+
These colors form Manim's default color space.
|
|
4
|
+
|
|
5
|
+
.. manim:: ColorsOverview
|
|
6
|
+
:save_last_frame:
|
|
7
|
+
:hide_source:
|
|
8
|
+
|
|
9
|
+
import manim.utils.color.manim_colors as Colors
|
|
10
|
+
|
|
11
|
+
class ColorsOverview(Scene):
|
|
12
|
+
def construct(self):
|
|
13
|
+
def color_group(color):
|
|
14
|
+
group = VGroup(
|
|
15
|
+
*[
|
|
16
|
+
Line(ORIGIN, RIGHT * 1.5, stroke_width=35, color=getattr(Colors, name.upper()))
|
|
17
|
+
for name in subnames(color)
|
|
18
|
+
]
|
|
19
|
+
).arrange_submobjects(buff=0.4, direction=DOWN)
|
|
20
|
+
|
|
21
|
+
name = Text(color).scale(0.6).next_to(group, UP, buff=0.3)
|
|
22
|
+
if any(decender in color for decender in "gjpqy"):
|
|
23
|
+
name.shift(DOWN * 0.08)
|
|
24
|
+
group.add(name)
|
|
25
|
+
return group
|
|
26
|
+
|
|
27
|
+
def subnames(name):
|
|
28
|
+
return [name + "_" + char for char in "abcde"]
|
|
29
|
+
|
|
30
|
+
color_groups = VGroup(
|
|
31
|
+
*[
|
|
32
|
+
color_group(color)
|
|
33
|
+
for color in [
|
|
34
|
+
"blue",
|
|
35
|
+
"teal",
|
|
36
|
+
"green",
|
|
37
|
+
"yellow",
|
|
38
|
+
"gold",
|
|
39
|
+
"red",
|
|
40
|
+
"maroon",
|
|
41
|
+
"purple",
|
|
42
|
+
]
|
|
43
|
+
]
|
|
44
|
+
).arrange_submobjects(buff=0.2, aligned_edge=DOWN)
|
|
45
|
+
|
|
46
|
+
for line, char in zip(color_groups[0], "abcde"):
|
|
47
|
+
color_groups.add(Text(char).scale(0.6).next_to(line, LEFT, buff=0.2))
|
|
48
|
+
|
|
49
|
+
def named_lines_group(length, colors, names, text_colors, align_to_block):
|
|
50
|
+
lines = VGroup(
|
|
51
|
+
*[
|
|
52
|
+
Line(
|
|
53
|
+
ORIGIN,
|
|
54
|
+
RIGHT * length,
|
|
55
|
+
stroke_width=55,
|
|
56
|
+
color=getattr(Colors, color.upper()),
|
|
57
|
+
)
|
|
58
|
+
for color in colors
|
|
59
|
+
]
|
|
60
|
+
).arrange_submobjects(buff=0.6, direction=DOWN)
|
|
61
|
+
|
|
62
|
+
for line, name, color in zip(lines, names, text_colors):
|
|
63
|
+
line.add(Text(name, color=color).scale(0.6).move_to(line))
|
|
64
|
+
lines.next_to(color_groups, DOWN, buff=0.5).align_to(
|
|
65
|
+
color_groups[align_to_block], LEFT
|
|
66
|
+
)
|
|
67
|
+
return lines
|
|
68
|
+
|
|
69
|
+
other_colors = (
|
|
70
|
+
"pink",
|
|
71
|
+
"light_pink",
|
|
72
|
+
"orange",
|
|
73
|
+
"light_brown",
|
|
74
|
+
"dark_brown",
|
|
75
|
+
"gray_brown",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
other_lines = named_lines_group(
|
|
79
|
+
3.2,
|
|
80
|
+
other_colors,
|
|
81
|
+
other_colors,
|
|
82
|
+
[BLACK] * 4 + [WHITE] * 2,
|
|
83
|
+
0,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
gray_lines = named_lines_group(
|
|
87
|
+
6.6,
|
|
88
|
+
["white"] + subnames("gray") + ["black"],
|
|
89
|
+
[
|
|
90
|
+
"white",
|
|
91
|
+
"lighter_gray / gray_a",
|
|
92
|
+
"light_gray / gray_b",
|
|
93
|
+
"gray / gray_c",
|
|
94
|
+
"dark_gray / gray_d",
|
|
95
|
+
"darker_gray / gray_e",
|
|
96
|
+
"black",
|
|
97
|
+
],
|
|
98
|
+
[BLACK] * 3 + [WHITE] * 4,
|
|
99
|
+
2,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
pure_colors = (
|
|
103
|
+
"pure_red",
|
|
104
|
+
"pure_green",
|
|
105
|
+
"pure_blue",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
pure_lines = named_lines_group(
|
|
109
|
+
3.2,
|
|
110
|
+
pure_colors,
|
|
111
|
+
pure_colors,
|
|
112
|
+
[BLACK, BLACK, WHITE],
|
|
113
|
+
6,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
self.add(color_groups, other_lines, gray_lines, pure_lines)
|
|
117
|
+
|
|
118
|
+
VGroup(*self.mobjects).move_to(ORIGIN)
|
|
119
|
+
|
|
120
|
+
.. automanimcolormodule:: manim.utils.color.manim_colors
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
from typing import List
|
|
125
|
+
|
|
126
|
+
from .core import ManimColor
|
|
127
|
+
|
|
128
|
+
WHITE = ManimColor("#FFFFFF")
|
|
129
|
+
GRAY_A = ManimColor("#DDDDDD")
|
|
130
|
+
GREY_A = ManimColor("#DDDDDD")
|
|
131
|
+
GRAY_B = ManimColor("#BBBBBB")
|
|
132
|
+
GREY_B = ManimColor("#BBBBBB")
|
|
133
|
+
GRAY_C = ManimColor("#888888")
|
|
134
|
+
GREY_C = ManimColor("#888888")
|
|
135
|
+
GRAY_D = ManimColor("#444444")
|
|
136
|
+
GREY_D = ManimColor("#444444")
|
|
137
|
+
GRAY_E = ManimColor("#222222")
|
|
138
|
+
GREY_E = ManimColor("#222222")
|
|
139
|
+
BLACK = ManimColor("#000000")
|
|
140
|
+
LIGHTER_GRAY = ManimColor("#DDDDDD")
|
|
141
|
+
LIGHTER_GREY = ManimColor("#DDDDDD")
|
|
142
|
+
LIGHT_GRAY = ManimColor("#BBBBBB")
|
|
143
|
+
LIGHT_GREY = ManimColor("#BBBBBB")
|
|
144
|
+
GRAY = ManimColor("#888888")
|
|
145
|
+
GREY = ManimColor("#888888")
|
|
146
|
+
DARK_GRAY = ManimColor("#444444")
|
|
147
|
+
DARK_GREY = ManimColor("#444444")
|
|
148
|
+
DARKER_GRAY = ManimColor("#222222")
|
|
149
|
+
DARKER_GREY = ManimColor("#222222")
|
|
150
|
+
BLUE_A = ManimColor("#C7E9F1")
|
|
151
|
+
BLUE_B = ManimColor("#9CDCEB")
|
|
152
|
+
BLUE_C = ManimColor("#58C4DD")
|
|
153
|
+
BLUE_D = ManimColor("#29ABCA")
|
|
154
|
+
BLUE_E = ManimColor("#236B8E")
|
|
155
|
+
PURE_BLUE = ManimColor("#0000FF")
|
|
156
|
+
BLUE = ManimColor("#58C4DD")
|
|
157
|
+
DARK_BLUE = ManimColor("#236B8E")
|
|
158
|
+
TEAL_A = ManimColor("#ACEAD7")
|
|
159
|
+
TEAL_B = ManimColor("#76DDC0")
|
|
160
|
+
TEAL_C = ManimColor("#5CD0B3")
|
|
161
|
+
TEAL_D = ManimColor("#55C1A7")
|
|
162
|
+
TEAL_E = ManimColor("#49A88F")
|
|
163
|
+
TEAL = ManimColor("#5CD0B3")
|
|
164
|
+
GREEN_A = ManimColor("#C9E2AE")
|
|
165
|
+
GREEN_B = ManimColor("#A6CF8C")
|
|
166
|
+
GREEN_C = ManimColor("#83C167")
|
|
167
|
+
GREEN_D = ManimColor("#77B05D")
|
|
168
|
+
GREEN_E = ManimColor("#699C52")
|
|
169
|
+
PURE_GREEN = ManimColor("#00FF00")
|
|
170
|
+
GREEN = ManimColor("#83C167")
|
|
171
|
+
YELLOW_A = ManimColor("#FFF1B6")
|
|
172
|
+
YELLOW_B = ManimColor("#FFEA94")
|
|
173
|
+
YELLOW_C = ManimColor("#FFFF00")
|
|
174
|
+
YELLOW_D = ManimColor("#F4D345")
|
|
175
|
+
YELLOW_E = ManimColor("#E8C11C")
|
|
176
|
+
YELLOW = ManimColor("#FFFF00")
|
|
177
|
+
GOLD_A = ManimColor("#F7C797")
|
|
178
|
+
GOLD_B = ManimColor("#F9B775")
|
|
179
|
+
GOLD_C = ManimColor("#F0AC5F")
|
|
180
|
+
GOLD_D = ManimColor("#E1A158")
|
|
181
|
+
GOLD_E = ManimColor("#C78D46")
|
|
182
|
+
GOLD = ManimColor("#F0AC5F")
|
|
183
|
+
RED_A = ManimColor("#F7A1A3")
|
|
184
|
+
RED_B = ManimColor("#FF8080")
|
|
185
|
+
RED_C = ManimColor("#FC6255")
|
|
186
|
+
RED_D = ManimColor("#E65A4C")
|
|
187
|
+
RED_E = ManimColor("#CF5044")
|
|
188
|
+
PURE_RED = ManimColor("#FF0000")
|
|
189
|
+
RED = ManimColor("#FC6255")
|
|
190
|
+
MAROON_A = ManimColor("#ECABC1")
|
|
191
|
+
MAROON_B = ManimColor("#EC92AB")
|
|
192
|
+
MAROON_C = ManimColor("#C55F73")
|
|
193
|
+
MAROON_D = ManimColor("#A24D61")
|
|
194
|
+
MAROON_E = ManimColor("#94424F")
|
|
195
|
+
MAROON = ManimColor("#C55F73")
|
|
196
|
+
PURPLE_A = ManimColor("#CAA3E8")
|
|
197
|
+
PURPLE_B = ManimColor("#B189C6")
|
|
198
|
+
PURPLE_C = ManimColor("#9A72AC")
|
|
199
|
+
PURPLE_D = ManimColor("#715582")
|
|
200
|
+
PURPLE_E = ManimColor("#644172")
|
|
201
|
+
PURPLE = ManimColor("#9A72AC")
|
|
202
|
+
PINK = ManimColor("#D147BD")
|
|
203
|
+
LIGHT_PINK = ManimColor("#DC75CD")
|
|
204
|
+
ORANGE = ManimColor("#FF862F")
|
|
205
|
+
LIGHT_BROWN = ManimColor("#CD853F")
|
|
206
|
+
DARK_BROWN = ManimColor("#8B4513")
|
|
207
|
+
GRAY_BROWN = ManimColor("#736357")
|
|
208
|
+
GREY_BROWN = ManimColor("#736357")
|
|
209
|
+
|
|
210
|
+
# Colors used for Manim Community's logo and banner
|
|
211
|
+
|
|
212
|
+
LOGO_WHITE = ManimColor("#ECE7E2")
|
|
213
|
+
LOGO_GREEN = ManimColor("#87C2A5")
|
|
214
|
+
LOGO_BLUE = ManimColor("#525893")
|
|
215
|
+
LOGO_RED = ManimColor("#E07A5F")
|
|
216
|
+
LOGO_BLACK = ManimColor("#343434")
|
|
217
|
+
|
|
218
|
+
_all_manim_colors: List[ManimColor] = [
|
|
219
|
+
x for x in globals().values() if isinstance(x, ManimColor)
|
|
220
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
|
|
5
|
+
from docutils import nodes
|
|
6
|
+
from docutils.parsers.rst import Directive
|
|
7
|
+
from sphinx.application import Sphinx
|
|
8
|
+
|
|
9
|
+
from manim import ManimColor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def setup(app: Sphinx) -> None:
|
|
13
|
+
app.add_directive("automanimcolormodule", ManimColorModuleDocumenter)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ManimColorModuleDocumenter(Directive):
|
|
17
|
+
objtype = "automanimcolormodule"
|
|
18
|
+
required_arguments = 1
|
|
19
|
+
has_content = True
|
|
20
|
+
|
|
21
|
+
def add_directive_header(self, sig: str) -> None:
|
|
22
|
+
super().add_directive_header(sig)
|
|
23
|
+
|
|
24
|
+
def run(
|
|
25
|
+
self,
|
|
26
|
+
) -> None:
|
|
27
|
+
module_name = self.arguments[0]
|
|
28
|
+
try:
|
|
29
|
+
import importlib
|
|
30
|
+
|
|
31
|
+
module = importlib.import_module(module_name)
|
|
32
|
+
except ImportError:
|
|
33
|
+
return [
|
|
34
|
+
nodes.error(
|
|
35
|
+
None,
|
|
36
|
+
nodes.paragraph(text="Failed to import module '%s'" % module_name),
|
|
37
|
+
)
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
# Number of Colors displayed in one row
|
|
41
|
+
num_color_cols = 2
|
|
42
|
+
table = nodes.table(align="center")
|
|
43
|
+
|
|
44
|
+
tgroup = nodes.tgroup(cols=num_color_cols * 2)
|
|
45
|
+
table += tgroup
|
|
46
|
+
for _ in range(num_color_cols * 2):
|
|
47
|
+
tgroup += nodes.colspec(colwidth=1)
|
|
48
|
+
|
|
49
|
+
# Create header rows for the table
|
|
50
|
+
thead = nodes.thead()
|
|
51
|
+
row = nodes.row()
|
|
52
|
+
for _ in range(num_color_cols):
|
|
53
|
+
col1 = nodes.paragraph(text="Color Name")
|
|
54
|
+
col2 = nodes.paragraph(text="RGB Hex Code")
|
|
55
|
+
row += nodes.entry("", col1)
|
|
56
|
+
row += nodes.entry("", col2)
|
|
57
|
+
thead += row
|
|
58
|
+
tgroup += thead
|
|
59
|
+
|
|
60
|
+
color_elements = []
|
|
61
|
+
for member_name, member_obj in inspect.getmembers(module):
|
|
62
|
+
if isinstance(member_obj, ManimColor):
|
|
63
|
+
r, g, b = member_obj.to_rgb()
|
|
64
|
+
luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
65
|
+
|
|
66
|
+
# Choose the font color based on the background luminance
|
|
67
|
+
if luminance > 0.5:
|
|
68
|
+
font_color = "black"
|
|
69
|
+
else:
|
|
70
|
+
font_color = "white"
|
|
71
|
+
|
|
72
|
+
color_elements.append((member_name, member_obj.to_hex(), font_color))
|
|
73
|
+
|
|
74
|
+
tbody = nodes.tbody()
|
|
75
|
+
|
|
76
|
+
for base_i in range(0, len(color_elements), num_color_cols):
|
|
77
|
+
row = nodes.row()
|
|
78
|
+
for member_name, hex_code, font_color in color_elements[
|
|
79
|
+
base_i : base_i + num_color_cols
|
|
80
|
+
]:
|
|
81
|
+
col1 = nodes.literal(text=member_name)
|
|
82
|
+
col2 = nodes.raw(
|
|
83
|
+
"",
|
|
84
|
+
f'<div style="background-color:{hex_code};padding: 0.25rem 0;border-radius:8px;margin: 0.5rem 0.2rem"><code style="color:{font_color};">{hex_code}</code></div>',
|
|
85
|
+
format="html",
|
|
86
|
+
)
|
|
87
|
+
row += nodes.entry("", col1)
|
|
88
|
+
row += nodes.entry("", col2)
|
|
89
|
+
tbody += row
|
|
90
|
+
tgroup += tbody
|
|
91
|
+
|
|
92
|
+
return [table]
|
|
@@ -26,7 +26,7 @@ render scenes that are defined within doctests, for example::
|
|
|
26
26
|
>>> from manim import Create, Dot, RED, Scene
|
|
27
27
|
>>> dot = Dot(color=RED)
|
|
28
28
|
>>> dot.color
|
|
29
|
-
|
|
29
|
+
ManimColor('#FC6255')
|
|
30
30
|
>>> class DirectiveDoctestExample(Scene):
|
|
31
31
|
... def construct(self):
|
|
32
32
|
... self.play(Create(dot))
|
|
@@ -85,6 +85,7 @@ import os
|
|
|
85
85
|
import re
|
|
86
86
|
import shutil
|
|
87
87
|
import sys
|
|
88
|
+
import textwrap
|
|
88
89
|
from pathlib import Path
|
|
89
90
|
from timeit import timeit
|
|
90
91
|
|
|
@@ -94,6 +95,7 @@ from docutils.parsers.rst import Directive, directives # type: ignore
|
|
|
94
95
|
from docutils.statemachine import StringList
|
|
95
96
|
|
|
96
97
|
from manim import QUALITIES
|
|
98
|
+
from manim import __version__ as manim_version
|
|
97
99
|
|
|
98
100
|
classnamedict = {}
|
|
99
101
|
|
|
@@ -168,16 +170,25 @@ class ManimDirective(Directive):
|
|
|
168
170
|
or self.state.document.settings.env.app.builder.name == "gettext"
|
|
169
171
|
)
|
|
170
172
|
if should_skip:
|
|
173
|
+
clsname = self.arguments[0]
|
|
171
174
|
node = SkipManimNode()
|
|
172
175
|
self.state.nested_parse(
|
|
173
176
|
StringList(
|
|
174
177
|
[
|
|
175
|
-
f"Placeholder block for ``{
|
|
178
|
+
f"Placeholder block for ``{clsname}``.",
|
|
176
179
|
"",
|
|
177
180
|
".. code-block:: python",
|
|
178
181
|
"",
|
|
179
182
|
]
|
|
180
183
|
+ [" " + line for line in self.content]
|
|
184
|
+
+ [
|
|
185
|
+
"",
|
|
186
|
+
".. raw:: html",
|
|
187
|
+
"",
|
|
188
|
+
f' <pre data-manim-binder data-manim-classname="{clsname}">',
|
|
189
|
+
]
|
|
190
|
+
+ [" " + line for line in self.content]
|
|
191
|
+
+ [" </pre>"],
|
|
181
192
|
),
|
|
182
193
|
self.content_offset,
|
|
183
194
|
node,
|
|
@@ -235,6 +246,13 @@ class ManimDirective(Directive):
|
|
|
235
246
|
"",
|
|
236
247
|
" from manim import *\n",
|
|
237
248
|
*(" " + line for line in self.content),
|
|
249
|
+
"",
|
|
250
|
+
".. raw:: html",
|
|
251
|
+
"",
|
|
252
|
+
f' <pre data-manim-binder data-manim-classname="{clsname}">',
|
|
253
|
+
*(" " + line for line in self.content),
|
|
254
|
+
"",
|
|
255
|
+
" </pre>",
|
|
238
256
|
]
|
|
239
257
|
source_block = "\n".join(source_block)
|
|
240
258
|
|
|
@@ -272,10 +290,13 @@ class ManimDirective(Directive):
|
|
|
272
290
|
f"{clsname}().render()",
|
|
273
291
|
]
|
|
274
292
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
293
|
+
try:
|
|
294
|
+
with tempconfig(example_config):
|
|
295
|
+
run_time = timeit(lambda: exec("\n".join(code), globals()), number=1)
|
|
296
|
+
video_dir = config.get_dir("video_dir")
|
|
297
|
+
images_dir = config.get_dir("images_dir")
|
|
298
|
+
except Exception as e:
|
|
299
|
+
raise RuntimeError(f"Error while rendering example {clsname}") from e
|
|
279
300
|
|
|
280
301
|
_write_rendering_stats(
|
|
281
302
|
clsname,
|
|
@@ -340,6 +361,9 @@ def _log_rendering_times(*args):
|
|
|
340
361
|
|
|
341
362
|
print("\nRendering Summary\n-----------------\n")
|
|
342
363
|
|
|
364
|
+
# filter out empty lists caused by csv reader
|
|
365
|
+
data = [row for row in data if row]
|
|
366
|
+
|
|
343
367
|
max_file_length = max(len(row[0]) for row in data)
|
|
344
368
|
for key, group in it.groupby(data, key=lambda row: row[0]):
|
|
345
369
|
key = key.ljust(max_file_length + 1, ".")
|
|
@@ -374,6 +398,16 @@ def setup(app):
|
|
|
374
398
|
app.connect("builder-inited", _delete_rendering_times)
|
|
375
399
|
app.connect("build-finished", _log_rendering_times)
|
|
376
400
|
|
|
401
|
+
app.add_js_file("manim-binder.min.js")
|
|
402
|
+
app.add_js_file(
|
|
403
|
+
None,
|
|
404
|
+
body=textwrap.dedent(
|
|
405
|
+
f"""\
|
|
406
|
+
window.initManimBinder({{branch: "v{manim_version}"}})
|
|
407
|
+
"""
|
|
408
|
+
).strip(),
|
|
409
|
+
)
|
|
410
|
+
|
|
377
411
|
metadata = {"parallel_read_safe": False, "parallel_write_safe": True}
|
|
378
412
|
return metadata
|
|
379
413
|
|
manim/utils/file_ops.py
CHANGED
|
@@ -183,7 +183,7 @@ def modify_atime(file_path: str) -> None:
|
|
|
183
183
|
file_path
|
|
184
184
|
The path of the file.
|
|
185
185
|
"""
|
|
186
|
-
os.utime(file_path, times=(time.time(),
|
|
186
|
+
os.utime(file_path, times=(time.time(), Path(file_path).stat().st_mtime))
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
def open_file(file_path, in_browser=False):
|
manim/utils/hashing.py
CHANGED
|
@@ -207,7 +207,7 @@ class _CustomEncoder(json.JSONEncoder):
|
|
|
207
207
|
del cvardict[i]
|
|
208
208
|
try:
|
|
209
209
|
code = inspect.getsource(obj)
|
|
210
|
-
except OSError:
|
|
210
|
+
except (OSError, TypeError):
|
|
211
211
|
# This happens when rendering videos included in the documentation
|
|
212
212
|
# within doctests and should be replaced by a solution avoiding
|
|
213
213
|
# hash collision (due to the same, empty, code strings) at some point.
|
manim/utils/iterables.py
CHANGED
|
@@ -65,7 +65,7 @@ def all_elements_are_instances(iterable: Iterable, Class) -> bool:
|
|
|
65
65
|
"""Returns ``True`` if all elements of iterable are instances of Class.
|
|
66
66
|
False otherwise.
|
|
67
67
|
"""
|
|
68
|
-
return all(
|
|
68
|
+
return all(isinstance(e, Class) for e in iterable)
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def batch_by_property(
|
manim/utils/rate_functions.py
CHANGED
|
@@ -89,6 +89,9 @@ from __future__ import annotations
|
|
|
89
89
|
__all__ = [
|
|
90
90
|
"linear",
|
|
91
91
|
"smooth",
|
|
92
|
+
"smoothstep",
|
|
93
|
+
"smootherstep",
|
|
94
|
+
"smoothererstep",
|
|
92
95
|
"rush_into",
|
|
93
96
|
"rush_from",
|
|
94
97
|
"slow_into",
|
|
@@ -155,6 +158,36 @@ def smooth(t: float, inflection: float = 10.0) -> float:
|
|
|
155
158
|
)
|
|
156
159
|
|
|
157
160
|
|
|
161
|
+
def smoothstep(t: float) -> float:
|
|
162
|
+
"""Implementation of the 1st order SmoothStep sigmoid function.
|
|
163
|
+
The 1st derivative (speed) is zero at the endpoints.
|
|
164
|
+
https://en.wikipedia.org/wiki/Smoothstep
|
|
165
|
+
"""
|
|
166
|
+
return 0 if t <= 0 else 3 * t**2 - 2 * t**3 if t < 1 else 1
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def smootherstep(t: float) -> float:
|
|
170
|
+
"""Implementation of the 2nd order SmoothStep sigmoid function.
|
|
171
|
+
The 1st and 2nd derivatives (speed and acceleration) are zero at the endpoints.
|
|
172
|
+
https://en.wikipedia.org/wiki/Smoothstep
|
|
173
|
+
"""
|
|
174
|
+
return 0 if t <= 0 else 6 * t**5 - 15 * t**4 + 10 * t**3 if t < 1 else 1
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def smoothererstep(t: float) -> float:
|
|
178
|
+
"""Implementation of the 3rd order SmoothStep sigmoid function.
|
|
179
|
+
The 1st, 2nd and 3rd derivatives (speed, acceleration and jerk) are zero at the endpoints.
|
|
180
|
+
https://en.wikipedia.org/wiki/Smoothstep
|
|
181
|
+
"""
|
|
182
|
+
return (
|
|
183
|
+
0
|
|
184
|
+
if t <= 0
|
|
185
|
+
else 35 * t**4 - 84 * t**5 + 70 * t**6 - 20 * t**7
|
|
186
|
+
if t < 1
|
|
187
|
+
else 1
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
158
191
|
@unit_interval
|
|
159
192
|
def rush_into(t: float, inflection: float = 10.0) -> float:
|
|
160
193
|
return 2 * smooth(t / 2.0, inflection)
|
manim/utils/simple_functions.py
CHANGED
|
@@ -6,7 +6,6 @@ __all__ = [
|
|
|
6
6
|
"binary_search",
|
|
7
7
|
"choose",
|
|
8
8
|
"clip",
|
|
9
|
-
"get_parameters",
|
|
10
9
|
"sigmoid",
|
|
11
10
|
]
|
|
12
11
|
|
|
@@ -117,23 +116,6 @@ def clip(a, min_a, max_a):
|
|
|
117
116
|
return a
|
|
118
117
|
|
|
119
118
|
|
|
120
|
-
def get_parameters(function: Callable) -> MappingProxyType[str, inspect.Parameter]:
|
|
121
|
-
"""Return the parameters of ``function`` as an ordered mapping of parameters'
|
|
122
|
-
names to their corresponding ``Parameter`` objects.
|
|
123
|
-
|
|
124
|
-
Examples
|
|
125
|
-
--------
|
|
126
|
-
::
|
|
127
|
-
|
|
128
|
-
>>> get_parameters(get_parameters)
|
|
129
|
-
mappingproxy(OrderedDict([('function', <Parameter "function: 'Callable'">)]))
|
|
130
|
-
|
|
131
|
-
>>> tuple(get_parameters(choose))
|
|
132
|
-
('n', 'k')
|
|
133
|
-
"""
|
|
134
|
-
return inspect.signature(function).parameters
|
|
135
|
-
|
|
136
|
-
|
|
137
119
|
def sigmoid(x: float) -> float:
|
|
138
120
|
r"""Returns the output of the logistic function.
|
|
139
121
|
|
manim/utils/space_ops.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from manim.typing import Point3D_Array, Vector
|
|
6
|
+
|
|
5
7
|
__all__ = [
|
|
6
8
|
"quaternion_mult",
|
|
7
9
|
"quaternion_from_angle_axis",
|
|
@@ -37,14 +39,12 @@ __all__ = [
|
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
import itertools as it
|
|
40
|
-
import math
|
|
41
42
|
from typing import Sequence
|
|
42
43
|
|
|
43
44
|
import numpy as np
|
|
44
45
|
from mapbox_earcut import triangulate_float32 as earcut
|
|
45
46
|
from scipy.spatial.transform import Rotation
|
|
46
47
|
|
|
47
|
-
from .. import config
|
|
48
48
|
from ..constants import DOWN, OUT, PI, RIGHT, TAU, UP, RendererType
|
|
49
49
|
from ..utils.iterables import adjacent_pairs
|
|
50
50
|
|
|
@@ -69,34 +69,19 @@ def quaternion_mult(
|
|
|
69
69
|
Union[np.ndarray, List[Union[float, np.ndarray]]]
|
|
70
70
|
Returns a list of product of two quaternions.
|
|
71
71
|
"""
|
|
72
|
-
if
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return result
|
|
86
|
-
elif config.renderer == RendererType.CAIRO:
|
|
87
|
-
q1 = quats[0]
|
|
88
|
-
q2 = quats[1]
|
|
89
|
-
|
|
90
|
-
w1, x1, y1, z1 = q1
|
|
91
|
-
w2, x2, y2, z2 = q2
|
|
92
|
-
return np.array(
|
|
93
|
-
[
|
|
94
|
-
w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
|
|
95
|
-
w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
|
|
96
|
-
w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2,
|
|
97
|
-
w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2,
|
|
98
|
-
],
|
|
99
|
-
)
|
|
72
|
+
if len(quats) == 0:
|
|
73
|
+
return [1, 0, 0, 0]
|
|
74
|
+
result = quats[0]
|
|
75
|
+
for next_quat in quats[1:]:
|
|
76
|
+
w1, x1, y1, z1 = result
|
|
77
|
+
w2, x2, y2, z2 = next_quat
|
|
78
|
+
result = [
|
|
79
|
+
w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
|
|
80
|
+
w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
|
|
81
|
+
w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2,
|
|
82
|
+
w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2,
|
|
83
|
+
]
|
|
84
|
+
return result
|
|
100
85
|
|
|
101
86
|
|
|
102
87
|
def quaternion_from_angle_axis(
|
|
@@ -122,12 +107,9 @@ def quaternion_from_angle_axis(
|
|
|
122
107
|
List[float]
|
|
123
108
|
Gives back a quaternion from the angle and axis
|
|
124
109
|
"""
|
|
125
|
-
if
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return [math.cos(angle / 2), *(math.sin(angle / 2) * axis)]
|
|
129
|
-
elif config.renderer == RendererType.CAIRO:
|
|
130
|
-
return np.append(np.cos(angle / 2), np.sin(angle / 2) * normalize(axis))
|
|
110
|
+
if not axis_normalized:
|
|
111
|
+
axis = normalize(axis)
|
|
112
|
+
return [np.cos(angle / 2), *(np.sin(angle / 2) * axis)]
|
|
131
113
|
|
|
132
114
|
|
|
133
115
|
def angle_axis_from_quaternion(quaternion: Sequence[float]) -> Sequence[float]:
|
|
@@ -275,7 +257,7 @@ def rotation_about_z(angle: float) -> np.ndarray:
|
|
|
275
257
|
np.ndarray
|
|
276
258
|
Gives back the rotated matrix.
|
|
277
259
|
"""
|
|
278
|
-
c, s =
|
|
260
|
+
c, s = np.cos(angle), np.sin(angle)
|
|
279
261
|
return np.array(
|
|
280
262
|
[
|
|
281
263
|
[c, -s, 0],
|
|
@@ -559,10 +541,10 @@ def line_intersection(
|
|
|
559
541
|
|
|
560
542
|
|
|
561
543
|
def find_intersection(
|
|
562
|
-
p0s: Sequence[np.ndarray],
|
|
563
|
-
v0s: Sequence[np.ndarray],
|
|
564
|
-
p1s: Sequence[np.ndarray],
|
|
565
|
-
v1s: Sequence[np.ndarray],
|
|
544
|
+
p0s: Sequence[np.ndarray] | Point3D_Array,
|
|
545
|
+
v0s: Sequence[np.ndarray] | Point3D_Array,
|
|
546
|
+
p1s: Sequence[np.ndarray] | Point3D_Array,
|
|
547
|
+
v1s: Sequence[np.ndarray] | Point3D_Array,
|
|
566
548
|
threshold: float = 1e-5,
|
|
567
549
|
) -> Sequence[np.ndarray]:
|
|
568
550
|
"""
|
|
@@ -640,7 +622,38 @@ def shoelace_direction(x_y: np.ndarray) -> str:
|
|
|
640
622
|
return "CW" if area > 0 else "CCW"
|
|
641
623
|
|
|
642
624
|
|
|
643
|
-
def cross2d(
|
|
625
|
+
def cross2d(
|
|
626
|
+
a: Sequence[Vector] | Vector, b: Sequence[Vector] | Vector
|
|
627
|
+
) -> Sequence[float] | float:
|
|
628
|
+
"""Compute the determinant(s) of the passed
|
|
629
|
+
vector (sequences).
|
|
630
|
+
|
|
631
|
+
Parameters
|
|
632
|
+
----------
|
|
633
|
+
a
|
|
634
|
+
A vector or a sequence of vectors.
|
|
635
|
+
b
|
|
636
|
+
A vector or a sequence of vectors.
|
|
637
|
+
|
|
638
|
+
Returns
|
|
639
|
+
-------
|
|
640
|
+
Sequence[float] | float
|
|
641
|
+
The determinant or sequence of determinants
|
|
642
|
+
of the first two components of the specified
|
|
643
|
+
vectors.
|
|
644
|
+
|
|
645
|
+
Examples
|
|
646
|
+
--------
|
|
647
|
+
.. code-block:: pycon
|
|
648
|
+
|
|
649
|
+
>>> cross2d(np.array([1, 2]), np.array([3, 4]))
|
|
650
|
+
-2
|
|
651
|
+
>>> cross2d(
|
|
652
|
+
... np.array([[1, 2, 0], [1, 0, 0]]),
|
|
653
|
+
... np.array([[3, 4, 0], [0, 1, 0]]),
|
|
654
|
+
... )
|
|
655
|
+
array([-2, 1])
|
|
656
|
+
"""
|
|
644
657
|
if len(a.shape) == 2:
|
|
645
658
|
return a[:, 0] * b[:, 1] - a[:, 1] * b[:, 0]
|
|
646
659
|
else:
|