manim 0.17.0__py3-none-any.whl → 0.19.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- manim/__init__.py +11 -6
- manim/__main__.py +62 -19
- manim/_config/__init__.py +10 -9
- manim/_config/cli_colors.py +26 -9
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +23 -13
- manim/_config/utils.py +662 -468
- manim/animation/animation.py +164 -18
- manim/animation/changing.py +34 -23
- manim/animation/composition.py +265 -67
- manim/animation/creation.py +208 -26
- manim/animation/fading.py +16 -18
- manim/animation/growing.py +35 -15
- manim/animation/indication.py +150 -76
- manim/animation/movement.py +56 -22
- manim/animation/numbers.py +64 -6
- manim/animation/rotation.py +78 -7
- manim/animation/specialized.py +6 -7
- manim/animation/speedmodifier.py +13 -10
- manim/animation/transform.py +14 -11
- manim/animation/transform_matching_parts.py +3 -4
- manim/animation/updaters/mobject_update_utils.py +152 -30
- manim/animation/updaters/update.py +10 -7
- manim/camera/camera.py +182 -118
- manim/camera/mapping_camera.py +34 -3
- manim/camera/moving_camera.py +95 -74
- manim/camera/multi_camera.py +23 -15
- manim/camera/three_d_camera.py +70 -52
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +76 -44
- manim/cli/checkhealth/checks.py +192 -0
- manim/cli/checkhealth/commands.py +90 -0
- manim/cli/default_group.py +158 -25
- manim/cli/init/commands.py +33 -25
- manim/cli/plugins/commands.py +16 -3
- manim/cli/render/commands.py +72 -60
- manim/cli/render/ease_of_access_options.py +4 -3
- manim/cli/render/global_options.py +59 -17
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +98 -33
- manim/constants.py +109 -59
- manim/data_structures.py +31 -0
- manim/mobject/frame.py +8 -5
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +277 -135
- manim/mobject/geometry/boolean_ops.py +32 -31
- manim/mobject/geometry/labeled.py +376 -0
- manim/mobject/geometry/line.py +192 -87
- manim/mobject/geometry/polygram.py +224 -58
- manim/mobject/geometry/shape_matchers.py +61 -25
- manim/mobject/geometry/tips.py +122 -48
- manim/mobject/graph.py +1027 -419
- manim/mobject/graphing/coordinate_systems.py +533 -278
- manim/mobject/graphing/functions.py +53 -32
- manim/mobject/graphing/number_line.py +123 -65
- manim/mobject/graphing/probability.py +88 -62
- manim/mobject/graphing/scale.py +33 -19
- manim/mobject/logo.py +118 -28
- manim/mobject/matrix.py +87 -83
- manim/mobject/mobject.py +912 -442
- manim/mobject/opengl/dot_cloud.py +16 -5
- manim/mobject/opengl/opengl_compatibility.py +4 -2
- manim/mobject/opengl/opengl_geometry.py +254 -153
- manim/mobject/opengl/opengl_image_mobject.py +3 -1
- manim/mobject/opengl/opengl_mobject.py +779 -482
- manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
- manim/mobject/opengl/opengl_surface.py +14 -92
- manim/mobject/opengl/opengl_three_dimensions.py +12 -8
- manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
- manim/mobject/svg/brace.py +173 -41
- manim/mobject/svg/svg_mobject.py +139 -53
- manim/mobject/table.py +61 -68
- manim/mobject/text/code_mobject.py +193 -539
- manim/mobject/text/numbers.py +81 -34
- manim/mobject/text/tex_mobject.py +130 -78
- manim/mobject/text/text_mobject.py +288 -164
- manim/mobject/three_d/polyhedra.py +111 -13
- manim/mobject/three_d/three_d_utils.py +17 -8
- manim/mobject/three_d/three_dimensions.py +239 -106
- manim/mobject/types/image_mobject.py +50 -30
- manim/mobject/types/point_cloud_mobject.py +120 -75
- manim/mobject/types/vectorized_mobject.py +841 -408
- manim/mobject/value_tracker.py +105 -38
- manim/mobject/vector_field.py +50 -31
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +10 -14
- manim/renderer/cairo_renderer.py +65 -50
- manim/renderer/opengl_renderer.py +89 -69
- manim/renderer/opengl_renderer_window.py +39 -18
- manim/renderer/shader.py +123 -87
- manim/renderer/shader_wrapper.py +44 -28
- manim/renderer/vectorized_mobject_rendering.py +38 -10
- manim/scene/moving_camera_scene.py +32 -3
- manim/scene/scene.py +507 -242
- manim/scene/scene_file_writer.py +371 -220
- manim/scene/section.py +20 -16
- manim/scene/three_d_scene.py +14 -22
- manim/scene/vector_space_scene.py +223 -129
- manim/scene/zoomed_scene.py +46 -41
- manim/typing.py +990 -0
- manim/utils/bezier.py +1823 -371
- manim/utils/caching.py +12 -5
- manim/utils/color/AS2700.py +236 -0
- manim/utils/color/BS381.py +318 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +533 -0
- manim/utils/color/XKCD.py +952 -0
- manim/utils/color/__init__.py +61 -0
- manim/utils/color/core.py +1667 -0
- manim/utils/color/manim_colors.py +218 -0
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +39 -19
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +86 -39
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +236 -0
- manim/utils/docbuild/autocolor_directive.py +99 -0
- manim/utils/docbuild/manim_directive.py +94 -41
- manim/utils/docbuild/module_parsing.py +245 -0
- manim/utils/exceptions.py +6 -0
- manim/utils/family.py +5 -3
- manim/utils/family_ops.py +17 -4
- manim/utils/file_ops.py +27 -17
- manim/utils/hashing.py +55 -45
- manim/utils/images.py +13 -7
- manim/utils/ipython_magic.py +13 -7
- manim/utils/iterables.py +163 -120
- manim/utils/module_ops.py +66 -24
- manim/utils/opengl.py +77 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +30 -33
- manim/utils/polylabel.py +235 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +98 -32
- manim/utils/simple_functions.py +25 -33
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +188 -115
- manim/utils/testing/__init__.py +17 -0
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +34 -18
- manim/utils/testing/frames_comparison.py +37 -19
- manim/utils/tex.py +130 -198
- manim/utils/tex_file_writing.py +77 -47
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
- manim-0.19.1.dist-info/RECORD +220 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
- manim-0.19.1.dist-info/entry_points.txt +3 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
- manim/cli/new/group.py +0 -189
- manim/communitycolors.py +0 -9
- manim/gui/__init__.py +0 -0
- manim/gui/gui.py +0 -82
- manim/plugins/import_plugins.py +0 -43
- manim/utils/color.py +0 -552
- manim-0.17.0.dist-info/RECORD +0 -206
- manim-0.17.0.dist-info/entry_points.txt +0 -4
- /manim/cli/{new → checkhealth}/__init__.py +0 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
manim/mobject/geometry/line.py
CHANGED
|
@@ -14,10 +14,9 @@ __all__ = [
|
|
|
14
14
|
"RightAngle",
|
|
15
15
|
]
|
|
16
16
|
|
|
17
|
-
from typing import Any,
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
|
-
from colour import Color
|
|
21
20
|
|
|
22
21
|
from manim import config
|
|
23
22
|
from manim.constants import *
|
|
@@ -27,20 +26,87 @@ from manim.mobject.mobject import Mobject
|
|
|
27
26
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
28
27
|
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
29
28
|
from manim.mobject.types.vectorized_mobject import DashedVMobject, VGroup, VMobject
|
|
30
|
-
from manim.utils.color import
|
|
31
|
-
from manim.utils.color import Colors
|
|
29
|
+
from manim.utils.color import WHITE
|
|
32
30
|
from manim.utils.space_ops import angle_of_vector, line_intersection, normalize
|
|
33
31
|
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from typing_extensions import Self, TypeAlias
|
|
34
|
+
|
|
35
|
+
from manim.typing import Point3D, Point3DLike, Vector2DLike, Vector3D, Vector3DLike
|
|
36
|
+
from manim.utils.color import ParsableManimColor
|
|
37
|
+
|
|
38
|
+
from ..matrix import Matrix # Avoid circular import
|
|
39
|
+
|
|
40
|
+
AngleQuadrant: TypeAlias = tuple[Literal[-1, 1], Literal[-1, 1]]
|
|
41
|
+
r"""A tuple of 2 integers which can be either +1 or -1, allowing to select
|
|
42
|
+
one of the 4 quadrants of the Cartesian plane.
|
|
43
|
+
|
|
44
|
+
Let :math:`L_1,\ L_2` be two lines defined by start points
|
|
45
|
+
:math:`S_1,\ S_2` and end points :math:`E_1,\ E_2`. We define the "positive
|
|
46
|
+
direction" of :math:`L_1` as the direction from :math:`S_1` to :math:`E_1`,
|
|
47
|
+
and its "negative direction" as the opposite one. We do the same with
|
|
48
|
+
:math:`L_2`.
|
|
49
|
+
|
|
50
|
+
If :math:`L_1` and :math:`L_2` intersect, they divide the plane into 4
|
|
51
|
+
quadrants. To pick one quadrant, choose the integers in this tuple in the
|
|
52
|
+
following way:
|
|
53
|
+
|
|
54
|
+
- If the 1st integer is +1, select one of the 2 quadrants towards the
|
|
55
|
+
positive direction of :math:`L_1`, i.e. closest to `E_1`. Otherwise, if
|
|
56
|
+
the 1st integer is -1, select one of the 2 quadrants towards the
|
|
57
|
+
negative direction of :math:`L_1`, i.e. closest to `S_1`.
|
|
58
|
+
|
|
59
|
+
- Similarly, the sign of the 2nd integer picks the positive or negative
|
|
60
|
+
direction of :math:`L_2` and, thus, selects one of the 2 quadrants
|
|
61
|
+
which are closest to :math:`E_2` or :math:`S_2` respectively.
|
|
62
|
+
"""
|
|
63
|
+
|
|
34
64
|
|
|
35
65
|
class Line(TipableVMobject):
|
|
36
|
-
|
|
66
|
+
"""A straight or curved line segment between two points or mobjects.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
start
|
|
71
|
+
The starting point or Mobject of the line.
|
|
72
|
+
end
|
|
73
|
+
The ending point or Mobject of the line.
|
|
74
|
+
buff
|
|
75
|
+
The distance to shorten the line from both ends.
|
|
76
|
+
path_arc
|
|
77
|
+
If nonzero, the line will be curved into an arc with this angle (in radians).
|
|
78
|
+
kwargs
|
|
79
|
+
Additional arguments to be passed to :class:`TipableVMobject`
|
|
80
|
+
|
|
81
|
+
Examples
|
|
82
|
+
--------
|
|
83
|
+
.. manim:: LineExample
|
|
84
|
+
:save_last_frame:
|
|
85
|
+
|
|
86
|
+
class LineExample(Scene):
|
|
87
|
+
def construct(self):
|
|
88
|
+
line1 = Line(LEFT*2, RIGHT*2)
|
|
89
|
+
line2 = Line(LEFT*2, RIGHT*2, buff=0.5)
|
|
90
|
+
line3 = Line(LEFT*2, RIGHT*2, path_arc=PI/2)
|
|
91
|
+
grp = VGroup(line1,line2,line3).arrange(DOWN, buff=2)
|
|
92
|
+
self.add(grp)
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __init__(
|
|
96
|
+
self,
|
|
97
|
+
start: Point3DLike | Mobject = LEFT,
|
|
98
|
+
end: Point3DLike | Mobject = RIGHT,
|
|
99
|
+
buff: float = 0,
|
|
100
|
+
path_arc: float = 0,
|
|
101
|
+
**kwargs: Any,
|
|
102
|
+
) -> None:
|
|
37
103
|
self.dim = 3
|
|
38
104
|
self.buff = buff
|
|
39
105
|
self.path_arc = path_arc
|
|
40
106
|
self._set_start_and_end_attrs(start, end)
|
|
41
107
|
super().__init__(**kwargs)
|
|
42
108
|
|
|
43
|
-
def generate_points(self):
|
|
109
|
+
def generate_points(self) -> None:
|
|
44
110
|
self.set_points_by_ends(
|
|
45
111
|
start=self.start,
|
|
46
112
|
end=self.end,
|
|
@@ -48,33 +114,52 @@ class Line(TipableVMobject):
|
|
|
48
114
|
path_arc=self.path_arc,
|
|
49
115
|
)
|
|
50
116
|
|
|
51
|
-
def set_points_by_ends(
|
|
117
|
+
def set_points_by_ends(
|
|
118
|
+
self,
|
|
119
|
+
start: Point3DLike | Mobject,
|
|
120
|
+
end: Point3DLike | Mobject,
|
|
121
|
+
buff: float = 0,
|
|
122
|
+
path_arc: float = 0,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Sets the points of the line based on its start and end points.
|
|
125
|
+
Unlike :meth:`put_start_and_end_on`, this method respects `self.buff` and
|
|
126
|
+
Mobject bounding boxes.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
start
|
|
131
|
+
The start point or Mobject of the line.
|
|
132
|
+
end
|
|
133
|
+
The end point or Mobject of the line.
|
|
134
|
+
buff
|
|
135
|
+
The empty space between the start and end of the line, by default 0.
|
|
136
|
+
path_arc
|
|
137
|
+
The angle of a circle spanned by this arc, by default 0 which is a straight line.
|
|
138
|
+
"""
|
|
139
|
+
self._set_start_and_end_attrs(start, end)
|
|
52
140
|
if path_arc:
|
|
53
141
|
arc = ArcBetweenPoints(self.start, self.end, angle=self.path_arc)
|
|
54
142
|
self.set_points(arc.points)
|
|
55
143
|
else:
|
|
56
|
-
self.set_points_as_corners([start, end])
|
|
144
|
+
self.set_points_as_corners(np.asarray([self.start, self.end]))
|
|
57
145
|
|
|
58
146
|
self._account_for_buff(buff)
|
|
59
147
|
|
|
60
|
-
init_points
|
|
148
|
+
def init_points(self) -> None:
|
|
149
|
+
self.generate_points()
|
|
61
150
|
|
|
62
|
-
def _account_for_buff(self, buff):
|
|
63
|
-
if buff
|
|
151
|
+
def _account_for_buff(self, buff: float) -> None:
|
|
152
|
+
if buff <= 0:
|
|
64
153
|
return
|
|
65
|
-
|
|
66
|
-
if self.path_arc == 0:
|
|
67
|
-
length = self.get_length()
|
|
68
|
-
else:
|
|
69
|
-
length = self.get_arc_length()
|
|
70
|
-
#
|
|
154
|
+
length = self.get_length() if self.path_arc == 0 else self.get_arc_length()
|
|
71
155
|
if length < 2 * buff:
|
|
72
156
|
return
|
|
73
157
|
buff_proportion = buff / length
|
|
74
158
|
self.pointwise_become_partial(self, buff_proportion, 1 - buff_proportion)
|
|
75
|
-
return self
|
|
76
159
|
|
|
77
|
-
def _set_start_and_end_attrs(
|
|
160
|
+
def _set_start_and_end_attrs(
|
|
161
|
+
self, start: Point3DLike | Mobject, end: Point3DLike | Mobject
|
|
162
|
+
) -> None:
|
|
78
163
|
# If either start or end are Mobjects, this
|
|
79
164
|
# gives their centers
|
|
80
165
|
rough_start = self._pointify(start)
|
|
@@ -88,9 +173,9 @@ class Line(TipableVMobject):
|
|
|
88
173
|
|
|
89
174
|
def _pointify(
|
|
90
175
|
self,
|
|
91
|
-
mob_or_point: Mobject |
|
|
92
|
-
direction:
|
|
93
|
-
) ->
|
|
176
|
+
mob_or_point: Mobject | Point3DLike,
|
|
177
|
+
direction: Vector3DLike | None = None,
|
|
178
|
+
) -> Point3D:
|
|
94
179
|
"""Transforms a mobject into its corresponding point. Does nothing if a point is passed.
|
|
95
180
|
|
|
96
181
|
``direction`` determines the location of the point along its bounding box in that direction.
|
|
@@ -110,11 +195,15 @@ class Line(TipableVMobject):
|
|
|
110
195
|
return mob.get_boundary_point(direction)
|
|
111
196
|
return np.array(mob_or_point)
|
|
112
197
|
|
|
113
|
-
def set_path_arc(self, new_value):
|
|
198
|
+
def set_path_arc(self, new_value: float) -> None:
|
|
114
199
|
self.path_arc = new_value
|
|
115
200
|
self.init_points()
|
|
116
201
|
|
|
117
|
-
def put_start_and_end_on(
|
|
202
|
+
def put_start_and_end_on(
|
|
203
|
+
self,
|
|
204
|
+
start: Point3DLike,
|
|
205
|
+
end: Point3DLike,
|
|
206
|
+
) -> Self:
|
|
118
207
|
"""Sets starts and end coordinates of a line.
|
|
119
208
|
|
|
120
209
|
Examples
|
|
@@ -140,21 +229,21 @@ class Line(TipableVMobject):
|
|
|
140
229
|
if np.all(curr_start == curr_end):
|
|
141
230
|
# TODO, any problems with resetting
|
|
142
231
|
# these attrs?
|
|
143
|
-
self.start = start
|
|
144
|
-
self.end = end
|
|
232
|
+
self.start = np.asarray(start)
|
|
233
|
+
self.end = np.asarray(end)
|
|
145
234
|
self.generate_points()
|
|
146
235
|
return super().put_start_and_end_on(start, end)
|
|
147
236
|
|
|
148
|
-
def get_vector(self):
|
|
237
|
+
def get_vector(self) -> Vector3D:
|
|
149
238
|
return self.get_end() - self.get_start()
|
|
150
239
|
|
|
151
|
-
def get_unit_vector(self):
|
|
240
|
+
def get_unit_vector(self) -> Vector3D:
|
|
152
241
|
return normalize(self.get_vector())
|
|
153
242
|
|
|
154
|
-
def get_angle(self):
|
|
243
|
+
def get_angle(self) -> float:
|
|
155
244
|
return angle_of_vector(self.get_vector())
|
|
156
245
|
|
|
157
|
-
def get_projection(self, point:
|
|
246
|
+
def get_projection(self, point: Point3DLike) -> Point3D:
|
|
158
247
|
"""Returns the projection of a point onto a line.
|
|
159
248
|
|
|
160
249
|
Parameters
|
|
@@ -162,16 +251,15 @@ class Line(TipableVMobject):
|
|
|
162
251
|
point
|
|
163
252
|
The point to which the line is projected.
|
|
164
253
|
"""
|
|
165
|
-
|
|
166
254
|
start = self.get_start()
|
|
167
255
|
end = self.get_end()
|
|
168
256
|
unit_vect = normalize(end - start)
|
|
169
|
-
return start + np.dot(point - start, unit_vect) * unit_vect
|
|
257
|
+
return start + float(np.dot(point - start, unit_vect)) * unit_vect
|
|
170
258
|
|
|
171
|
-
def get_slope(self):
|
|
172
|
-
return np.tan(self.get_angle())
|
|
259
|
+
def get_slope(self) -> float:
|
|
260
|
+
return float(np.tan(self.get_angle()))
|
|
173
261
|
|
|
174
|
-
def set_angle(self, angle, about_point=None):
|
|
262
|
+
def set_angle(self, angle: float, about_point: Point3DLike | None = None) -> Self:
|
|
175
263
|
if about_point is None:
|
|
176
264
|
about_point = self.get_start()
|
|
177
265
|
|
|
@@ -182,8 +270,9 @@ class Line(TipableVMobject):
|
|
|
182
270
|
|
|
183
271
|
return self
|
|
184
272
|
|
|
185
|
-
def set_length(self, length):
|
|
186
|
-
|
|
273
|
+
def set_length(self, length: float) -> Self:
|
|
274
|
+
scale_factor: float = length / self.get_length()
|
|
275
|
+
return self.scale(scale_factor)
|
|
187
276
|
|
|
188
277
|
|
|
189
278
|
class DashedLine(Line):
|
|
@@ -225,8 +314,8 @@ class DashedLine(Line):
|
|
|
225
314
|
*args: Any,
|
|
226
315
|
dash_length: float = DEFAULT_DASH_LENGTH,
|
|
227
316
|
dashed_ratio: float = 0.5,
|
|
228
|
-
**kwargs,
|
|
229
|
-
):
|
|
317
|
+
**kwargs: Any,
|
|
318
|
+
) -> None:
|
|
230
319
|
self.dash_length = dash_length
|
|
231
320
|
self.dashed_ratio = dashed_ratio
|
|
232
321
|
super().__init__(*args, **kwargs)
|
|
@@ -248,14 +337,13 @@ class DashedLine(Line):
|
|
|
248
337
|
>>> DashedLine()._calculate_num_dashes()
|
|
249
338
|
20
|
|
250
339
|
"""
|
|
251
|
-
|
|
252
340
|
# Minimum number of dashes has to be 2
|
|
253
341
|
return max(
|
|
254
342
|
2,
|
|
255
343
|
int(np.ceil((self.get_length() / self.dash_length) * self.dashed_ratio)),
|
|
256
344
|
)
|
|
257
345
|
|
|
258
|
-
def get_start(self) ->
|
|
346
|
+
def get_start(self) -> Point3D:
|
|
259
347
|
"""Returns the start point of the line.
|
|
260
348
|
|
|
261
349
|
Examples
|
|
@@ -265,13 +353,12 @@ class DashedLine(Line):
|
|
|
265
353
|
>>> DashedLine().get_start()
|
|
266
354
|
array([-1., 0., 0.])
|
|
267
355
|
"""
|
|
268
|
-
|
|
269
356
|
if len(self.submobjects) > 0:
|
|
270
357
|
return self.submobjects[0].get_start()
|
|
271
358
|
else:
|
|
272
359
|
return super().get_start()
|
|
273
360
|
|
|
274
|
-
def get_end(self) ->
|
|
361
|
+
def get_end(self) -> Point3D:
|
|
275
362
|
"""Returns the end point of the line.
|
|
276
363
|
|
|
277
364
|
Examples
|
|
@@ -281,13 +368,12 @@ class DashedLine(Line):
|
|
|
281
368
|
>>> DashedLine().get_end()
|
|
282
369
|
array([1., 0., 0.])
|
|
283
370
|
"""
|
|
284
|
-
|
|
285
371
|
if len(self.submobjects) > 0:
|
|
286
372
|
return self.submobjects[-1].get_end()
|
|
287
373
|
else:
|
|
288
374
|
return super().get_end()
|
|
289
375
|
|
|
290
|
-
def get_first_handle(self) ->
|
|
376
|
+
def get_first_handle(self) -> Point3D:
|
|
291
377
|
"""Returns the point of the first handle.
|
|
292
378
|
|
|
293
379
|
Examples
|
|
@@ -297,10 +383,13 @@ class DashedLine(Line):
|
|
|
297
383
|
>>> DashedLine().get_first_handle()
|
|
298
384
|
array([-0.98333333, 0. , 0. ])
|
|
299
385
|
"""
|
|
386
|
+
# Type inference of extracting an element from a list, is not
|
|
387
|
+
# supported by numpy, see this numpy issue
|
|
388
|
+
# https://github.com/numpy/numpy/issues/16544
|
|
389
|
+
first_handle: Point3D = self.submobjects[0].points[1]
|
|
390
|
+
return first_handle
|
|
300
391
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
def get_last_handle(self) -> np.ndarray:
|
|
392
|
+
def get_last_handle(self) -> Point3D:
|
|
304
393
|
"""Returns the point of the last handle.
|
|
305
394
|
|
|
306
395
|
Examples
|
|
@@ -310,8 +399,11 @@ class DashedLine(Line):
|
|
|
310
399
|
>>> DashedLine().get_last_handle()
|
|
311
400
|
array([0.98333333, 0. , 0. ])
|
|
312
401
|
"""
|
|
313
|
-
|
|
314
|
-
|
|
402
|
+
# Type inference of extracting an element from a list, is not
|
|
403
|
+
# supported by numpy, see this numpy issue
|
|
404
|
+
# https://github.com/numpy/numpy/issues/16544
|
|
405
|
+
last_handle: Point3D = self.submobjects[-1].points[2]
|
|
406
|
+
return last_handle
|
|
315
407
|
|
|
316
408
|
|
|
317
409
|
class TangentLine(Line):
|
|
@@ -353,8 +445,8 @@ class TangentLine(Line):
|
|
|
353
445
|
alpha: float,
|
|
354
446
|
length: float = 1,
|
|
355
447
|
d_alpha: float = 1e-6,
|
|
356
|
-
**kwargs,
|
|
357
|
-
):
|
|
448
|
+
**kwargs: Any,
|
|
449
|
+
) -> None:
|
|
358
450
|
self.length = length
|
|
359
451
|
self.d_alpha = d_alpha
|
|
360
452
|
da = self.d_alpha
|
|
@@ -396,10 +488,10 @@ class Elbow(VMobject, metaclass=ConvertToOpenGL):
|
|
|
396
488
|
self.add(elbow_group)
|
|
397
489
|
"""
|
|
398
490
|
|
|
399
|
-
def __init__(self, width: float = 0.2, angle: float = 0, **kwargs):
|
|
491
|
+
def __init__(self, width: float = 0.2, angle: float = 0, **kwargs: Any) -> None:
|
|
400
492
|
self.angle = angle
|
|
401
493
|
super().__init__(**kwargs)
|
|
402
|
-
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
|
|
494
|
+
self.set_points_as_corners(np.array([UP, UP + RIGHT, RIGHT]))
|
|
403
495
|
self.scale_to_fit_width(width, about_point=ORIGIN)
|
|
404
496
|
self.rotate(self.angle, about_point=ORIGIN)
|
|
405
497
|
|
|
@@ -499,19 +591,19 @@ class Arrow(Line):
|
|
|
499
591
|
buff: float = MED_SMALL_BUFF,
|
|
500
592
|
max_tip_length_to_length_ratio: float = 0.25,
|
|
501
593
|
max_stroke_width_to_length_ratio: float = 5,
|
|
502
|
-
**kwargs,
|
|
503
|
-
):
|
|
594
|
+
**kwargs: Any,
|
|
595
|
+
) -> None:
|
|
504
596
|
self.max_tip_length_to_length_ratio = max_tip_length_to_length_ratio
|
|
505
597
|
self.max_stroke_width_to_length_ratio = max_stroke_width_to_length_ratio
|
|
506
598
|
tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
|
|
507
|
-
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs)
|
|
599
|
+
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs) # type: ignore[misc]
|
|
508
600
|
# TODO, should this be affected when
|
|
509
601
|
# Arrow.set_stroke is called?
|
|
510
602
|
self.initial_stroke_width = self.stroke_width
|
|
511
603
|
self.add_tip(tip_shape=tip_shape)
|
|
512
604
|
self._set_stroke_width_from_length()
|
|
513
605
|
|
|
514
|
-
def scale(self, factor, scale_tips=False, **kwargs):
|
|
606
|
+
def scale(self, factor: float, scale_tips: bool = False, **kwargs: Any) -> Self: # type: ignore[override]
|
|
515
607
|
r"""Scale an arrow, but keep stroke width and arrow tip size fixed.
|
|
516
608
|
|
|
517
609
|
|
|
@@ -561,7 +653,7 @@ class Arrow(Line):
|
|
|
561
653
|
self.add_tip(tip=old_tips[1], at_start=True)
|
|
562
654
|
return self
|
|
563
655
|
|
|
564
|
-
def get_normal_vector(self) ->
|
|
656
|
+
def get_normal_vector(self) -> Vector3D:
|
|
565
657
|
"""Returns the normal of a vector.
|
|
566
658
|
|
|
567
659
|
Examples
|
|
@@ -571,11 +663,10 @@ class Arrow(Line):
|
|
|
571
663
|
>>> np.round(Arrow().get_normal_vector()) + 0. # add 0. to avoid negative 0 in output
|
|
572
664
|
array([ 0., 0., -1.])
|
|
573
665
|
"""
|
|
574
|
-
|
|
575
666
|
p0, p1, p2 = self.tip.get_start_anchors()[:3]
|
|
576
667
|
return normalize(np.cross(p2 - p1, p1 - p0))
|
|
577
668
|
|
|
578
|
-
def reset_normal_vector(self):
|
|
669
|
+
def reset_normal_vector(self) -> Self:
|
|
579
670
|
"""Resets the normal of a vector"""
|
|
580
671
|
self.normal_vector = self.get_normal_vector()
|
|
581
672
|
return self
|
|
@@ -591,15 +682,18 @@ class Arrow(Line):
|
|
|
591
682
|
>>> Arrow().get_default_tip_length()
|
|
592
683
|
0.35
|
|
593
684
|
"""
|
|
594
|
-
|
|
595
685
|
max_ratio = self.max_tip_length_to_length_ratio
|
|
596
686
|
return min(self.tip_length, max_ratio * self.get_length())
|
|
597
687
|
|
|
598
|
-
def _set_stroke_width_from_length(self):
|
|
688
|
+
def _set_stroke_width_from_length(self) -> Self:
|
|
599
689
|
"""Sets stroke width based on length."""
|
|
600
690
|
max_ratio = self.max_stroke_width_to_length_ratio
|
|
601
691
|
if config.renderer == RendererType.OPENGL:
|
|
602
|
-
self
|
|
692
|
+
# Mypy does not recognize that the self object in this case
|
|
693
|
+
# is a OpenGLVMobject and that the set_stroke method is
|
|
694
|
+
# defined here:
|
|
695
|
+
# mobject/opengl/opengl_vectorized_mobject.py#L248
|
|
696
|
+
self.set_stroke( # type: ignore[call-arg]
|
|
603
697
|
width=min(self.initial_stroke_width, max_ratio * self.get_length()),
|
|
604
698
|
recurse=False,
|
|
605
699
|
)
|
|
@@ -614,6 +708,11 @@ class Arrow(Line):
|
|
|
614
708
|
class Vector(Arrow):
|
|
615
709
|
"""A vector specialized for use in graphs.
|
|
616
710
|
|
|
711
|
+
.. caution::
|
|
712
|
+
Do not confuse with the :class:`~.Vector2D`,
|
|
713
|
+
:class:`~.Vector3D` or :class:`~.VectorND` type aliases,
|
|
714
|
+
which are not Mobjects!
|
|
715
|
+
|
|
617
716
|
Parameters
|
|
618
717
|
----------
|
|
619
718
|
direction
|
|
@@ -636,7 +735,12 @@ class Vector(Arrow):
|
|
|
636
735
|
self.add(plane, vector_1, vector_2)
|
|
637
736
|
"""
|
|
638
737
|
|
|
639
|
-
def __init__(
|
|
738
|
+
def __init__(
|
|
739
|
+
self,
|
|
740
|
+
direction: Vector2DLike | Vector3DLike = RIGHT,
|
|
741
|
+
buff: float = 0,
|
|
742
|
+
**kwargs: Any,
|
|
743
|
+
) -> None:
|
|
640
744
|
self.buff = buff
|
|
641
745
|
if len(direction) == 2:
|
|
642
746
|
direction = np.hstack([direction, 0])
|
|
@@ -647,9 +751,9 @@ class Vector(Arrow):
|
|
|
647
751
|
self,
|
|
648
752
|
integer_labels: bool = True,
|
|
649
753
|
n_dim: int = 2,
|
|
650
|
-
color:
|
|
651
|
-
**kwargs,
|
|
652
|
-
):
|
|
754
|
+
color: ParsableManimColor | None = None,
|
|
755
|
+
**kwargs: Any,
|
|
756
|
+
) -> Matrix:
|
|
653
757
|
"""Creates a label based on the coordinates of the vector.
|
|
654
758
|
|
|
655
759
|
Parameters
|
|
@@ -684,7 +788,6 @@ class Vector(Arrow):
|
|
|
684
788
|
|
|
685
789
|
self.add(plane, vec_1, vec_2, label_1, label_2)
|
|
686
790
|
"""
|
|
687
|
-
|
|
688
791
|
# avoiding circular imports
|
|
689
792
|
from ..matrix import Matrix
|
|
690
793
|
|
|
@@ -752,7 +855,7 @@ class DoubleArrow(Arrow):
|
|
|
752
855
|
self.add(box, d1, d2, d3)
|
|
753
856
|
"""
|
|
754
857
|
|
|
755
|
-
def __init__(self, *args: Any, **kwargs):
|
|
858
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
756
859
|
if "tip_shape_end" in kwargs:
|
|
757
860
|
kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
|
|
758
861
|
tip_shape_start = kwargs.pop("tip_shape_start", ArrowTriangleFilledTip)
|
|
@@ -873,16 +976,16 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
873
976
|
self,
|
|
874
977
|
line1: Line,
|
|
875
978
|
line2: Line,
|
|
876
|
-
radius: float = None,
|
|
877
|
-
quadrant:
|
|
979
|
+
radius: float | None = None,
|
|
980
|
+
quadrant: AngleQuadrant = (1, 1),
|
|
878
981
|
other_angle: bool = False,
|
|
879
982
|
dot: bool = False,
|
|
880
983
|
dot_radius: float | None = None,
|
|
881
984
|
dot_distance: float = 0.55,
|
|
882
|
-
dot_color:
|
|
985
|
+
dot_color: ParsableManimColor = WHITE,
|
|
883
986
|
elbow: bool = False,
|
|
884
|
-
**kwargs,
|
|
885
|
-
):
|
|
987
|
+
**kwargs: Any,
|
|
988
|
+
) -> None:
|
|
886
989
|
super().__init__(**kwargs)
|
|
887
990
|
self.lines = (line1, line2)
|
|
888
991
|
self.quadrant = quadrant
|
|
@@ -918,9 +1021,9 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
918
1021
|
+ quadrant[0] * radius * line1.get_unit_vector()
|
|
919
1022
|
+ quadrant[1] * radius * line2.get_unit_vector()
|
|
920
1023
|
)
|
|
921
|
-
angle_mobject = Elbow(**kwargs)
|
|
1024
|
+
angle_mobject: VMobject = Elbow(**kwargs)
|
|
922
1025
|
angle_mobject.set_points_as_corners(
|
|
923
|
-
[anchor_angle_1, anchor_middle, anchor_angle_2],
|
|
1026
|
+
np.array([anchor_angle_1, anchor_middle, anchor_angle_2]),
|
|
924
1027
|
)
|
|
925
1028
|
else:
|
|
926
1029
|
angle_1 = angle_of_vector(anchor_angle_1 - inter)
|
|
@@ -984,11 +1087,10 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
984
1087
|
>>> angle.get_lines()
|
|
985
1088
|
VGroup(Line, Line)
|
|
986
1089
|
"""
|
|
987
|
-
|
|
988
1090
|
return VGroup(*self.lines)
|
|
989
1091
|
|
|
990
1092
|
def get_value(self, degrees: bool = False) -> float:
|
|
991
|
-
"""Get the value of an angle of the :class:`Angle` class.
|
|
1093
|
+
r"""Get the value of an angle of the :class:`Angle` class.
|
|
992
1094
|
|
|
993
1095
|
Parameters
|
|
994
1096
|
----------
|
|
@@ -1013,21 +1115,18 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1013
1115
|
|
|
1014
1116
|
angle = Angle(line1, line2, radius=0.4)
|
|
1015
1117
|
|
|
1016
|
-
value = DecimalNumber(angle.get_value(degrees=True), unit="^{
|
|
1118
|
+
value = DecimalNumber(angle.get_value(degrees=True), unit=r"^{\circ}")
|
|
1017
1119
|
value.next_to(angle, UR)
|
|
1018
1120
|
|
|
1019
1121
|
self.add(line1, line2, angle, value)
|
|
1020
1122
|
"""
|
|
1021
|
-
|
|
1022
|
-
if degrees:
|
|
1023
|
-
return self.angle_value / DEGREES
|
|
1024
|
-
return self.angle_value
|
|
1123
|
+
return self.angle_value / DEGREES if degrees else self.angle_value
|
|
1025
1124
|
|
|
1026
1125
|
@staticmethod
|
|
1027
1126
|
def from_three_points(
|
|
1028
|
-
A:
|
|
1127
|
+
A: Point3DLike, B: Point3DLike, C: Point3DLike, **kwargs: Any
|
|
1029
1128
|
) -> Angle:
|
|
1030
|
-
"""The angle between the lines AB and BC.
|
|
1129
|
+
r"""The angle between the lines AB and BC.
|
|
1031
1130
|
|
|
1032
1131
|
This constructs the angle :math:`\\angle ABC`.
|
|
1033
1132
|
|
|
@@ -1101,5 +1200,11 @@ class RightAngle(Angle):
|
|
|
1101
1200
|
self.add(plots)
|
|
1102
1201
|
"""
|
|
1103
1202
|
|
|
1104
|
-
def __init__(
|
|
1203
|
+
def __init__(
|
|
1204
|
+
self,
|
|
1205
|
+
line1: Line,
|
|
1206
|
+
line2: Line,
|
|
1207
|
+
length: float | None = None,
|
|
1208
|
+
**kwargs: Any,
|
|
1209
|
+
) -> None:
|
|
1105
1210
|
super().__init__(line1, line2, radius=length, elbow=True, **kwargs)
|