manim 0.18.0.post0__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/__init__.py +3 -6
- manim/__main__.py +61 -20
- manim/_config/__init__.py +6 -3
- manim/_config/cli_colors.py +16 -8
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +14 -8
- manim/_config/utils.py +651 -472
- manim/animation/animation.py +152 -5
- manim/animation/composition.py +80 -39
- manim/animation/creation.py +196 -14
- manim/animation/fading.py +5 -9
- manim/animation/indication.py +103 -47
- manim/animation/movement.py +22 -5
- manim/animation/rotation.py +3 -2
- manim/animation/specialized.py +4 -6
- manim/animation/speedmodifier.py +10 -5
- manim/animation/transform.py +4 -5
- manim/animation/transform_matching_parts.py +1 -1
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +15 -6
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +70 -44
- manim/cli/checkhealth/checks.py +93 -75
- manim/cli/checkhealth/commands.py +14 -5
- manim/cli/default_group.py +157 -25
- manim/cli/init/commands.py +32 -24
- 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 +51 -15
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +97 -32
- manim/constants.py +65 -19
- manim/gui/gui.py +2 -0
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +112 -78
- manim/mobject/geometry/boolean_ops.py +32 -25
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +132 -64
- manim/mobject/geometry/polygram.py +126 -30
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +38 -29
- manim/mobject/graph.py +414 -133
- manim/mobject/graphing/coordinate_systems.py +126 -64
- manim/mobject/graphing/functions.py +25 -15
- manim/mobject/graphing/number_line.py +24 -10
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +314 -165
- manim/mobject/opengl/opengl_compatibility.py +2 -0
- manim/mobject/opengl/opengl_geometry.py +30 -9
- manim/mobject/opengl/opengl_image_mobject.py +2 -0
- manim/mobject/opengl/opengl_mobject.py +509 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
- manim/mobject/opengl/opengl_surface.py +3 -2
- manim/mobject/opengl/opengl_three_dimensions.py +2 -0
- manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
- manim/mobject/svg/brace.py +63 -13
- manim/mobject/svg/svg_mobject.py +4 -3
- manim/mobject/table.py +11 -13
- manim/mobject/text/code_mobject.py +186 -548
- manim/mobject/text/numbers.py +9 -7
- manim/mobject/text/tex_mobject.py +23 -14
- manim/mobject/text/text_mobject.py +70 -24
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_d_utils.py +4 -4
- manim/mobject/three_d/three_dimensions.py +62 -34
- manim/mobject/types/image_mobject.py +42 -24
- manim/mobject/types/point_cloud_mobject.py +105 -67
- manim/mobject/types/vectorized_mobject.py +496 -228
- manim/mobject/value_tracker.py +5 -4
- manim/mobject/vector_field.py +5 -5
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +14 -8
- manim/renderer/cairo_renderer.py +20 -10
- manim/renderer/opengl_renderer.py +21 -23
- manim/renderer/opengl_renderer_window.py +2 -0
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +5 -2
- manim/renderer/vectorized_mobject_rendering.py +5 -0
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +90 -43
- manim/scene/scene_file_writer.py +316 -165
- manim/scene/section.py +17 -15
- manim/scene/three_d_scene.py +13 -21
- manim/scene/vector_space_scene.py +22 -9
- manim/typing.py +830 -70
- manim/utils/bezier.py +1667 -399
- manim/utils/caching.py +13 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +3 -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 +3 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +844 -309
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +90 -40
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +234 -0
- manim/utils/docbuild/autocolor_directive.py +21 -17
- manim/utils/docbuild/manim_directive.py +50 -35
- 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 +26 -16
- manim/utils/hashing.py +9 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +14 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +57 -19
- manim/utils/opengl.py +83 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +21 -23
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +74 -39
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +125 -69
- 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 +33 -18
- manim/utils/testing/frames_comparison.py +27 -19
- manim/utils/tex.py +127 -197
- manim/utils/tex_file_writing.py +47 -45
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim/cli/new/__init__.py +0 -0
- manim/cli/new/group.py +0 -189
- manim/plugins/import_plugins.py +0 -43
- manim-0.18.0.post0.dist-info/RECORD +0 -217
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Mobjects that represent coordinate systems."""
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
__all__ = [
|
|
@@ -14,7 +13,8 @@ __all__ = [
|
|
|
14
13
|
|
|
15
14
|
import fractions as fr
|
|
16
15
|
import numbers
|
|
17
|
-
from
|
|
16
|
+
from collections.abc import Iterable, Sequence
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Callable, TypeVar, overload
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
from typing_extensions import Self
|
|
@@ -27,6 +27,7 @@ from manim.mobject.geometry.polygram import Polygon, Rectangle, RegularPolygon
|
|
|
27
27
|
from manim.mobject.graphing.functions import ImplicitFunction, ParametricFunction
|
|
28
28
|
from manim.mobject.graphing.number_line import NumberLine
|
|
29
29
|
from manim.mobject.graphing.scale import LinearBase
|
|
30
|
+
from manim.mobject.mobject import Mobject
|
|
30
31
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
31
32
|
from manim.mobject.opengl.opengl_surface import OpenGLSurface
|
|
32
33
|
from manim.mobject.text.tex_mobject import MathTex
|
|
@@ -47,6 +48,7 @@ from manim.utils.color import (
|
|
|
47
48
|
ManimColor,
|
|
48
49
|
ParsableManimColor,
|
|
49
50
|
color_gradient,
|
|
51
|
+
interpolate_color,
|
|
50
52
|
invert_color,
|
|
51
53
|
)
|
|
52
54
|
from manim.utils.config_ops import merge_dicts_recursively, update_dict_recursively
|
|
@@ -55,7 +57,14 @@ from manim.utils.space_ops import angle_of_vector
|
|
|
55
57
|
|
|
56
58
|
if TYPE_CHECKING:
|
|
57
59
|
from manim.mobject.mobject import Mobject
|
|
58
|
-
from manim.typing import
|
|
60
|
+
from manim.typing import (
|
|
61
|
+
ManimFloat,
|
|
62
|
+
Point2D,
|
|
63
|
+
Point2DLike,
|
|
64
|
+
Point3D,
|
|
65
|
+
Point3DLike,
|
|
66
|
+
Vector3D,
|
|
67
|
+
)
|
|
59
68
|
|
|
60
69
|
LineType = TypeVar("LineType", bound=Line)
|
|
61
70
|
|
|
@@ -96,10 +105,10 @@ class CoordinateSystem:
|
|
|
96
105
|
)
|
|
97
106
|
|
|
98
107
|
# Extra lines and labels for point (1,1)
|
|
99
|
-
graphs += grid.get_horizontal_line(grid
|
|
100
|
-
graphs += grid.get_vertical_line(grid
|
|
101
|
-
graphs += Dot(point=grid
|
|
102
|
-
graphs += Tex("(1,1)").scale(0.75).next_to(grid
|
|
108
|
+
graphs += grid.get_horizontal_line(grid @ (1, 1, 0), color=BLUE)
|
|
109
|
+
graphs += grid.get_vertical_line(grid @ (1, 1, 0), color=BLUE)
|
|
110
|
+
graphs += Dot(point=grid @ (1, 1, 0), color=YELLOW)
|
|
111
|
+
graphs += Tex("(1,1)").scale(0.75).next_to(grid @ (1, 1, 0))
|
|
103
112
|
title = Title(
|
|
104
113
|
# spaces between braces to prevent SyntaxError
|
|
105
114
|
r"Graphs of $y=x^{ {1}\over{n} }$ and $y=x^n (n=1,2,3,...,20)$",
|
|
@@ -145,10 +154,10 @@ class CoordinateSystem:
|
|
|
145
154
|
self.y_length = y_length
|
|
146
155
|
self.num_sampled_graph_points_per_tick = 10
|
|
147
156
|
|
|
148
|
-
def coords_to_point(self, *coords:
|
|
157
|
+
def coords_to_point(self, *coords: ManimFloat):
|
|
149
158
|
raise NotImplementedError()
|
|
150
159
|
|
|
151
|
-
def point_to_coords(self, point:
|
|
160
|
+
def point_to_coords(self, point: Point3DLike):
|
|
152
161
|
raise NotImplementedError()
|
|
153
162
|
|
|
154
163
|
def polar_to_point(self, radius: float, azimuth: float) -> Point2D:
|
|
@@ -182,7 +191,7 @@ class CoordinateSystem:
|
|
|
182
191
|
"""
|
|
183
192
|
return self.coords_to_point(radius * np.cos(azimuth), radius * np.sin(azimuth))
|
|
184
193
|
|
|
185
|
-
def point_to_polar(self, point:
|
|
194
|
+
def point_to_polar(self, point: Point2DLike) -> Point2D:
|
|
186
195
|
r"""Gets polar coordinates from a point.
|
|
187
196
|
|
|
188
197
|
Parameters
|
|
@@ -204,7 +213,7 @@ class CoordinateSystem:
|
|
|
204
213
|
"""Abbreviation for :meth:`coords_to_point`"""
|
|
205
214
|
return self.coords_to_point(*coords)
|
|
206
215
|
|
|
207
|
-
def p2c(self, point:
|
|
216
|
+
def p2c(self, point: Point3DLike):
|
|
208
217
|
"""Abbreviation for :meth:`point_to_coords`"""
|
|
209
218
|
return self.point_to_coords(point)
|
|
210
219
|
|
|
@@ -305,7 +314,7 @@ class CoordinateSystem:
|
|
|
305
314
|
label
|
|
306
315
|
The label. Defaults to :class:`~.MathTex` for ``str`` and ``float`` inputs.
|
|
307
316
|
edge
|
|
308
|
-
The edge of the
|
|
317
|
+
The edge of the y-axis to which the label will be added, by default ``UR``.
|
|
309
318
|
direction
|
|
310
319
|
Allows for further positioning of the label from an edge, by default ``UR``
|
|
311
320
|
buff
|
|
@@ -332,7 +341,6 @@ class CoordinateSystem:
|
|
|
332
341
|
)
|
|
333
342
|
self.add(ax, y_label)
|
|
334
343
|
"""
|
|
335
|
-
|
|
336
344
|
return self._get_axis_label(
|
|
337
345
|
label, self.get_y_axis(), edge, direction, buff=buff, **kwargs
|
|
338
346
|
)
|
|
@@ -365,7 +373,6 @@ class CoordinateSystem:
|
|
|
365
373
|
:class:`~.Mobject`
|
|
366
374
|
The positioned label along the given axis.
|
|
367
375
|
"""
|
|
368
|
-
|
|
369
376
|
label = self.x_axis._create_label_tex(label)
|
|
370
377
|
label.next_to(axis.get_edge_center(edge), direction=direction, buff=buff)
|
|
371
378
|
label.shift_onto_screen(buff=MED_SMALL_BUFF)
|
|
@@ -394,7 +401,9 @@ class CoordinateSystem:
|
|
|
394
401
|
ax = ThreeDAxes()
|
|
395
402
|
x_labels = range(-4, 5)
|
|
396
403
|
z_labels = range(-4, 4, 2)
|
|
397
|
-
ax.add_coordinates(
|
|
404
|
+
ax.add_coordinates(
|
|
405
|
+
x_labels, None, z_labels
|
|
406
|
+
) # default y labels, custom x & z labels
|
|
398
407
|
ax.add_coordinates(x_labels) # only x labels
|
|
399
408
|
|
|
400
409
|
You can also specifically control the position and value of the labels using a dict.
|
|
@@ -405,11 +414,18 @@ class CoordinateSystem:
|
|
|
405
414
|
x_pos = [x for x in range(1, 8)]
|
|
406
415
|
|
|
407
416
|
# strings are automatically converted into a Tex mobject.
|
|
408
|
-
x_vals = [
|
|
417
|
+
x_vals = [
|
|
418
|
+
"Monday",
|
|
419
|
+
"Tuesday",
|
|
420
|
+
"Wednesday",
|
|
421
|
+
"Thursday",
|
|
422
|
+
"Friday",
|
|
423
|
+
"Saturday",
|
|
424
|
+
"Sunday",
|
|
425
|
+
]
|
|
409
426
|
x_dict = dict(zip(x_pos, x_vals))
|
|
410
427
|
ax.add_coordinates(x_dict)
|
|
411
428
|
"""
|
|
412
|
-
|
|
413
429
|
self.coordinate_labels = VGroup()
|
|
414
430
|
# if nothing is passed to axes_numbers, produce axes with default labelling
|
|
415
431
|
if not axes_numbers:
|
|
@@ -441,8 +457,7 @@ class CoordinateSystem:
|
|
|
441
457
|
line_config: dict | None = ...,
|
|
442
458
|
color: ParsableManimColor | None = ...,
|
|
443
459
|
stroke_width: float = ...,
|
|
444
|
-
) -> DashedLine:
|
|
445
|
-
...
|
|
460
|
+
) -> DashedLine: ...
|
|
446
461
|
|
|
447
462
|
@overload
|
|
448
463
|
def get_line_from_axis_to_point(
|
|
@@ -453,8 +468,7 @@ class CoordinateSystem:
|
|
|
453
468
|
line_config: dict | None = ...,
|
|
454
469
|
color: ParsableManimColor | None = ...,
|
|
455
470
|
stroke_width: float = ...,
|
|
456
|
-
) -> LineType:
|
|
457
|
-
...
|
|
471
|
+
) -> LineType: ...
|
|
458
472
|
|
|
459
473
|
def get_line_from_axis_to_point( # type: ignore[no-untyped-def]
|
|
460
474
|
self,
|
|
@@ -492,7 +506,6 @@ class CoordinateSystem:
|
|
|
492
506
|
:meth:`~.CoordinateSystem.get_vertical_line`
|
|
493
507
|
:meth:`~.CoordinateSystem.get_horizontal_line`
|
|
494
508
|
"""
|
|
495
|
-
|
|
496
509
|
line_config = line_config if line_config is not None else {}
|
|
497
510
|
|
|
498
511
|
if color is None:
|
|
@@ -562,14 +575,13 @@ class CoordinateSystem:
|
|
|
562
575
|
class GetHorizontalLineExample(Scene):
|
|
563
576
|
def construct(self):
|
|
564
577
|
ax = Axes().add_coordinates()
|
|
565
|
-
point = ax
|
|
578
|
+
point = ax @ (-4, 1.5)
|
|
566
579
|
|
|
567
580
|
dot = Dot(point)
|
|
568
581
|
line = ax.get_horizontal_line(point, line_func=Line)
|
|
569
582
|
|
|
570
583
|
self.add(ax, line, dot)
|
|
571
584
|
"""
|
|
572
|
-
|
|
573
585
|
return self.get_line_from_axis_to_point(1, point, **kwargs)
|
|
574
586
|
|
|
575
587
|
def get_lines_to_point(self, point: Sequence[float], **kwargs) -> VGroup:
|
|
@@ -606,7 +618,6 @@ class CoordinateSystem:
|
|
|
606
618
|
lines_2 = ax.get_lines_to_point(circ.get_corner(DL), color=BLUE_B)
|
|
607
619
|
self.add(ax, lines_1, lines_2, circ)
|
|
608
620
|
"""
|
|
609
|
-
|
|
610
621
|
return VGroup(
|
|
611
622
|
self.get_horizontal_line(point, **kwargs),
|
|
612
623
|
self.get_vertical_line(point, **kwargs),
|
|
@@ -619,6 +630,8 @@ class CoordinateSystem:
|
|
|
619
630
|
function: Callable[[float], float],
|
|
620
631
|
x_range: Sequence[float] | None = None,
|
|
621
632
|
use_vectorized: bool = False,
|
|
633
|
+
colorscale: Union[Iterable[Color], Iterable[Color, float]] | None = None,
|
|
634
|
+
colorscale_axis: int = 1,
|
|
622
635
|
**kwargs: Any,
|
|
623
636
|
) -> ParametricFunction:
|
|
624
637
|
"""Generates a curve based on a function.
|
|
@@ -632,6 +645,12 @@ class CoordinateSystem:
|
|
|
632
645
|
use_vectorized
|
|
633
646
|
Whether to pass in the generated t value array to the function. Only use this if your function supports it.
|
|
634
647
|
Output should be a numpy array of shape ``[y_0, y_1, ...]``
|
|
648
|
+
colorscale
|
|
649
|
+
Colors of the function. Optional parameter used when coloring a function by values. Passing a list of colors
|
|
650
|
+
and a colorscale_axis will color the function by y-value. Passing a list of tuples in the form ``(color, pivot)``
|
|
651
|
+
allows user-defined pivots where the color transitions.
|
|
652
|
+
colorscale_axis
|
|
653
|
+
Defines the axis on which the colorscale is applied (0 = x, 1 = y), default is y-axis (1).
|
|
635
654
|
kwargs
|
|
636
655
|
Additional parameters to be passed to :class:`~.ParametricFunction`.
|
|
637
656
|
|
|
@@ -691,7 +710,6 @@ class CoordinateSystem:
|
|
|
691
710
|
|
|
692
711
|
self.add(axes, curves)
|
|
693
712
|
"""
|
|
694
|
-
|
|
695
713
|
t_range = np.array(self.x_range, dtype=float)
|
|
696
714
|
if x_range is not None:
|
|
697
715
|
t_range[: len(x_range)] = x_range
|
|
@@ -710,7 +728,57 @@ class CoordinateSystem:
|
|
|
710
728
|
use_vectorized=use_vectorized,
|
|
711
729
|
**kwargs,
|
|
712
730
|
)
|
|
731
|
+
|
|
713
732
|
graph.underlying_function = function
|
|
733
|
+
|
|
734
|
+
if colorscale:
|
|
735
|
+
if type(colorscale[0]) in (list, tuple):
|
|
736
|
+
new_colors, pivots = [
|
|
737
|
+
[i for i, j in colorscale],
|
|
738
|
+
[j for i, j in colorscale],
|
|
739
|
+
]
|
|
740
|
+
else:
|
|
741
|
+
new_colors = colorscale
|
|
742
|
+
|
|
743
|
+
ranges = [self.x_range, self.y_range]
|
|
744
|
+
pivot_min = ranges[colorscale_axis][0]
|
|
745
|
+
pivot_max = ranges[colorscale_axis][1]
|
|
746
|
+
pivot_frequency = (pivot_max - pivot_min) / (len(new_colors) - 1)
|
|
747
|
+
pivots = np.arange(
|
|
748
|
+
start=pivot_min,
|
|
749
|
+
stop=pivot_max + pivot_frequency,
|
|
750
|
+
step=pivot_frequency,
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
resolution = 0.01 if len(x_range) == 2 else x_range[2]
|
|
754
|
+
sample_points = np.arange(x_range[0], x_range[1] + resolution, resolution)
|
|
755
|
+
color_list = []
|
|
756
|
+
for samp_x in sample_points:
|
|
757
|
+
axis_value = (samp_x, function(samp_x))[colorscale_axis]
|
|
758
|
+
if axis_value <= pivots[0]:
|
|
759
|
+
color_list.append(new_colors[0])
|
|
760
|
+
elif axis_value >= pivots[-1]:
|
|
761
|
+
color_list.append(new_colors[-1])
|
|
762
|
+
else:
|
|
763
|
+
for i, pivot in enumerate(pivots):
|
|
764
|
+
if pivot > axis_value:
|
|
765
|
+
color_index = (axis_value - pivots[i - 1]) / (
|
|
766
|
+
pivots[i] - pivots[i - 1]
|
|
767
|
+
)
|
|
768
|
+
color_index = min(color_index, 1)
|
|
769
|
+
mob_color = interpolate_color(
|
|
770
|
+
new_colors[i - 1],
|
|
771
|
+
new_colors[i],
|
|
772
|
+
color_index,
|
|
773
|
+
)
|
|
774
|
+
color_list.append(mob_color)
|
|
775
|
+
break
|
|
776
|
+
if config.renderer == RendererType.OPENGL:
|
|
777
|
+
graph.set_color(color_list)
|
|
778
|
+
else:
|
|
779
|
+
graph.set_stroke(color_list)
|
|
780
|
+
graph.set_sheen_direction(RIGHT)
|
|
781
|
+
|
|
714
782
|
return graph
|
|
715
783
|
|
|
716
784
|
def plot_implicit_curve(
|
|
@@ -855,9 +923,11 @@ class CoordinateSystem:
|
|
|
855
923
|
function: Callable[[float], float],
|
|
856
924
|
u_range: Sequence[float] | None = None,
|
|
857
925
|
v_range: Sequence[float] | None = None,
|
|
858
|
-
colorscale:
|
|
859
|
-
|
|
860
|
-
|
|
926
|
+
colorscale: (
|
|
927
|
+
Sequence[ParsableManimColor]
|
|
928
|
+
| Sequence[tuple[ParsableManimColor, float]]
|
|
929
|
+
| None
|
|
930
|
+
) = None,
|
|
861
931
|
colorscale_axis: int = 2,
|
|
862
932
|
**kwargs: Any,
|
|
863
933
|
) -> Surface | OpenGLSurface:
|
|
@@ -940,7 +1010,7 @@ class CoordinateSystem:
|
|
|
940
1010
|
self,
|
|
941
1011
|
x: float,
|
|
942
1012
|
graph: ParametricFunction | VMobject,
|
|
943
|
-
) ->
|
|
1013
|
+
) -> Point3D:
|
|
944
1014
|
"""Returns the coordinates of the point on a ``graph`` corresponding to an ``x`` value.
|
|
945
1015
|
|
|
946
1016
|
Parameters
|
|
@@ -976,7 +1046,6 @@ class CoordinateSystem:
|
|
|
976
1046
|
|
|
977
1047
|
self.add(ax, curve, sq)
|
|
978
1048
|
"""
|
|
979
|
-
|
|
980
1049
|
if hasattr(graph, "underlying_function"):
|
|
981
1050
|
return graph.function(x)
|
|
982
1051
|
else:
|
|
@@ -1032,7 +1101,7 @@ class CoordinateSystem:
|
|
|
1032
1101
|
dot: bool = False,
|
|
1033
1102
|
dot_config: dict[str, Any] | None = None,
|
|
1034
1103
|
) -> Mobject:
|
|
1035
|
-
"""Creates a properly positioned label for the passed graph, with an optional dot.
|
|
1104
|
+
r"""Creates a properly positioned label for the passed graph, with an optional dot.
|
|
1036
1105
|
|
|
1037
1106
|
Parameters
|
|
1038
1107
|
----------
|
|
@@ -1069,7 +1138,7 @@ class CoordinateSystem:
|
|
|
1069
1138
|
sin = ax.plot(lambda x: np.sin(x), color=PURPLE_B)
|
|
1070
1139
|
label = ax.get_graph_label(
|
|
1071
1140
|
graph=sin,
|
|
1072
|
-
label= MathTex(r"
|
|
1141
|
+
label= MathTex(r"\frac{\pi}{2}"),
|
|
1073
1142
|
x_val=PI / 2,
|
|
1074
1143
|
dot=True,
|
|
1075
1144
|
direction=UR,
|
|
@@ -1077,7 +1146,6 @@ class CoordinateSystem:
|
|
|
1077
1146
|
|
|
1078
1147
|
self.add(ax, sin, label)
|
|
1079
1148
|
"""
|
|
1080
|
-
|
|
1081
1149
|
if dot_config is None:
|
|
1082
1150
|
dot_config = {}
|
|
1083
1151
|
if color is None:
|
|
@@ -1197,7 +1265,6 @@ class CoordinateSystem:
|
|
|
1197
1265
|
ax, bounding_line, quadratic, rects_right, rects_left, bounded_rects
|
|
1198
1266
|
)
|
|
1199
1267
|
"""
|
|
1200
|
-
|
|
1201
1268
|
# setting up x_range, overwrite user's third input
|
|
1202
1269
|
if x_range is None:
|
|
1203
1270
|
if bounded_graph is None:
|
|
@@ -1387,7 +1454,6 @@ class CoordinateSystem:
|
|
|
1387
1454
|
ax.angle_of_tangent(x=3, graph=curve)
|
|
1388
1455
|
# 1.4056476493802699
|
|
1389
1456
|
"""
|
|
1390
|
-
|
|
1391
1457
|
p0 = np.array([*self.input_to_graph_coords(x, graph)])
|
|
1392
1458
|
p1 = np.array([*self.input_to_graph_coords(x + dx, graph)])
|
|
1393
1459
|
return angle_of_vector(p1 - p0)
|
|
@@ -1419,7 +1485,6 @@ class CoordinateSystem:
|
|
|
1419
1485
|
ax.slope_of_tangent(x=-2, graph=curve)
|
|
1420
1486
|
# -3.5000000259052038
|
|
1421
1487
|
"""
|
|
1422
|
-
|
|
1423
1488
|
return np.tan(self.angle_of_tangent(x, graph, **kwargs))
|
|
1424
1489
|
|
|
1425
1490
|
def plot_derivative_graph(
|
|
@@ -1695,7 +1760,6 @@ class CoordinateSystem:
|
|
|
1695
1760
|
|
|
1696
1761
|
self.add(ax, curve, lines)
|
|
1697
1762
|
"""
|
|
1698
|
-
|
|
1699
1763
|
x_range = x_range if x_range is not None else self.x_range
|
|
1700
1764
|
|
|
1701
1765
|
return VGroup(
|
|
@@ -1757,7 +1821,6 @@ class CoordinateSystem:
|
|
|
1757
1821
|
t_label = axes.get_T_label(x_val=4, graph=func, label=Tex("x-value"))
|
|
1758
1822
|
self.add(axes, func, t_label)
|
|
1759
1823
|
"""
|
|
1760
|
-
|
|
1761
1824
|
T_label_group = VGroup()
|
|
1762
1825
|
triangle = RegularPolygon(n=3, start_angle=np.pi / 2, stroke_width=0).set_fill(
|
|
1763
1826
|
color=triangle_color,
|
|
@@ -1780,6 +1843,14 @@ class CoordinateSystem:
|
|
|
1780
1843
|
|
|
1781
1844
|
return T_label_group
|
|
1782
1845
|
|
|
1846
|
+
def __matmul__(self, coord: Point3DLike | Mobject):
|
|
1847
|
+
if isinstance(coord, Mobject):
|
|
1848
|
+
coord = coord.get_center()
|
|
1849
|
+
return self.coords_to_point(*coord)
|
|
1850
|
+
|
|
1851
|
+
def __rmatmul__(self, point: Point3DLike):
|
|
1852
|
+
return self.point_to_coords(point)
|
|
1853
|
+
|
|
1783
1854
|
|
|
1784
1855
|
class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
1785
1856
|
"""Creates a set of axes.
|
|
@@ -1941,7 +2012,6 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
1941
2012
|
)
|
|
1942
2013
|
)
|
|
1943
2014
|
"""
|
|
1944
|
-
|
|
1945
2015
|
for default_config, passed_config in zip(default_configs, passed_configs):
|
|
1946
2016
|
if passed_config is not None:
|
|
1947
2017
|
update_dict_recursively(default_config, passed_config)
|
|
@@ -1980,6 +2050,7 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
1980
2050
|
self, *coords: float | Sequence[float] | Sequence[Sequence[float]] | np.ndarray
|
|
1981
2051
|
) -> np.ndarray:
|
|
1982
2052
|
"""Accepts coordinates from the axes and returns a point with respect to the scene.
|
|
2053
|
+
Equivalent to `ax @ (coord1)`
|
|
1983
2054
|
|
|
1984
2055
|
Parameters
|
|
1985
2056
|
----------
|
|
@@ -2008,6 +2079,8 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
2008
2079
|
>>> ax = Axes()
|
|
2009
2080
|
>>> np.around(ax.coords_to_point(1, 0, 0), 2)
|
|
2010
2081
|
array([0.86, 0. , 0. ])
|
|
2082
|
+
>>> np.around(ax @ (1, 0, 0), 2)
|
|
2083
|
+
array([0.86, 0. , 0. ])
|
|
2011
2084
|
>>> np.around(ax.coords_to_point([[0, 1], [1, 1], [1, 0]]), 2)
|
|
2012
2085
|
array([[0. , 0.75, 0. ],
|
|
2013
2086
|
[0.86, 0.75, 0. ],
|
|
@@ -2183,7 +2256,6 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
2183
2256
|
)
|
|
2184
2257
|
self.add(ax, labels)
|
|
2185
2258
|
"""
|
|
2186
|
-
|
|
2187
2259
|
self.axis_labels = VGroup(
|
|
2188
2260
|
self.get_x_axis_label(x_label),
|
|
2189
2261
|
self.get_y_axis_label(y_label),
|
|
@@ -2342,7 +2414,7 @@ class ThreeDAxes(Axes):
|
|
|
2342
2414
|
y_length: float | None = config.frame_height + 2.5,
|
|
2343
2415
|
z_length: float | None = config.frame_height - 1.5,
|
|
2344
2416
|
z_axis_config: dict[str, Any] | None = None,
|
|
2345
|
-
z_normal:
|
|
2417
|
+
z_normal: Vector3D = DOWN,
|
|
2346
2418
|
num_axis_pieces: int = 20,
|
|
2347
2419
|
light_source: Sequence[float] = 9 * DOWN + 7 * LEFT + 10 * OUT,
|
|
2348
2420
|
# opengl stuff (?)
|
|
@@ -2433,7 +2505,7 @@ class ThreeDAxes(Axes):
|
|
|
2433
2505
|
direction: Sequence[float] = UR,
|
|
2434
2506
|
buff: float = SMALL_BUFF,
|
|
2435
2507
|
rotation: float = PI / 2,
|
|
2436
|
-
rotation_axis:
|
|
2508
|
+
rotation_axis: Vector3D = OUT,
|
|
2437
2509
|
**kwargs,
|
|
2438
2510
|
) -> Mobject:
|
|
2439
2511
|
"""Generate a y-axis label.
|
|
@@ -2470,7 +2542,6 @@ class ThreeDAxes(Axes):
|
|
|
2470
2542
|
self.set_camera_orientation(phi=2*PI/5, theta=PI/5)
|
|
2471
2543
|
self.add(ax, lab)
|
|
2472
2544
|
"""
|
|
2473
|
-
|
|
2474
2545
|
positioned_label = self._get_axis_label(
|
|
2475
2546
|
label, self.get_y_axis(), edge, direction, buff=buff, **kwargs
|
|
2476
2547
|
)
|
|
@@ -2480,11 +2551,11 @@ class ThreeDAxes(Axes):
|
|
|
2480
2551
|
def get_z_axis_label(
|
|
2481
2552
|
self,
|
|
2482
2553
|
label: float | str | Mobject,
|
|
2483
|
-
edge:
|
|
2484
|
-
direction:
|
|
2554
|
+
edge: Vector3D = OUT,
|
|
2555
|
+
direction: Vector3D = RIGHT,
|
|
2485
2556
|
buff: float = SMALL_BUFF,
|
|
2486
2557
|
rotation: float = PI / 2,
|
|
2487
|
-
rotation_axis:
|
|
2558
|
+
rotation_axis: Vector3D = RIGHT,
|
|
2488
2559
|
**kwargs: Any,
|
|
2489
2560
|
) -> Mobject:
|
|
2490
2561
|
"""Generate a z-axis label.
|
|
@@ -2521,7 +2592,6 @@ class ThreeDAxes(Axes):
|
|
|
2521
2592
|
self.set_camera_orientation(phi=2*PI/5, theta=PI/5)
|
|
2522
2593
|
self.add(ax, lab)
|
|
2523
2594
|
"""
|
|
2524
|
-
|
|
2525
2595
|
positioned_label = self._get_axis_label(
|
|
2526
2596
|
label, self.get_z_axis(), edge, direction, buff=buff, **kwargs
|
|
2527
2597
|
)
|
|
@@ -2571,11 +2641,10 @@ class ThreeDAxes(Axes):
|
|
|
2571
2641
|
self.set_camera_orientation(phi=2*PI/5, theta=PI/5)
|
|
2572
2642
|
axes = ThreeDAxes()
|
|
2573
2643
|
labels = axes.get_axis_labels(
|
|
2574
|
-
|
|
2644
|
+
Text("x-axis").scale(0.7), Text("y-axis").scale(0.45), Text("z-axis").scale(0.45)
|
|
2575
2645
|
)
|
|
2576
2646
|
self.add(axes, labels)
|
|
2577
2647
|
"""
|
|
2578
|
-
|
|
2579
2648
|
self.axis_labels = VGroup(
|
|
2580
2649
|
self.get_x_axis_label(x_label),
|
|
2581
2650
|
self.get_y_axis_label(y_label),
|
|
@@ -2653,14 +2722,12 @@ class NumberPlane(Axes):
|
|
|
2653
2722
|
|
|
2654
2723
|
def __init__(
|
|
2655
2724
|
self,
|
|
2656
|
-
x_range: Sequence[float]
|
|
2657
|
-
| None = (
|
|
2725
|
+
x_range: Sequence[float] | None = (
|
|
2658
2726
|
-config["frame_x_radius"],
|
|
2659
2727
|
config["frame_x_radius"],
|
|
2660
2728
|
1,
|
|
2661
2729
|
),
|
|
2662
|
-
y_range: Sequence[float]
|
|
2663
|
-
| None = (
|
|
2730
|
+
y_range: Sequence[float] | None = (
|
|
2664
2731
|
-config["frame_y_radius"],
|
|
2665
2732
|
config["frame_y_radius"],
|
|
2666
2733
|
1,
|
|
@@ -2801,7 +2868,6 @@ class NumberPlane(Axes):
|
|
|
2801
2868
|
The first (i.e the non-faded lines parallel to `axis_parallel_to`) and second
|
|
2802
2869
|
(i.e the faded lines parallel to `axis_parallel_to`) sets of lines, respectively.
|
|
2803
2870
|
"""
|
|
2804
|
-
|
|
2805
2871
|
line = Line(axis_parallel_to.get_start(), axis_parallel_to.get_end())
|
|
2806
2872
|
if ratio_faded_lines == 0: # don't show faded lines
|
|
2807
2873
|
ratio_faded_lines = 1 # i.e. set ratio to 1
|
|
@@ -3169,7 +3235,7 @@ class PolarPlane(Axes):
|
|
|
3169
3235
|
elif self.azimuth_units == "degrees":
|
|
3170
3236
|
a_tex = [
|
|
3171
3237
|
MathTex(
|
|
3172
|
-
f
|
|
3238
|
+
f"{360 * i['label']:g}" + r"^{\circ}",
|
|
3173
3239
|
font_size=self.azimuth_label_font_size,
|
|
3174
3240
|
).next_to(
|
|
3175
3241
|
i["point"],
|
|
@@ -3182,7 +3248,7 @@ class PolarPlane(Axes):
|
|
|
3182
3248
|
elif self.azimuth_units == "gradians":
|
|
3183
3249
|
a_tex = [
|
|
3184
3250
|
MathTex(
|
|
3185
|
-
f
|
|
3251
|
+
f"{400 * i['label']:g}" + r"^{g}",
|
|
3186
3252
|
font_size=self.azimuth_label_font_size,
|
|
3187
3253
|
).next_to(
|
|
3188
3254
|
i["point"],
|
|
@@ -3195,7 +3261,7 @@ class PolarPlane(Axes):
|
|
|
3195
3261
|
elif self.azimuth_units is None:
|
|
3196
3262
|
a_tex = [
|
|
3197
3263
|
MathTex(
|
|
3198
|
-
f
|
|
3264
|
+
f"{i['label']:g}",
|
|
3199
3265
|
font_size=self.azimuth_label_font_size,
|
|
3200
3266
|
).next_to(
|
|
3201
3267
|
i["point"],
|
|
@@ -3313,7 +3379,6 @@ class ComplexPlane(NumberPlane):
|
|
|
3313
3379
|
np.ndarray
|
|
3314
3380
|
The point on the plane.
|
|
3315
3381
|
"""
|
|
3316
|
-
|
|
3317
3382
|
number = complex(number)
|
|
3318
3383
|
return self.coords_to_point(number.real, number.imag)
|
|
3319
3384
|
|
|
@@ -3321,7 +3386,7 @@ class ComplexPlane(NumberPlane):
|
|
|
3321
3386
|
"""Abbreviation for :meth:`number_to_point`."""
|
|
3322
3387
|
return self.number_to_point(number)
|
|
3323
3388
|
|
|
3324
|
-
def point_to_number(self, point:
|
|
3389
|
+
def point_to_number(self, point: Point3DLike) -> complex:
|
|
3325
3390
|
"""Accepts a point and returns a complex number equivalent to that point on the plane.
|
|
3326
3391
|
|
|
3327
3392
|
Parameters
|
|
@@ -3334,11 +3399,10 @@ class ComplexPlane(NumberPlane):
|
|
|
3334
3399
|
complex
|
|
3335
3400
|
A complex number consisting of real and imaginary components.
|
|
3336
3401
|
"""
|
|
3337
|
-
|
|
3338
3402
|
x, y = self.point_to_coords(point)
|
|
3339
3403
|
return complex(x, y)
|
|
3340
3404
|
|
|
3341
|
-
def p2n(self, point:
|
|
3405
|
+
def p2n(self, point: Point3DLike) -> complex:
|
|
3342
3406
|
"""Abbreviation for :meth:`point_to_number`."""
|
|
3343
3407
|
return self.point_to_number(point)
|
|
3344
3408
|
|
|
@@ -3372,7 +3436,6 @@ class ComplexPlane(NumberPlane):
|
|
|
3372
3436
|
:class:`~.VGroup`
|
|
3373
3437
|
A :class:`~.VGroup` containing the positioned label mobjects.
|
|
3374
3438
|
"""
|
|
3375
|
-
|
|
3376
3439
|
# TODO: Make this work the same as coord_sys.add_coordinates()
|
|
3377
3440
|
if len(numbers) == 0:
|
|
3378
3441
|
numbers = self._get_default_coordinate_values()
|
|
@@ -3403,6 +3466,5 @@ class ComplexPlane(NumberPlane):
|
|
|
3403
3466
|
kwargs
|
|
3404
3467
|
Additional arguments to be passed to :meth:`~.NumberLine.get_number_mobject`, i.e. :class:`~.DecimalNumber`.
|
|
3405
3468
|
"""
|
|
3406
|
-
|
|
3407
3469
|
self.add(self.get_coordinate_labels(*numbers, **kwargs))
|
|
3408
3470
|
return self
|
|
@@ -5,7 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
__all__ = ["ParametricFunction", "FunctionGraph", "ImplicitFunction"]
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from collections.abc import Iterable, Sequence
|
|
9
|
+
from typing import TYPE_CHECKING, Callable
|
|
9
10
|
|
|
10
11
|
import numpy as np
|
|
11
12
|
from isosurfaces import plot_isoline
|
|
@@ -14,6 +15,12 @@ from manim import config
|
|
|
14
15
|
from manim.mobject.graphing.scale import LinearBase, _ScaleBase
|
|
15
16
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
16
17
|
from manim.mobject.types.vectorized_mobject import VMobject
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from typing_extensions import Self
|
|
21
|
+
|
|
22
|
+
from manim.typing import Point3D, Point3DLike
|
|
23
|
+
|
|
17
24
|
from manim.utils.color import YELLOW
|
|
18
25
|
|
|
19
26
|
|
|
@@ -23,9 +30,9 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
23
30
|
Parameters
|
|
24
31
|
----------
|
|
25
32
|
function
|
|
26
|
-
The function to be plotted in the form of ``(lambda
|
|
33
|
+
The function to be plotted in the form of ``(lambda t: (x(t), y(t), z(t)))``
|
|
27
34
|
t_range
|
|
28
|
-
Determines the length that the function spans. By default ``[0, 1]``
|
|
35
|
+
Determines the length that the function spans in the form of (t_min, t_max, step=0.01). By default ``[0, 1]``
|
|
29
36
|
scaling
|
|
30
37
|
Scaling class applied to the points of the function. Default of :class:`~.LinearBase`.
|
|
31
38
|
use_smoothing
|
|
@@ -49,10 +56,10 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
49
56
|
|
|
50
57
|
class PlotParametricFunction(Scene):
|
|
51
58
|
def func(self, t):
|
|
52
|
-
return
|
|
59
|
+
return (np.sin(2 * t), np.sin(3 * t), 0)
|
|
53
60
|
|
|
54
61
|
def construct(self):
|
|
55
|
-
func = ParametricFunction(self.func, t_range =
|
|
62
|
+
func = ParametricFunction(self.func, t_range = (0, TAU), fill_opacity=0).set_color(RED)
|
|
56
63
|
self.add(func.scale(3))
|
|
57
64
|
|
|
58
65
|
.. manim:: ThreeDParametricSpring
|
|
@@ -61,11 +68,11 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
61
68
|
class ThreeDParametricSpring(ThreeDScene):
|
|
62
69
|
def construct(self):
|
|
63
70
|
curve1 = ParametricFunction(
|
|
64
|
-
lambda u:
|
|
71
|
+
lambda u: (
|
|
65
72
|
1.2 * np.cos(u),
|
|
66
73
|
1.2 * np.sin(u),
|
|
67
74
|
u * 0.05
|
|
68
|
-
|
|
75
|
+
), color=RED, t_range = (-3*TAU, 5*TAU, 0.01)
|
|
69
76
|
).set_shade_in_3d(True)
|
|
70
77
|
axes = ThreeDAxes()
|
|
71
78
|
self.add(axes, curve1)
|
|
@@ -97,8 +104,8 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
97
104
|
|
|
98
105
|
def __init__(
|
|
99
106
|
self,
|
|
100
|
-
function: Callable[[float
|
|
101
|
-
t_range:
|
|
107
|
+
function: Callable[[float], Point3DLike],
|
|
108
|
+
t_range: tuple[float, float] | tuple[float, float, float] = (0, 1),
|
|
102
109
|
scaling: _ScaleBase = LinearBase(),
|
|
103
110
|
dt: float = 1e-8,
|
|
104
111
|
discontinuities: Iterable[float] | None = None,
|
|
@@ -106,10 +113,13 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
106
113
|
use_vectorized: bool = False,
|
|
107
114
|
**kwargs,
|
|
108
115
|
):
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
def internal_parametric_function(t: float) -> Point3D:
|
|
117
|
+
"""Wrap ``function``'s output inside a NumPy array."""
|
|
118
|
+
return np.asarray(function(t))
|
|
119
|
+
|
|
120
|
+
self.function = internal_parametric_function
|
|
111
121
|
if len(t_range) == 2:
|
|
112
|
-
t_range =
|
|
122
|
+
t_range = (*t_range, 0.01)
|
|
113
123
|
|
|
114
124
|
self.scaling = scaling
|
|
115
125
|
|
|
@@ -121,13 +131,13 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
121
131
|
|
|
122
132
|
super().__init__(**kwargs)
|
|
123
133
|
|
|
124
|
-
def get_function(self):
|
|
134
|
+
def get_function(self) -> Callable[[float], Point3D]:
|
|
125
135
|
return self.function
|
|
126
136
|
|
|
127
|
-
def get_point_from_function(self, t):
|
|
137
|
+
def get_point_from_function(self, t: float) -> Point3D:
|
|
128
138
|
return self.function(t)
|
|
129
139
|
|
|
130
|
-
def generate_points(self):
|
|
140
|
+
def generate_points(self) -> Self:
|
|
131
141
|
if self.discontinuities is not None:
|
|
132
142
|
discontinuities = filter(
|
|
133
143
|
lambda t: self.t_min <= t <= self.t_max,
|