manim 0.17.3__py3-none-any.whl → 0.18.0.post0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of manim might be problematic. Click here for more details.

Files changed (84) hide show
  1. manim/__init__.py +1 -0
  2. manim/__main__.py +2 -0
  3. manim/_config/__init__.py +0 -1
  4. manim/_config/logger_utils.py +1 -0
  5. manim/_config/utils.py +14 -5
  6. manim/animation/changing.py +9 -5
  7. manim/animation/creation.py +8 -3
  8. manim/animation/indication.py +4 -4
  9. manim/animation/speedmodifier.py +2 -4
  10. manim/animation/updaters/mobject_update_utils.py +134 -16
  11. manim/camera/camera.py +31 -17
  12. manim/cli/checkhealth/__init__.py +0 -0
  13. manim/cli/checkhealth/checks.py +173 -0
  14. manim/cli/checkhealth/commands.py +81 -0
  15. manim/cli/render/global_options.py +6 -0
  16. manim/constants.py +58 -54
  17. manim/mobject/geometry/__init__.py +1 -0
  18. manim/mobject/geometry/arc.py +126 -91
  19. manim/mobject/geometry/boolean_ops.py +6 -10
  20. manim/mobject/geometry/labeled.py +155 -0
  21. manim/mobject/geometry/line.py +66 -50
  22. manim/mobject/geometry/polygram.py +23 -15
  23. manim/mobject/geometry/shape_matchers.py +24 -15
  24. manim/mobject/geometry/tips.py +62 -40
  25. manim/mobject/graph.py +3 -4
  26. manim/mobject/graphing/coordinate_systems.py +190 -139
  27. manim/mobject/graphing/number_line.py +5 -2
  28. manim/mobject/graphing/probability.py +4 -3
  29. manim/mobject/graphing/scale.py +7 -7
  30. manim/mobject/logo.py +108 -22
  31. manim/mobject/matrix.py +33 -37
  32. manim/mobject/mobject.py +327 -260
  33. manim/mobject/opengl/opengl_image_mobject.py +1 -1
  34. manim/mobject/opengl/opengl_mobject.py +18 -12
  35. manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
  36. manim/mobject/opengl/opengl_surface.py +1 -1
  37. manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
  38. manim/mobject/svg/brace.py +3 -1
  39. manim/mobject/svg/svg_mobject.py +9 -11
  40. manim/mobject/table.py +50 -54
  41. manim/mobject/text/numbers.py +48 -6
  42. manim/mobject/text/tex_mobject.py +8 -12
  43. manim/mobject/text/text_mobject.py +32 -24
  44. manim/mobject/three_d/three_d_utils.py +13 -8
  45. manim/mobject/three_d/three_dimensions.py +61 -43
  46. manim/mobject/types/image_mobject.py +5 -4
  47. manim/mobject/types/point_cloud_mobject.py +8 -6
  48. manim/mobject/types/vectorized_mobject.py +385 -258
  49. manim/mobject/vector_field.py +19 -11
  50. manim/plugins/import_plugins.py +1 -1
  51. manim/plugins/plugins_flags.py +1 -6
  52. manim/renderer/shader.py +2 -2
  53. manim/scene/scene.py +15 -7
  54. manim/scene/scene_file_writer.py +1 -2
  55. manim/scene/three_d_scene.py +1 -1
  56. manim/scene/vector_space_scene.py +17 -7
  57. manim/typing.py +133 -0
  58. manim/utils/bezier.py +267 -83
  59. manim/utils/color/AS2700.py +234 -0
  60. manim/utils/color/BS381.py +315 -0
  61. manim/utils/color/X11.py +530 -0
  62. manim/utils/color/XKCD.py +949 -0
  63. manim/utils/color/__init__.py +58 -0
  64. manim/utils/color/core.py +1036 -0
  65. manim/utils/color/manim_colors.py +220 -0
  66. manim/utils/docbuild/autocolor_directive.py +92 -0
  67. manim/utils/docbuild/manim_directive.py +40 -6
  68. manim/utils/file_ops.py +1 -1
  69. manim/utils/hashing.py +1 -1
  70. manim/utils/iterables.py +1 -1
  71. manim/utils/rate_functions.py +33 -0
  72. manim/utils/simple_functions.py +0 -18
  73. manim/utils/space_ops.py +55 -42
  74. manim/utils/testing/frames_comparison.py +9 -0
  75. manim/utils/tex.py +2 -0
  76. manim/utils/tex_file_writing.py +29 -2
  77. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
  78. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
  79. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
  80. manim/communitycolors.py +0 -9
  81. manim/utils/color.py +0 -552
  82. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
  83. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
  84. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
@@ -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
- <Color #fc6255>
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 ``{self.arguments[0]}``.",
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
- with tempconfig(example_config):
276
- run_time = timeit(lambda: exec("\n".join(code), globals()), number=1)
277
- video_dir = config.get_dir("video_dir")
278
- images_dir = config.get_dir("images_dir")
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(), os.path.getmtime(file_path)))
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([isinstance(e, Class) for e in iterable])
68
+ return all(isinstance(e, Class) for e in iterable)
69
69
 
70
70
 
71
71
  def batch_by_property(
@@ -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)
@@ -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 config.renderer == RendererType.OPENGL:
73
- if len(quats) == 0:
74
- return [1, 0, 0, 0]
75
- result = quats[0]
76
- for next_quat in quats[1:]:
77
- w1, x1, y1, z1 = result
78
- w2, x2, y2, z2 = next_quat
79
- result = [
80
- w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
81
- w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
82
- w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2,
83
- w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2,
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 config.renderer == RendererType.OPENGL:
126
- if not axis_normalized:
127
- axis = normalize(axis)
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 = math.cos(angle), math.sin(angle)
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(a, b):
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: