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
manim/mobject/geometry/line.py
CHANGED
|
@@ -17,7 +17,6 @@ __all__ = [
|
|
|
17
17
|
from typing import TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
|
-
from typing_extensions import Self
|
|
21
20
|
|
|
22
21
|
from manim import config
|
|
23
22
|
from manim.constants import *
|
|
@@ -31,68 +30,115 @@ from manim.utils.color import WHITE
|
|
|
31
30
|
from manim.utils.space_ops import angle_of_vector, line_intersection, normalize
|
|
32
31
|
|
|
33
32
|
if TYPE_CHECKING:
|
|
34
|
-
from
|
|
33
|
+
from typing import Any
|
|
34
|
+
|
|
35
|
+
from typing_extensions import Literal, Self, TypeAlias
|
|
36
|
+
|
|
37
|
+
from manim.typing import Point2DLike, Point3D, Point3DLike, Vector3D
|
|
35
38
|
from manim.utils.color import ParsableManimColor
|
|
36
39
|
|
|
37
40
|
from ..matrix import Matrix # Avoid circular import
|
|
38
41
|
|
|
42
|
+
AngleQuadrant: TypeAlias = tuple[Literal[-1, 1], Literal[-1, 1]]
|
|
43
|
+
r"""A tuple of 2 integers which can be either +1 or -1, allowing to select
|
|
44
|
+
one of the 4 quadrants of the Cartesian plane.
|
|
45
|
+
|
|
46
|
+
Let :math:`L_1,\ L_2` be two lines defined by start points
|
|
47
|
+
:math:`S_1,\ S_2` and end points :math:`E_1,\ E_2`. We define the "positive
|
|
48
|
+
direction" of :math:`L_1` as the direction from :math:`S_1` to :math:`E_1`,
|
|
49
|
+
and its "negative direction" as the opposite one. We do the same with
|
|
50
|
+
:math:`L_2`.
|
|
51
|
+
|
|
52
|
+
If :math:`L_1` and :math:`L_2` intersect, they divide the plane into 4
|
|
53
|
+
quadrants. To pick one quadrant, choose the integers in this tuple in the
|
|
54
|
+
following way:
|
|
55
|
+
|
|
56
|
+
- If the 1st integer is +1, select one of the 2 quadrants towards the
|
|
57
|
+
positive direction of :math:`L_1`, i.e. closest to `E_1`. Otherwise, if
|
|
58
|
+
the 1st integer is -1, select one of the 2 quadrants towards the
|
|
59
|
+
negative direction of :math:`L_1`, i.e. closest to `S_1`.
|
|
60
|
+
|
|
61
|
+
- Similarly, the sign of the 2nd integer picks the positive or negative
|
|
62
|
+
direction of :math:`L_2` and, thus, selects one of the 2 quadrants
|
|
63
|
+
which are closest to :math:`E_2` or :math:`S_2` respectively.
|
|
64
|
+
"""
|
|
65
|
+
|
|
39
66
|
|
|
40
67
|
class Line(TipableVMobject):
|
|
41
68
|
def __init__(
|
|
42
69
|
self,
|
|
43
|
-
start:
|
|
44
|
-
end:
|
|
70
|
+
start: Point3DLike | Mobject = LEFT,
|
|
71
|
+
end: Point3DLike | Mobject = RIGHT,
|
|
45
72
|
buff: float = 0,
|
|
46
73
|
path_arc: float | None = None,
|
|
47
|
-
**kwargs,
|
|
74
|
+
**kwargs: Any,
|
|
48
75
|
) -> None:
|
|
49
76
|
self.dim = 3
|
|
50
77
|
self.buff = buff
|
|
51
78
|
self.path_arc = path_arc
|
|
52
79
|
self._set_start_and_end_attrs(start, end)
|
|
53
80
|
super().__init__(**kwargs)
|
|
81
|
+
# TODO: Deal with the situation where path_arc is None
|
|
54
82
|
|
|
55
83
|
def generate_points(self) -> None:
|
|
56
84
|
self.set_points_by_ends(
|
|
57
85
|
start=self.start,
|
|
58
86
|
end=self.end,
|
|
59
87
|
buff=self.buff,
|
|
60
|
-
path_arc=self.path_arc,
|
|
88
|
+
path_arc=self.path_arc, # type: ignore[arg-type]
|
|
61
89
|
)
|
|
62
90
|
|
|
63
91
|
def set_points_by_ends(
|
|
64
92
|
self,
|
|
65
|
-
start:
|
|
66
|
-
end:
|
|
93
|
+
start: Point3DLike | Mobject,
|
|
94
|
+
end: Point3DLike | Mobject,
|
|
67
95
|
buff: float = 0,
|
|
68
96
|
path_arc: float = 0,
|
|
69
97
|
) -> None:
|
|
98
|
+
"""Sets the points of the line based on its start and end points.
|
|
99
|
+
Unlike :meth:`put_start_and_end_on`, this method respects `self.buff` and
|
|
100
|
+
Mobject bounding boxes.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
start
|
|
105
|
+
The start point or Mobject of the line.
|
|
106
|
+
end
|
|
107
|
+
The end point or Mobject of the line.
|
|
108
|
+
buff
|
|
109
|
+
The empty space between the start and end of the line, by default 0.
|
|
110
|
+
path_arc
|
|
111
|
+
The angle of a circle spanned by this arc, by default 0 which is a straight line.
|
|
112
|
+
"""
|
|
113
|
+
self._set_start_and_end_attrs(start, end)
|
|
70
114
|
if path_arc:
|
|
115
|
+
# self.path_arc could potentially be None, which is not accepted
|
|
116
|
+
# as parameter.
|
|
117
|
+
assert self.path_arc is not None
|
|
71
118
|
arc = ArcBetweenPoints(self.start, self.end, angle=self.path_arc)
|
|
72
119
|
self.set_points(arc.points)
|
|
73
120
|
else:
|
|
74
|
-
self.set_points_as_corners([start, end])
|
|
121
|
+
self.set_points_as_corners(np.asarray([self.start, self.end]))
|
|
75
122
|
|
|
76
123
|
self._account_for_buff(buff)
|
|
77
124
|
|
|
78
125
|
init_points = generate_points
|
|
79
126
|
|
|
80
|
-
def _account_for_buff(self, buff: float) ->
|
|
127
|
+
def _account_for_buff(self, buff: float) -> None:
|
|
81
128
|
if buff == 0:
|
|
82
129
|
return
|
|
83
130
|
#
|
|
84
|
-
if self.path_arc == 0
|
|
85
|
-
length = self.get_length()
|
|
86
|
-
else:
|
|
87
|
-
length = self.get_arc_length()
|
|
131
|
+
length = self.get_length() if self.path_arc == 0 else self.get_arc_length()
|
|
88
132
|
#
|
|
89
133
|
if length < 2 * buff:
|
|
90
134
|
return
|
|
91
135
|
buff_proportion = buff / length
|
|
92
136
|
self.pointwise_become_partial(self, buff_proportion, 1 - buff_proportion)
|
|
93
|
-
return
|
|
137
|
+
return
|
|
94
138
|
|
|
95
|
-
def _set_start_and_end_attrs(
|
|
139
|
+
def _set_start_and_end_attrs(
|
|
140
|
+
self, start: Point3DLike | Mobject, end: Point3DLike | Mobject
|
|
141
|
+
) -> None:
|
|
96
142
|
# If either start or end are Mobjects, this
|
|
97
143
|
# gives their centers
|
|
98
144
|
rough_start = self._pointify(start)
|
|
@@ -106,8 +152,8 @@ class Line(TipableVMobject):
|
|
|
106
152
|
|
|
107
153
|
def _pointify(
|
|
108
154
|
self,
|
|
109
|
-
mob_or_point: Mobject |
|
|
110
|
-
direction:
|
|
155
|
+
mob_or_point: Mobject | Point3DLike,
|
|
156
|
+
direction: Vector3D | None = None,
|
|
111
157
|
) -> Point3D:
|
|
112
158
|
"""Transforms a mobject into its corresponding point. Does nothing if a point is passed.
|
|
113
159
|
|
|
@@ -132,7 +178,11 @@ class Line(TipableVMobject):
|
|
|
132
178
|
self.path_arc = new_value
|
|
133
179
|
self.init_points()
|
|
134
180
|
|
|
135
|
-
def put_start_and_end_on(
|
|
181
|
+
def put_start_and_end_on(
|
|
182
|
+
self,
|
|
183
|
+
start: Point3DLike,
|
|
184
|
+
end: Point3DLike,
|
|
185
|
+
) -> Self:
|
|
136
186
|
"""Sets starts and end coordinates of a line.
|
|
137
187
|
|
|
138
188
|
Examples
|
|
@@ -158,21 +208,21 @@ class Line(TipableVMobject):
|
|
|
158
208
|
if np.all(curr_start == curr_end):
|
|
159
209
|
# TODO, any problems with resetting
|
|
160
210
|
# these attrs?
|
|
161
|
-
self.start = start
|
|
162
|
-
self.end = end
|
|
211
|
+
self.start = np.asarray(start)
|
|
212
|
+
self.end = np.asarray(end)
|
|
163
213
|
self.generate_points()
|
|
164
214
|
return super().put_start_and_end_on(start, end)
|
|
165
215
|
|
|
166
|
-
def get_vector(self) ->
|
|
216
|
+
def get_vector(self) -> Vector3D:
|
|
167
217
|
return self.get_end() - self.get_start()
|
|
168
218
|
|
|
169
|
-
def get_unit_vector(self) ->
|
|
219
|
+
def get_unit_vector(self) -> Vector3D:
|
|
170
220
|
return normalize(self.get_vector())
|
|
171
221
|
|
|
172
222
|
def get_angle(self) -> float:
|
|
173
223
|
return angle_of_vector(self.get_vector())
|
|
174
224
|
|
|
175
|
-
def get_projection(self, point:
|
|
225
|
+
def get_projection(self, point: Point3DLike) -> Point3D:
|
|
176
226
|
"""Returns the projection of a point onto a line.
|
|
177
227
|
|
|
178
228
|
Parameters
|
|
@@ -180,16 +230,15 @@ class Line(TipableVMobject):
|
|
|
180
230
|
point
|
|
181
231
|
The point to which the line is projected.
|
|
182
232
|
"""
|
|
183
|
-
|
|
184
233
|
start = self.get_start()
|
|
185
234
|
end = self.get_end()
|
|
186
235
|
unit_vect = normalize(end - start)
|
|
187
|
-
return start + np.dot(point - start, unit_vect) * unit_vect
|
|
236
|
+
return start + float(np.dot(point - start, unit_vect)) * unit_vect
|
|
188
237
|
|
|
189
238
|
def get_slope(self) -> float:
|
|
190
|
-
return np.tan(self.get_angle())
|
|
239
|
+
return float(np.tan(self.get_angle()))
|
|
191
240
|
|
|
192
|
-
def set_angle(self, angle: float, about_point:
|
|
241
|
+
def set_angle(self, angle: float, about_point: Point3DLike | None = None) -> Self:
|
|
193
242
|
if about_point is None:
|
|
194
243
|
about_point = self.get_start()
|
|
195
244
|
|
|
@@ -201,7 +250,8 @@ class Line(TipableVMobject):
|
|
|
201
250
|
return self
|
|
202
251
|
|
|
203
252
|
def set_length(self, length: float) -> Self:
|
|
204
|
-
|
|
253
|
+
scale_factor: float = length / self.get_length()
|
|
254
|
+
return self.scale(scale_factor)
|
|
205
255
|
|
|
206
256
|
|
|
207
257
|
class DashedLine(Line):
|
|
@@ -240,10 +290,10 @@ class DashedLine(Line):
|
|
|
240
290
|
|
|
241
291
|
def __init__(
|
|
242
292
|
self,
|
|
243
|
-
*args,
|
|
293
|
+
*args: Any,
|
|
244
294
|
dash_length: float = DEFAULT_DASH_LENGTH,
|
|
245
295
|
dashed_ratio: float = 0.5,
|
|
246
|
-
**kwargs,
|
|
296
|
+
**kwargs: Any,
|
|
247
297
|
) -> None:
|
|
248
298
|
self.dash_length = dash_length
|
|
249
299
|
self.dashed_ratio = dashed_ratio
|
|
@@ -266,7 +316,6 @@ class DashedLine(Line):
|
|
|
266
316
|
>>> DashedLine()._calculate_num_dashes()
|
|
267
317
|
20
|
|
268
318
|
"""
|
|
269
|
-
|
|
270
319
|
# Minimum number of dashes has to be 2
|
|
271
320
|
return max(
|
|
272
321
|
2,
|
|
@@ -283,7 +332,6 @@ class DashedLine(Line):
|
|
|
283
332
|
>>> DashedLine().get_start()
|
|
284
333
|
array([-1., 0., 0.])
|
|
285
334
|
"""
|
|
286
|
-
|
|
287
335
|
if len(self.submobjects) > 0:
|
|
288
336
|
return self.submobjects[0].get_start()
|
|
289
337
|
else:
|
|
@@ -299,7 +347,6 @@ class DashedLine(Line):
|
|
|
299
347
|
>>> DashedLine().get_end()
|
|
300
348
|
array([1., 0., 0.])
|
|
301
349
|
"""
|
|
302
|
-
|
|
303
350
|
if len(self.submobjects) > 0:
|
|
304
351
|
return self.submobjects[-1].get_end()
|
|
305
352
|
else:
|
|
@@ -315,8 +362,11 @@ class DashedLine(Line):
|
|
|
315
362
|
>>> DashedLine().get_first_handle()
|
|
316
363
|
array([-0.98333333, 0. , 0. ])
|
|
317
364
|
"""
|
|
318
|
-
|
|
319
|
-
|
|
365
|
+
# Type inference of extracting an element from a list, is not
|
|
366
|
+
# supported by numpy, see this numpy issue
|
|
367
|
+
# https://github.com/numpy/numpy/issues/16544
|
|
368
|
+
first_handle: Point3D = self.submobjects[0].points[1]
|
|
369
|
+
return first_handle
|
|
320
370
|
|
|
321
371
|
def get_last_handle(self) -> Point3D:
|
|
322
372
|
"""Returns the point of the last handle.
|
|
@@ -328,8 +378,11 @@ class DashedLine(Line):
|
|
|
328
378
|
>>> DashedLine().get_last_handle()
|
|
329
379
|
array([0.98333333, 0. , 0. ])
|
|
330
380
|
"""
|
|
331
|
-
|
|
332
|
-
|
|
381
|
+
# Type inference of extracting an element from a list, is not
|
|
382
|
+
# supported by numpy, see this numpy issue
|
|
383
|
+
# https://github.com/numpy/numpy/issues/16544
|
|
384
|
+
last_handle: Point3D = self.submobjects[-1].points[2]
|
|
385
|
+
return last_handle
|
|
333
386
|
|
|
334
387
|
|
|
335
388
|
class TangentLine(Line):
|
|
@@ -371,7 +424,7 @@ class TangentLine(Line):
|
|
|
371
424
|
alpha: float,
|
|
372
425
|
length: float = 1,
|
|
373
426
|
d_alpha: float = 1e-6,
|
|
374
|
-
**kwargs,
|
|
427
|
+
**kwargs: Any,
|
|
375
428
|
) -> None:
|
|
376
429
|
self.length = length
|
|
377
430
|
self.d_alpha = d_alpha
|
|
@@ -414,10 +467,10 @@ class Elbow(VMobject, metaclass=ConvertToOpenGL):
|
|
|
414
467
|
self.add(elbow_group)
|
|
415
468
|
"""
|
|
416
469
|
|
|
417
|
-
def __init__(self, width: float = 0.2, angle: float = 0, **kwargs) -> None:
|
|
470
|
+
def __init__(self, width: float = 0.2, angle: float = 0, **kwargs: Any) -> None:
|
|
418
471
|
self.angle = angle
|
|
419
472
|
super().__init__(**kwargs)
|
|
420
|
-
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
|
|
473
|
+
self.set_points_as_corners(np.array([UP, UP + RIGHT, RIGHT]))
|
|
421
474
|
self.scale_to_fit_width(width, about_point=ORIGIN)
|
|
422
475
|
self.rotate(self.angle, about_point=ORIGIN)
|
|
423
476
|
|
|
@@ -512,24 +565,24 @@ class Arrow(Line):
|
|
|
512
565
|
|
|
513
566
|
def __init__(
|
|
514
567
|
self,
|
|
515
|
-
*args,
|
|
568
|
+
*args: Any,
|
|
516
569
|
stroke_width: float = 6,
|
|
517
570
|
buff: float = MED_SMALL_BUFF,
|
|
518
571
|
max_tip_length_to_length_ratio: float = 0.25,
|
|
519
572
|
max_stroke_width_to_length_ratio: float = 5,
|
|
520
|
-
**kwargs,
|
|
573
|
+
**kwargs: Any,
|
|
521
574
|
) -> None:
|
|
522
575
|
self.max_tip_length_to_length_ratio = max_tip_length_to_length_ratio
|
|
523
576
|
self.max_stroke_width_to_length_ratio = max_stroke_width_to_length_ratio
|
|
524
577
|
tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
|
|
525
|
-
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs)
|
|
578
|
+
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs) # type: ignore[misc]
|
|
526
579
|
# TODO, should this be affected when
|
|
527
580
|
# Arrow.set_stroke is called?
|
|
528
581
|
self.initial_stroke_width = self.stroke_width
|
|
529
582
|
self.add_tip(tip_shape=tip_shape)
|
|
530
583
|
self._set_stroke_width_from_length()
|
|
531
584
|
|
|
532
|
-
def scale(self, factor: float, scale_tips: bool = False, **kwargs) -> Self:
|
|
585
|
+
def scale(self, factor: float, scale_tips: bool = False, **kwargs: Any) -> Self: # type: ignore[override]
|
|
533
586
|
r"""Scale an arrow, but keep stroke width and arrow tip size fixed.
|
|
534
587
|
|
|
535
588
|
|
|
@@ -579,7 +632,7 @@ class Arrow(Line):
|
|
|
579
632
|
self.add_tip(tip=old_tips[1], at_start=True)
|
|
580
633
|
return self
|
|
581
634
|
|
|
582
|
-
def get_normal_vector(self) ->
|
|
635
|
+
def get_normal_vector(self) -> Vector3D:
|
|
583
636
|
"""Returns the normal of a vector.
|
|
584
637
|
|
|
585
638
|
Examples
|
|
@@ -589,7 +642,6 @@ class Arrow(Line):
|
|
|
589
642
|
>>> np.round(Arrow().get_normal_vector()) + 0. # add 0. to avoid negative 0 in output
|
|
590
643
|
array([ 0., 0., -1.])
|
|
591
644
|
"""
|
|
592
|
-
|
|
593
645
|
p0, p1, p2 = self.tip.get_start_anchors()[:3]
|
|
594
646
|
return normalize(np.cross(p2 - p1, p1 - p0))
|
|
595
647
|
|
|
@@ -609,7 +661,6 @@ class Arrow(Line):
|
|
|
609
661
|
>>> Arrow().get_default_tip_length()
|
|
610
662
|
0.35
|
|
611
663
|
"""
|
|
612
|
-
|
|
613
664
|
max_ratio = self.max_tip_length_to_length_ratio
|
|
614
665
|
return min(self.tip_length, max_ratio * self.get_length())
|
|
615
666
|
|
|
@@ -617,7 +668,11 @@ class Arrow(Line):
|
|
|
617
668
|
"""Sets stroke width based on length."""
|
|
618
669
|
max_ratio = self.max_stroke_width_to_length_ratio
|
|
619
670
|
if config.renderer == RendererType.OPENGL:
|
|
620
|
-
self
|
|
671
|
+
# Mypy does not recognize that the self object in this case
|
|
672
|
+
# is a OpenGLVMobject and that the set_stroke method is
|
|
673
|
+
# defined here:
|
|
674
|
+
# mobject/opengl/opengl_vectorized_mobject.py#L248
|
|
675
|
+
self.set_stroke( # type: ignore[call-arg]
|
|
621
676
|
width=min(self.initial_stroke_width, max_ratio * self.get_length()),
|
|
622
677
|
recurse=False,
|
|
623
678
|
)
|
|
@@ -632,6 +687,11 @@ class Arrow(Line):
|
|
|
632
687
|
class Vector(Arrow):
|
|
633
688
|
"""A vector specialized for use in graphs.
|
|
634
689
|
|
|
690
|
+
.. caution::
|
|
691
|
+
Do not confuse with the :class:`~.Vector2D`,
|
|
692
|
+
:class:`~.Vector3D` or :class:`~.VectorND` type aliases,
|
|
693
|
+
which are not Mobjects!
|
|
694
|
+
|
|
635
695
|
Parameters
|
|
636
696
|
----------
|
|
637
697
|
direction
|
|
@@ -654,7 +714,12 @@ class Vector(Arrow):
|
|
|
654
714
|
self.add(plane, vector_1, vector_2)
|
|
655
715
|
"""
|
|
656
716
|
|
|
657
|
-
def __init__(
|
|
717
|
+
def __init__(
|
|
718
|
+
self,
|
|
719
|
+
direction: Point2DLike | Point3DLike = RIGHT,
|
|
720
|
+
buff: float = 0,
|
|
721
|
+
**kwargs: Any,
|
|
722
|
+
) -> None:
|
|
658
723
|
self.buff = buff
|
|
659
724
|
if len(direction) == 2:
|
|
660
725
|
direction = np.hstack([direction, 0])
|
|
@@ -666,7 +731,7 @@ class Vector(Arrow):
|
|
|
666
731
|
integer_labels: bool = True,
|
|
667
732
|
n_dim: int = 2,
|
|
668
733
|
color: ParsableManimColor | None = None,
|
|
669
|
-
**kwargs,
|
|
734
|
+
**kwargs: Any,
|
|
670
735
|
) -> Matrix:
|
|
671
736
|
"""Creates a label based on the coordinates of the vector.
|
|
672
737
|
|
|
@@ -702,7 +767,6 @@ class Vector(Arrow):
|
|
|
702
767
|
|
|
703
768
|
self.add(plane, vec_1, vec_2, label_1, label_2)
|
|
704
769
|
"""
|
|
705
|
-
|
|
706
770
|
# avoiding circular imports
|
|
707
771
|
from ..matrix import Matrix
|
|
708
772
|
|
|
@@ -770,7 +834,7 @@ class DoubleArrow(Arrow):
|
|
|
770
834
|
self.add(box, d1, d2, d3)
|
|
771
835
|
"""
|
|
772
836
|
|
|
773
|
-
def __init__(self, *args, **kwargs) -> None:
|
|
837
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
774
838
|
if "tip_shape_end" in kwargs:
|
|
775
839
|
kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
|
|
776
840
|
tip_shape_start = kwargs.pop("tip_shape_start", ArrowTriangleFilledTip)
|
|
@@ -892,14 +956,14 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
892
956
|
line1: Line,
|
|
893
957
|
line2: Line,
|
|
894
958
|
radius: float | None = None,
|
|
895
|
-
quadrant:
|
|
959
|
+
quadrant: AngleQuadrant = (1, 1),
|
|
896
960
|
other_angle: bool = False,
|
|
897
961
|
dot: bool = False,
|
|
898
962
|
dot_radius: float | None = None,
|
|
899
963
|
dot_distance: float = 0.55,
|
|
900
964
|
dot_color: ParsableManimColor = WHITE,
|
|
901
965
|
elbow: bool = False,
|
|
902
|
-
**kwargs,
|
|
966
|
+
**kwargs: Any,
|
|
903
967
|
) -> None:
|
|
904
968
|
super().__init__(**kwargs)
|
|
905
969
|
self.lines = (line1, line2)
|
|
@@ -936,9 +1000,9 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
936
1000
|
+ quadrant[0] * radius * line1.get_unit_vector()
|
|
937
1001
|
+ quadrant[1] * radius * line2.get_unit_vector()
|
|
938
1002
|
)
|
|
939
|
-
angle_mobject = Elbow(**kwargs)
|
|
1003
|
+
angle_mobject: VMobject = Elbow(**kwargs)
|
|
940
1004
|
angle_mobject.set_points_as_corners(
|
|
941
|
-
[anchor_angle_1, anchor_middle, anchor_angle_2],
|
|
1005
|
+
np.array([anchor_angle_1, anchor_middle, anchor_angle_2]),
|
|
942
1006
|
)
|
|
943
1007
|
else:
|
|
944
1008
|
angle_1 = angle_of_vector(anchor_angle_1 - inter)
|
|
@@ -1002,11 +1066,10 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1002
1066
|
>>> angle.get_lines()
|
|
1003
1067
|
VGroup(Line, Line)
|
|
1004
1068
|
"""
|
|
1005
|
-
|
|
1006
1069
|
return VGroup(*self.lines)
|
|
1007
1070
|
|
|
1008
1071
|
def get_value(self, degrees: bool = False) -> float:
|
|
1009
|
-
"""Get the value of an angle of the :class:`Angle` class.
|
|
1072
|
+
r"""Get the value of an angle of the :class:`Angle` class.
|
|
1010
1073
|
|
|
1011
1074
|
Parameters
|
|
1012
1075
|
----------
|
|
@@ -1031,17 +1094,18 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1031
1094
|
|
|
1032
1095
|
angle = Angle(line1, line2, radius=0.4)
|
|
1033
1096
|
|
|
1034
|
-
value = DecimalNumber(angle.get_value(degrees=True), unit="^{
|
|
1097
|
+
value = DecimalNumber(angle.get_value(degrees=True), unit=r"^{\circ}")
|
|
1035
1098
|
value.next_to(angle, UR)
|
|
1036
1099
|
|
|
1037
1100
|
self.add(line1, line2, angle, value)
|
|
1038
1101
|
"""
|
|
1039
|
-
|
|
1040
1102
|
return self.angle_value / DEGREES if degrees else self.angle_value
|
|
1041
1103
|
|
|
1042
1104
|
@staticmethod
|
|
1043
|
-
def from_three_points(
|
|
1044
|
-
|
|
1105
|
+
def from_three_points(
|
|
1106
|
+
A: Point3DLike, B: Point3DLike, C: Point3DLike, **kwargs: Any
|
|
1107
|
+
) -> Angle:
|
|
1108
|
+
r"""The angle between the lines AB and BC.
|
|
1045
1109
|
|
|
1046
1110
|
This constructs the angle :math:`\\angle ABC`.
|
|
1047
1111
|
|
|
@@ -1116,6 +1180,10 @@ class RightAngle(Angle):
|
|
|
1116
1180
|
"""
|
|
1117
1181
|
|
|
1118
1182
|
def __init__(
|
|
1119
|
-
self,
|
|
1183
|
+
self,
|
|
1184
|
+
line1: Line,
|
|
1185
|
+
line2: Line,
|
|
1186
|
+
length: float | None = None,
|
|
1187
|
+
**kwargs: Any,
|
|
1120
1188
|
) -> None:
|
|
1121
1189
|
super().__init__(line1, line2, radius=length, elbow=True, **kwargs)
|