manim 0.18.1__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of manim might be problematic. Click here for more details.
- manim/__main__.py +45 -12
- manim/_config/__init__.py +2 -2
- manim/_config/cli_colors.py +8 -4
- manim/_config/default.cfg +0 -2
- manim/_config/logger_utils.py +5 -0
- manim/_config/utils.py +29 -38
- manim/animation/animation.py +148 -8
- manim/animation/composition.py +16 -13
- manim/animation/creation.py +184 -8
- manim/animation/fading.py +5 -8
- manim/animation/indication.py +93 -26
- manim/animation/movement.py +21 -3
- manim/animation/rotation.py +2 -1
- manim/animation/specialized.py +3 -5
- manim/animation/speedmodifier.py +3 -3
- manim/animation/transform.py +4 -5
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +2 -2
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +52 -36
- manim/cli/checkhealth/checks.py +92 -76
- manim/cli/checkhealth/commands.py +12 -5
- manim/cli/default_group.py +148 -24
- manim/cli/init/commands.py +28 -23
- manim/cli/plugins/commands.py +13 -3
- manim/cli/render/commands.py +47 -42
- manim/cli/render/global_options.py +43 -9
- manim/cli/render/render_options.py +84 -19
- manim/constants.py +11 -4
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +109 -75
- manim/mobject/geometry/boolean_ops.py +20 -17
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +120 -60
- manim/mobject/geometry/polygram.py +109 -25
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +36 -27
- manim/mobject/graph.py +48 -40
- manim/mobject/graphing/coordinate_systems.py +110 -45
- manim/mobject/graphing/functions.py +16 -10
- manim/mobject/graphing/number_line.py +23 -9
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +149 -103
- manim/mobject/opengl/opengl_geometry.py +4 -8
- manim/mobject/opengl/opengl_mobject.py +506 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +3 -7
- manim/mobject/opengl/opengl_surface.py +1 -2
- manim/mobject/opengl/opengl_vectorized_mobject.py +27 -65
- manim/mobject/svg/brace.py +61 -13
- manim/mobject/svg/svg_mobject.py +2 -1
- manim/mobject/table.py +11 -12
- manim/mobject/text/code_mobject.py +186 -550
- manim/mobject/text/numbers.py +7 -7
- manim/mobject/text/tex_mobject.py +22 -13
- manim/mobject/text/text_mobject.py +29 -20
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_dimensions.py +59 -31
- manim/mobject/types/image_mobject.py +37 -23
- manim/mobject/types/point_cloud_mobject.py +103 -67
- manim/mobject/types/vectorized_mobject.py +387 -214
- manim/mobject/value_tracker.py +2 -1
- manim/mobject/vector_field.py +2 -4
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +2 -3
- manim/plugins/plugins_flags.py +3 -3
- manim/renderer/cairo_renderer.py +11 -11
- manim/renderer/opengl_renderer.py +19 -20
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +3 -2
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +72 -41
- manim/scene/scene_file_writer.py +313 -164
- manim/scene/section.py +15 -15
- manim/scene/three_d_scene.py +8 -15
- manim/scene/vector_space_scene.py +3 -6
- manim/typing.py +326 -66
- manim/utils/bezier.py +1658 -381
- manim/utils/caching.py +11 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +2 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +3 -0
- manim/utils/color/XKCD.py +2 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +818 -301
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +40 -19
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -6
- manim/utils/deprecation.py +92 -43
- manim/utils/docbuild/autoaliasattr_directive.py +45 -8
- manim/utils/docbuild/autocolor_directive.py +12 -13
- manim/utils/docbuild/manim_directive.py +35 -29
- manim/utils/docbuild/module_parsing.py +74 -27
- manim/utils/family.py +3 -3
- manim/utils/family_ops.py +12 -4
- manim/utils/file_ops.py +22 -16
- manim/utils/hashing.py +7 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +12 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +55 -19
- manim/utils/opengl.py +68 -23
- manim/utils/parameter_parsing.py +3 -2
- manim/utils/paths.py +11 -5
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +69 -32
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +48 -37
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +33 -18
- manim/utils/testing/frames_comparison.py +20 -14
- manim/utils/tex.py +4 -2
- manim/utils/tex_file_writing.py +45 -45
- manim/utils/tex_templates.py +1 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/METADATA +16 -9
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim-0.18.1.dist-info/RECORD +0 -217
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE.community +0 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
|
@@ -13,7 +13,8 @@ __all__ = [
|
|
|
13
13
|
|
|
14
14
|
import fractions as fr
|
|
15
15
|
import numbers
|
|
16
|
-
from
|
|
16
|
+
from collections.abc import Iterable, Sequence
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Callable, TypeVar, overload
|
|
17
18
|
|
|
18
19
|
import numpy as np
|
|
19
20
|
from typing_extensions import Self
|
|
@@ -26,6 +27,7 @@ from manim.mobject.geometry.polygram import Polygon, Rectangle, RegularPolygon
|
|
|
26
27
|
from manim.mobject.graphing.functions import ImplicitFunction, ParametricFunction
|
|
27
28
|
from manim.mobject.graphing.number_line import NumberLine
|
|
28
29
|
from manim.mobject.graphing.scale import LinearBase
|
|
30
|
+
from manim.mobject.mobject import Mobject
|
|
29
31
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
30
32
|
from manim.mobject.opengl.opengl_surface import OpenGLSurface
|
|
31
33
|
from manim.mobject.text.tex_mobject import MathTex
|
|
@@ -46,6 +48,7 @@ from manim.utils.color import (
|
|
|
46
48
|
ManimColor,
|
|
47
49
|
ParsableManimColor,
|
|
48
50
|
color_gradient,
|
|
51
|
+
interpolate_color,
|
|
49
52
|
invert_color,
|
|
50
53
|
)
|
|
51
54
|
from manim.utils.config_ops import merge_dicts_recursively, update_dict_recursively
|
|
@@ -54,7 +57,14 @@ from manim.utils.space_ops import angle_of_vector
|
|
|
54
57
|
|
|
55
58
|
if TYPE_CHECKING:
|
|
56
59
|
from manim.mobject.mobject import Mobject
|
|
57
|
-
from manim.typing import
|
|
60
|
+
from manim.typing import (
|
|
61
|
+
ManimFloat,
|
|
62
|
+
Point2D,
|
|
63
|
+
Point2DLike,
|
|
64
|
+
Point3D,
|
|
65
|
+
Point3DLike,
|
|
66
|
+
Vector3D,
|
|
67
|
+
)
|
|
58
68
|
|
|
59
69
|
LineType = TypeVar("LineType", bound=Line)
|
|
60
70
|
|
|
@@ -95,10 +105,10 @@ class CoordinateSystem:
|
|
|
95
105
|
)
|
|
96
106
|
|
|
97
107
|
# Extra lines and labels for point (1,1)
|
|
98
|
-
graphs += grid.get_horizontal_line(grid
|
|
99
|
-
graphs += grid.get_vertical_line(grid
|
|
100
|
-
graphs += Dot(point=grid
|
|
101
|
-
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))
|
|
102
112
|
title = Title(
|
|
103
113
|
# spaces between braces to prevent SyntaxError
|
|
104
114
|
r"Graphs of $y=x^{ {1}\over{n} }$ and $y=x^n (n=1,2,3,...,20)$",
|
|
@@ -144,10 +154,10 @@ class CoordinateSystem:
|
|
|
144
154
|
self.y_length = y_length
|
|
145
155
|
self.num_sampled_graph_points_per_tick = 10
|
|
146
156
|
|
|
147
|
-
def coords_to_point(self, *coords:
|
|
157
|
+
def coords_to_point(self, *coords: ManimFloat):
|
|
148
158
|
raise NotImplementedError()
|
|
149
159
|
|
|
150
|
-
def point_to_coords(self, point:
|
|
160
|
+
def point_to_coords(self, point: Point3DLike):
|
|
151
161
|
raise NotImplementedError()
|
|
152
162
|
|
|
153
163
|
def polar_to_point(self, radius: float, azimuth: float) -> Point2D:
|
|
@@ -181,7 +191,7 @@ class CoordinateSystem:
|
|
|
181
191
|
"""
|
|
182
192
|
return self.coords_to_point(radius * np.cos(azimuth), radius * np.sin(azimuth))
|
|
183
193
|
|
|
184
|
-
def point_to_polar(self, point:
|
|
194
|
+
def point_to_polar(self, point: Point2DLike) -> Point2D:
|
|
185
195
|
r"""Gets polar coordinates from a point.
|
|
186
196
|
|
|
187
197
|
Parameters
|
|
@@ -203,7 +213,7 @@ class CoordinateSystem:
|
|
|
203
213
|
"""Abbreviation for :meth:`coords_to_point`"""
|
|
204
214
|
return self.coords_to_point(*coords)
|
|
205
215
|
|
|
206
|
-
def p2c(self, point:
|
|
216
|
+
def p2c(self, point: Point3DLike):
|
|
207
217
|
"""Abbreviation for :meth:`point_to_coords`"""
|
|
208
218
|
return self.point_to_coords(point)
|
|
209
219
|
|
|
@@ -331,7 +341,6 @@ class CoordinateSystem:
|
|
|
331
341
|
)
|
|
332
342
|
self.add(ax, y_label)
|
|
333
343
|
"""
|
|
334
|
-
|
|
335
344
|
return self._get_axis_label(
|
|
336
345
|
label, self.get_y_axis(), edge, direction, buff=buff, **kwargs
|
|
337
346
|
)
|
|
@@ -364,7 +373,6 @@ class CoordinateSystem:
|
|
|
364
373
|
:class:`~.Mobject`
|
|
365
374
|
The positioned label along the given axis.
|
|
366
375
|
"""
|
|
367
|
-
|
|
368
376
|
label = self.x_axis._create_label_tex(label)
|
|
369
377
|
label.next_to(axis.get_edge_center(edge), direction=direction, buff=buff)
|
|
370
378
|
label.shift_onto_screen(buff=MED_SMALL_BUFF)
|
|
@@ -393,7 +401,9 @@ class CoordinateSystem:
|
|
|
393
401
|
ax = ThreeDAxes()
|
|
394
402
|
x_labels = range(-4, 5)
|
|
395
403
|
z_labels = range(-4, 4, 2)
|
|
396
|
-
ax.add_coordinates(
|
|
404
|
+
ax.add_coordinates(
|
|
405
|
+
x_labels, None, z_labels
|
|
406
|
+
) # default y labels, custom x & z labels
|
|
397
407
|
ax.add_coordinates(x_labels) # only x labels
|
|
398
408
|
|
|
399
409
|
You can also specifically control the position and value of the labels using a dict.
|
|
@@ -404,11 +414,18 @@ class CoordinateSystem:
|
|
|
404
414
|
x_pos = [x for x in range(1, 8)]
|
|
405
415
|
|
|
406
416
|
# strings are automatically converted into a Tex mobject.
|
|
407
|
-
x_vals = [
|
|
417
|
+
x_vals = [
|
|
418
|
+
"Monday",
|
|
419
|
+
"Tuesday",
|
|
420
|
+
"Wednesday",
|
|
421
|
+
"Thursday",
|
|
422
|
+
"Friday",
|
|
423
|
+
"Saturday",
|
|
424
|
+
"Sunday",
|
|
425
|
+
]
|
|
408
426
|
x_dict = dict(zip(x_pos, x_vals))
|
|
409
427
|
ax.add_coordinates(x_dict)
|
|
410
428
|
"""
|
|
411
|
-
|
|
412
429
|
self.coordinate_labels = VGroup()
|
|
413
430
|
# if nothing is passed to axes_numbers, produce axes with default labelling
|
|
414
431
|
if not axes_numbers:
|
|
@@ -489,7 +506,6 @@ class CoordinateSystem:
|
|
|
489
506
|
:meth:`~.CoordinateSystem.get_vertical_line`
|
|
490
507
|
:meth:`~.CoordinateSystem.get_horizontal_line`
|
|
491
508
|
"""
|
|
492
|
-
|
|
493
509
|
line_config = line_config if line_config is not None else {}
|
|
494
510
|
|
|
495
511
|
if color is None:
|
|
@@ -559,14 +575,13 @@ class CoordinateSystem:
|
|
|
559
575
|
class GetHorizontalLineExample(Scene):
|
|
560
576
|
def construct(self):
|
|
561
577
|
ax = Axes().add_coordinates()
|
|
562
|
-
point = ax
|
|
578
|
+
point = ax @ (-4, 1.5)
|
|
563
579
|
|
|
564
580
|
dot = Dot(point)
|
|
565
581
|
line = ax.get_horizontal_line(point, line_func=Line)
|
|
566
582
|
|
|
567
583
|
self.add(ax, line, dot)
|
|
568
584
|
"""
|
|
569
|
-
|
|
570
585
|
return self.get_line_from_axis_to_point(1, point, **kwargs)
|
|
571
586
|
|
|
572
587
|
def get_lines_to_point(self, point: Sequence[float], **kwargs) -> VGroup:
|
|
@@ -603,7 +618,6 @@ class CoordinateSystem:
|
|
|
603
618
|
lines_2 = ax.get_lines_to_point(circ.get_corner(DL), color=BLUE_B)
|
|
604
619
|
self.add(ax, lines_1, lines_2, circ)
|
|
605
620
|
"""
|
|
606
|
-
|
|
607
621
|
return VGroup(
|
|
608
622
|
self.get_horizontal_line(point, **kwargs),
|
|
609
623
|
self.get_vertical_line(point, **kwargs),
|
|
@@ -616,6 +630,8 @@ class CoordinateSystem:
|
|
|
616
630
|
function: Callable[[float], float],
|
|
617
631
|
x_range: Sequence[float] | None = None,
|
|
618
632
|
use_vectorized: bool = False,
|
|
633
|
+
colorscale: Union[Iterable[Color], Iterable[Color, float]] | None = None,
|
|
634
|
+
colorscale_axis: int = 1,
|
|
619
635
|
**kwargs: Any,
|
|
620
636
|
) -> ParametricFunction:
|
|
621
637
|
"""Generates a curve based on a function.
|
|
@@ -629,6 +645,12 @@ class CoordinateSystem:
|
|
|
629
645
|
use_vectorized
|
|
630
646
|
Whether to pass in the generated t value array to the function. Only use this if your function supports it.
|
|
631
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).
|
|
632
654
|
kwargs
|
|
633
655
|
Additional parameters to be passed to :class:`~.ParametricFunction`.
|
|
634
656
|
|
|
@@ -688,7 +710,6 @@ class CoordinateSystem:
|
|
|
688
710
|
|
|
689
711
|
self.add(axes, curves)
|
|
690
712
|
"""
|
|
691
|
-
|
|
692
713
|
t_range = np.array(self.x_range, dtype=float)
|
|
693
714
|
if x_range is not None:
|
|
694
715
|
t_range[: len(x_range)] = x_range
|
|
@@ -707,7 +728,57 @@ class CoordinateSystem:
|
|
|
707
728
|
use_vectorized=use_vectorized,
|
|
708
729
|
**kwargs,
|
|
709
730
|
)
|
|
731
|
+
|
|
710
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
|
+
|
|
711
782
|
return graph
|
|
712
783
|
|
|
713
784
|
def plot_implicit_curve(
|
|
@@ -939,7 +1010,7 @@ class CoordinateSystem:
|
|
|
939
1010
|
self,
|
|
940
1011
|
x: float,
|
|
941
1012
|
graph: ParametricFunction | VMobject,
|
|
942
|
-
) ->
|
|
1013
|
+
) -> Point3D:
|
|
943
1014
|
"""Returns the coordinates of the point on a ``graph`` corresponding to an ``x`` value.
|
|
944
1015
|
|
|
945
1016
|
Parameters
|
|
@@ -975,7 +1046,6 @@ class CoordinateSystem:
|
|
|
975
1046
|
|
|
976
1047
|
self.add(ax, curve, sq)
|
|
977
1048
|
"""
|
|
978
|
-
|
|
979
1049
|
if hasattr(graph, "underlying_function"):
|
|
980
1050
|
return graph.function(x)
|
|
981
1051
|
else:
|
|
@@ -1031,7 +1101,7 @@ class CoordinateSystem:
|
|
|
1031
1101
|
dot: bool = False,
|
|
1032
1102
|
dot_config: dict[str, Any] | None = None,
|
|
1033
1103
|
) -> Mobject:
|
|
1034
|
-
"""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.
|
|
1035
1105
|
|
|
1036
1106
|
Parameters
|
|
1037
1107
|
----------
|
|
@@ -1068,7 +1138,7 @@ class CoordinateSystem:
|
|
|
1068
1138
|
sin = ax.plot(lambda x: np.sin(x), color=PURPLE_B)
|
|
1069
1139
|
label = ax.get_graph_label(
|
|
1070
1140
|
graph=sin,
|
|
1071
|
-
label= MathTex(r"
|
|
1141
|
+
label= MathTex(r"\frac{\pi}{2}"),
|
|
1072
1142
|
x_val=PI / 2,
|
|
1073
1143
|
dot=True,
|
|
1074
1144
|
direction=UR,
|
|
@@ -1076,7 +1146,6 @@ class CoordinateSystem:
|
|
|
1076
1146
|
|
|
1077
1147
|
self.add(ax, sin, label)
|
|
1078
1148
|
"""
|
|
1079
|
-
|
|
1080
1149
|
if dot_config is None:
|
|
1081
1150
|
dot_config = {}
|
|
1082
1151
|
if color is None:
|
|
@@ -1196,7 +1265,6 @@ class CoordinateSystem:
|
|
|
1196
1265
|
ax, bounding_line, quadratic, rects_right, rects_left, bounded_rects
|
|
1197
1266
|
)
|
|
1198
1267
|
"""
|
|
1199
|
-
|
|
1200
1268
|
# setting up x_range, overwrite user's third input
|
|
1201
1269
|
if x_range is None:
|
|
1202
1270
|
if bounded_graph is None:
|
|
@@ -1386,7 +1454,6 @@ class CoordinateSystem:
|
|
|
1386
1454
|
ax.angle_of_tangent(x=3, graph=curve)
|
|
1387
1455
|
# 1.4056476493802699
|
|
1388
1456
|
"""
|
|
1389
|
-
|
|
1390
1457
|
p0 = np.array([*self.input_to_graph_coords(x, graph)])
|
|
1391
1458
|
p1 = np.array([*self.input_to_graph_coords(x + dx, graph)])
|
|
1392
1459
|
return angle_of_vector(p1 - p0)
|
|
@@ -1418,7 +1485,6 @@ class CoordinateSystem:
|
|
|
1418
1485
|
ax.slope_of_tangent(x=-2, graph=curve)
|
|
1419
1486
|
# -3.5000000259052038
|
|
1420
1487
|
"""
|
|
1421
|
-
|
|
1422
1488
|
return np.tan(self.angle_of_tangent(x, graph, **kwargs))
|
|
1423
1489
|
|
|
1424
1490
|
def plot_derivative_graph(
|
|
@@ -1694,7 +1760,6 @@ class CoordinateSystem:
|
|
|
1694
1760
|
|
|
1695
1761
|
self.add(ax, curve, lines)
|
|
1696
1762
|
"""
|
|
1697
|
-
|
|
1698
1763
|
x_range = x_range if x_range is not None else self.x_range
|
|
1699
1764
|
|
|
1700
1765
|
return VGroup(
|
|
@@ -1756,7 +1821,6 @@ class CoordinateSystem:
|
|
|
1756
1821
|
t_label = axes.get_T_label(x_val=4, graph=func, label=Tex("x-value"))
|
|
1757
1822
|
self.add(axes, func, t_label)
|
|
1758
1823
|
"""
|
|
1759
|
-
|
|
1760
1824
|
T_label_group = VGroup()
|
|
1761
1825
|
triangle = RegularPolygon(n=3, start_angle=np.pi / 2, stroke_width=0).set_fill(
|
|
1762
1826
|
color=triangle_color,
|
|
@@ -1779,6 +1843,14 @@ class CoordinateSystem:
|
|
|
1779
1843
|
|
|
1780
1844
|
return T_label_group
|
|
1781
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
|
+
|
|
1782
1854
|
|
|
1783
1855
|
class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
1784
1856
|
"""Creates a set of axes.
|
|
@@ -1940,7 +2012,6 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
1940
2012
|
)
|
|
1941
2013
|
)
|
|
1942
2014
|
"""
|
|
1943
|
-
|
|
1944
2015
|
for default_config, passed_config in zip(default_configs, passed_configs):
|
|
1945
2016
|
if passed_config is not None:
|
|
1946
2017
|
update_dict_recursively(default_config, passed_config)
|
|
@@ -1979,6 +2050,7 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
1979
2050
|
self, *coords: float | Sequence[float] | Sequence[Sequence[float]] | np.ndarray
|
|
1980
2051
|
) -> np.ndarray:
|
|
1981
2052
|
"""Accepts coordinates from the axes and returns a point with respect to the scene.
|
|
2053
|
+
Equivalent to `ax @ (coord1)`
|
|
1982
2054
|
|
|
1983
2055
|
Parameters
|
|
1984
2056
|
----------
|
|
@@ -2007,6 +2079,8 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
2007
2079
|
>>> ax = Axes()
|
|
2008
2080
|
>>> np.around(ax.coords_to_point(1, 0, 0), 2)
|
|
2009
2081
|
array([0.86, 0. , 0. ])
|
|
2082
|
+
>>> np.around(ax @ (1, 0, 0), 2)
|
|
2083
|
+
array([0.86, 0. , 0. ])
|
|
2010
2084
|
>>> np.around(ax.coords_to_point([[0, 1], [1, 1], [1, 0]]), 2)
|
|
2011
2085
|
array([[0. , 0.75, 0. ],
|
|
2012
2086
|
[0.86, 0.75, 0. ],
|
|
@@ -2182,7 +2256,6 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
|
|
|
2182
2256
|
)
|
|
2183
2257
|
self.add(ax, labels)
|
|
2184
2258
|
"""
|
|
2185
|
-
|
|
2186
2259
|
self.axis_labels = VGroup(
|
|
2187
2260
|
self.get_x_axis_label(x_label),
|
|
2188
2261
|
self.get_y_axis_label(y_label),
|
|
@@ -2469,7 +2542,6 @@ class ThreeDAxes(Axes):
|
|
|
2469
2542
|
self.set_camera_orientation(phi=2*PI/5, theta=PI/5)
|
|
2470
2543
|
self.add(ax, lab)
|
|
2471
2544
|
"""
|
|
2472
|
-
|
|
2473
2545
|
positioned_label = self._get_axis_label(
|
|
2474
2546
|
label, self.get_y_axis(), edge, direction, buff=buff, **kwargs
|
|
2475
2547
|
)
|
|
@@ -2520,7 +2592,6 @@ class ThreeDAxes(Axes):
|
|
|
2520
2592
|
self.set_camera_orientation(phi=2*PI/5, theta=PI/5)
|
|
2521
2593
|
self.add(ax, lab)
|
|
2522
2594
|
"""
|
|
2523
|
-
|
|
2524
2595
|
positioned_label = self._get_axis_label(
|
|
2525
2596
|
label, self.get_z_axis(), edge, direction, buff=buff, **kwargs
|
|
2526
2597
|
)
|
|
@@ -2574,7 +2645,6 @@ class ThreeDAxes(Axes):
|
|
|
2574
2645
|
)
|
|
2575
2646
|
self.add(axes, labels)
|
|
2576
2647
|
"""
|
|
2577
|
-
|
|
2578
2648
|
self.axis_labels = VGroup(
|
|
2579
2649
|
self.get_x_axis_label(x_label),
|
|
2580
2650
|
self.get_y_axis_label(y_label),
|
|
@@ -2798,7 +2868,6 @@ class NumberPlane(Axes):
|
|
|
2798
2868
|
The first (i.e the non-faded lines parallel to `axis_parallel_to`) and second
|
|
2799
2869
|
(i.e the faded lines parallel to `axis_parallel_to`) sets of lines, respectively.
|
|
2800
2870
|
"""
|
|
2801
|
-
|
|
2802
2871
|
line = Line(axis_parallel_to.get_start(), axis_parallel_to.get_end())
|
|
2803
2872
|
if ratio_faded_lines == 0: # don't show faded lines
|
|
2804
2873
|
ratio_faded_lines = 1 # i.e. set ratio to 1
|
|
@@ -3166,7 +3235,7 @@ class PolarPlane(Axes):
|
|
|
3166
3235
|
elif self.azimuth_units == "degrees":
|
|
3167
3236
|
a_tex = [
|
|
3168
3237
|
MathTex(
|
|
3169
|
-
f
|
|
3238
|
+
f"{360 * i['label']:g}" + r"^{\circ}",
|
|
3170
3239
|
font_size=self.azimuth_label_font_size,
|
|
3171
3240
|
).next_to(
|
|
3172
3241
|
i["point"],
|
|
@@ -3179,7 +3248,7 @@ class PolarPlane(Axes):
|
|
|
3179
3248
|
elif self.azimuth_units == "gradians":
|
|
3180
3249
|
a_tex = [
|
|
3181
3250
|
MathTex(
|
|
3182
|
-
f
|
|
3251
|
+
f"{400 * i['label']:g}" + r"^{g}",
|
|
3183
3252
|
font_size=self.azimuth_label_font_size,
|
|
3184
3253
|
).next_to(
|
|
3185
3254
|
i["point"],
|
|
@@ -3192,7 +3261,7 @@ class PolarPlane(Axes):
|
|
|
3192
3261
|
elif self.azimuth_units is None:
|
|
3193
3262
|
a_tex = [
|
|
3194
3263
|
MathTex(
|
|
3195
|
-
f
|
|
3264
|
+
f"{i['label']:g}",
|
|
3196
3265
|
font_size=self.azimuth_label_font_size,
|
|
3197
3266
|
).next_to(
|
|
3198
3267
|
i["point"],
|
|
@@ -3310,7 +3379,6 @@ class ComplexPlane(NumberPlane):
|
|
|
3310
3379
|
np.ndarray
|
|
3311
3380
|
The point on the plane.
|
|
3312
3381
|
"""
|
|
3313
|
-
|
|
3314
3382
|
number = complex(number)
|
|
3315
3383
|
return self.coords_to_point(number.real, number.imag)
|
|
3316
3384
|
|
|
@@ -3318,7 +3386,7 @@ class ComplexPlane(NumberPlane):
|
|
|
3318
3386
|
"""Abbreviation for :meth:`number_to_point`."""
|
|
3319
3387
|
return self.number_to_point(number)
|
|
3320
3388
|
|
|
3321
|
-
def point_to_number(self, point:
|
|
3389
|
+
def point_to_number(self, point: Point3DLike) -> complex:
|
|
3322
3390
|
"""Accepts a point and returns a complex number equivalent to that point on the plane.
|
|
3323
3391
|
|
|
3324
3392
|
Parameters
|
|
@@ -3331,11 +3399,10 @@ class ComplexPlane(NumberPlane):
|
|
|
3331
3399
|
complex
|
|
3332
3400
|
A complex number consisting of real and imaginary components.
|
|
3333
3401
|
"""
|
|
3334
|
-
|
|
3335
3402
|
x, y = self.point_to_coords(point)
|
|
3336
3403
|
return complex(x, y)
|
|
3337
3404
|
|
|
3338
|
-
def p2n(self, point:
|
|
3405
|
+
def p2n(self, point: Point3DLike) -> complex:
|
|
3339
3406
|
"""Abbreviation for :meth:`point_to_number`."""
|
|
3340
3407
|
return self.point_to_number(point)
|
|
3341
3408
|
|
|
@@ -3369,7 +3436,6 @@ class ComplexPlane(NumberPlane):
|
|
|
3369
3436
|
:class:`~.VGroup`
|
|
3370
3437
|
A :class:`~.VGroup` containing the positioned label mobjects.
|
|
3371
3438
|
"""
|
|
3372
|
-
|
|
3373
3439
|
# TODO: Make this work the same as coord_sys.add_coordinates()
|
|
3374
3440
|
if len(numbers) == 0:
|
|
3375
3441
|
numbers = self._get_default_coordinate_values()
|
|
@@ -3400,6 +3466,5 @@ class ComplexPlane(NumberPlane):
|
|
|
3400
3466
|
kwargs
|
|
3401
3467
|
Additional arguments to be passed to :meth:`~.NumberLine.get_number_mobject`, i.e. :class:`~.DecimalNumber`.
|
|
3402
3468
|
"""
|
|
3403
|
-
|
|
3404
3469
|
self.add(self.get_coordinate_labels(*numbers, **kwargs))
|
|
3405
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
|
|
@@ -16,7 +17,9 @@ from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
|
16
17
|
from manim.mobject.types.vectorized_mobject import VMobject
|
|
17
18
|
|
|
18
19
|
if TYPE_CHECKING:
|
|
19
|
-
from
|
|
20
|
+
from typing_extensions import Self
|
|
21
|
+
|
|
22
|
+
from manim.typing import Point3D, Point3DLike
|
|
20
23
|
|
|
21
24
|
from manim.utils.color import YELLOW
|
|
22
25
|
|
|
@@ -101,8 +104,8 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
101
104
|
|
|
102
105
|
def __init__(
|
|
103
106
|
self,
|
|
104
|
-
function: Callable[[float],
|
|
105
|
-
t_range:
|
|
107
|
+
function: Callable[[float], Point3DLike],
|
|
108
|
+
t_range: tuple[float, float] | tuple[float, float, float] = (0, 1),
|
|
106
109
|
scaling: _ScaleBase = LinearBase(),
|
|
107
110
|
dt: float = 1e-8,
|
|
108
111
|
discontinuities: Iterable[float] | None = None,
|
|
@@ -110,10 +113,13 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
110
113
|
use_vectorized: bool = False,
|
|
111
114
|
**kwargs,
|
|
112
115
|
):
|
|
113
|
-
|
|
114
|
-
|
|
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
|
|
115
121
|
if len(t_range) == 2:
|
|
116
|
-
t_range =
|
|
122
|
+
t_range = (*t_range, 0.01)
|
|
117
123
|
|
|
118
124
|
self.scaling = scaling
|
|
119
125
|
|
|
@@ -125,13 +131,13 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
|
|
|
125
131
|
|
|
126
132
|
super().__init__(**kwargs)
|
|
127
133
|
|
|
128
|
-
def get_function(self):
|
|
134
|
+
def get_function(self) -> Callable[[float], Point3D]:
|
|
129
135
|
return self.function
|
|
130
136
|
|
|
131
|
-
def get_point_from_function(self, t):
|
|
137
|
+
def get_point_from_function(self, t: float) -> Point3D:
|
|
132
138
|
return self.function(t)
|
|
133
139
|
|
|
134
|
-
def generate_points(self):
|
|
140
|
+
def generate_points(self) -> Self:
|
|
135
141
|
if self.discontinuities is not None:
|
|
136
142
|
discontinuities = filter(
|
|
137
143
|
lambda t: self.t_min <= t <= self.t_max,
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from manim.mobject.mobject import Mobject
|
|
5
6
|
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
|
|
6
7
|
|
|
7
8
|
__all__ = ["NumberLine", "UnitInterval"]
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
from
|
|
11
|
+
from collections.abc import Iterable, Sequence
|
|
12
|
+
from typing import TYPE_CHECKING, Callable
|
|
11
13
|
|
|
12
14
|
if TYPE_CHECKING:
|
|
13
15
|
from manim.mobject.geometry.tips import ArrowTip
|
|
16
|
+
from manim.typing import Point3DLike
|
|
14
17
|
|
|
15
18
|
import numpy as np
|
|
16
19
|
|
|
@@ -274,7 +277,8 @@ class NumberLine(Line):
|
|
|
274
277
|
|
|
275
278
|
def add_ticks(self):
|
|
276
279
|
"""Adds ticks to the number line. Ticks can be accessed after creation
|
|
277
|
-
via ``self.ticks``.
|
|
280
|
+
via ``self.ticks``.
|
|
281
|
+
"""
|
|
278
282
|
ticks = VGroup()
|
|
279
283
|
elongated_tick_size = self.tick_size * self.longer_tick_multiple
|
|
280
284
|
elongated_tick_offsets = self.numbers_with_elongated_ticks - self.x_min
|
|
@@ -343,6 +347,7 @@ class NumberLine(Line):
|
|
|
343
347
|
def number_to_point(self, number: float | np.ndarray) -> np.ndarray:
|
|
344
348
|
"""Accepts a value along the number line and returns a point with
|
|
345
349
|
respect to the scene.
|
|
350
|
+
Equivalent to `NumberLine @ number`
|
|
346
351
|
|
|
347
352
|
Parameters
|
|
348
353
|
----------
|
|
@@ -363,7 +368,9 @@ class NumberLine(Line):
|
|
|
363
368
|
array([0., 0., 0.])
|
|
364
369
|
>>> number_line.number_to_point(1)
|
|
365
370
|
array([1., 0., 0.])
|
|
366
|
-
>>> number_line
|
|
371
|
+
>>> number_line @ 1
|
|
372
|
+
array([1., 0., 0.])
|
|
373
|
+
>>> number_line.number_to_point([1, 2, 3])
|
|
367
374
|
array([[1., 0., 0.],
|
|
368
375
|
[2., 0., 0.],
|
|
369
376
|
[3., 0., 0.]])
|
|
@@ -395,11 +402,11 @@ class NumberLine(Line):
|
|
|
395
402
|
|
|
396
403
|
>>> from manim import NumberLine
|
|
397
404
|
>>> number_line = NumberLine()
|
|
398
|
-
>>> number_line.point_to_number((0,0,0))
|
|
399
|
-
0.0
|
|
400
|
-
>>> number_line.point_to_number((1,0,0))
|
|
401
|
-
1.0
|
|
402
|
-
>>> number_line.point_to_number([[0.5,0,0],[1,0,0],[1.5,0,0]])
|
|
405
|
+
>>> number_line.point_to_number((0, 0, 0))
|
|
406
|
+
np.float64(0.0)
|
|
407
|
+
>>> number_line.point_to_number((1, 0, 0))
|
|
408
|
+
np.float64(1.0)
|
|
409
|
+
>>> number_line.point_to_number([[0.5, 0, 0], [1, 0, 0], [1.5, 0, 0]])
|
|
403
410
|
array([0.5, 1. , 1.5])
|
|
404
411
|
|
|
405
412
|
"""
|
|
@@ -574,7 +581,6 @@ class NumberLine(Line):
|
|
|
574
581
|
AttributeError
|
|
575
582
|
If the label does not have a ``font_size`` attribute, an ``AttributeError`` is raised.
|
|
576
583
|
"""
|
|
577
|
-
|
|
578
584
|
direction = self.label_direction if direction is None else direction
|
|
579
585
|
buff = self.line_to_number_buff if buff is None else buff
|
|
580
586
|
font_size = self.font_size if font_size is None else font_size
|
|
@@ -641,6 +647,14 @@ class NumberLine(Line):
|
|
|
641
647
|
return 0
|
|
642
648
|
return len(step.split(".")[-1])
|
|
643
649
|
|
|
650
|
+
def __matmul__(self, other: float):
|
|
651
|
+
return self.n2p(other)
|
|
652
|
+
|
|
653
|
+
def __rmatmul__(self, other: Point3DLike | Mobject):
|
|
654
|
+
if isinstance(other, Mobject):
|
|
655
|
+
other = other.get_center()
|
|
656
|
+
return self.p2n(other)
|
|
657
|
+
|
|
644
658
|
|
|
645
659
|
class UnitInterval(NumberLine):
|
|
646
660
|
def __init__(
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
__all__ = ["SampleSpace", "BarChart"]
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from collections.abc import Iterable, MutableSequence, Sequence
|
|
9
9
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
@@ -319,7 +319,6 @@ class BarChart(Axes):
|
|
|
319
319
|
Primarily used when the bars are initialized with ``self._add_bars``
|
|
320
320
|
or updated via ``self.change_bar_values``.
|
|
321
321
|
"""
|
|
322
|
-
|
|
323
322
|
self.bars.set_color_by_gradient(*self.bar_colors)
|
|
324
323
|
|
|
325
324
|
def _add_x_axis_labels(self):
|
|
@@ -329,7 +328,6 @@ class BarChart(Axes):
|
|
|
329
328
|
|
|
330
329
|
UP for negative values and DOWN for positive values.
|
|
331
330
|
"""
|
|
332
|
-
|
|
333
331
|
val_range = np.arange(
|
|
334
332
|
0.5, len(self.bar_names), 1
|
|
335
333
|
) # 0.5 shifted so that labels are centered, not on ticks
|
|
@@ -339,10 +337,7 @@ class BarChart(Axes):
|
|
|
339
337
|
for i, (value, bar_name) in enumerate(zip(val_range, self.bar_names)):
|
|
340
338
|
# to accommodate negative bars, the label may need to be
|
|
341
339
|
# below or above the x_axis depending on the value of the bar
|
|
342
|
-
if self.values[i] < 0
|
|
343
|
-
direction = UP
|
|
344
|
-
else:
|
|
345
|
-
direction = DOWN
|
|
340
|
+
direction = UP if self.values[i] < 0 else DOWN
|
|
346
341
|
bar_name_label = self.x_axis.label_constructor(bar_name)
|
|
347
342
|
|
|
348
343
|
bar_name_label.font_size = self.x_axis.font_size
|
|
@@ -372,7 +367,6 @@ class BarChart(Axes):
|
|
|
372
367
|
Rectangle
|
|
373
368
|
A positioned rectangle representing a bar on the chart.
|
|
374
369
|
"""
|
|
375
|
-
|
|
376
370
|
# bar measurements relative to the axis
|
|
377
371
|
|
|
378
372
|
# distance from between the y-axis and the top of the bar
|
|
@@ -435,7 +429,6 @@ class BarChart(Axes):
|
|
|
435
429
|
|
|
436
430
|
self.add(chart, c_bar_lbls)
|
|
437
431
|
"""
|
|
438
|
-
|
|
439
432
|
bar_labels = VGroup()
|
|
440
433
|
for bar, value in zip(self.bars, self.values):
|
|
441
434
|
bar_lbl = label_constructor(str(value))
|
|
@@ -483,7 +476,6 @@ class BarChart(Axes):
|
|
|
483
476
|
chart.change_bar_values(list(reversed(values)))
|
|
484
477
|
self.add(chart.get_bar_labels(font_size=24))
|
|
485
478
|
"""
|
|
486
|
-
|
|
487
479
|
for i, (bar, value) in enumerate(zip(self.bars, values)):
|
|
488
480
|
chart_val = self.values[i]
|
|
489
481
|
|