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
manim/mobject/geometry/line.py
CHANGED
|
@@ -30,70 +30,115 @@ from manim.utils.color import WHITE
|
|
|
30
30
|
from manim.utils.space_ops import angle_of_vector, line_intersection, normalize
|
|
31
31
|
|
|
32
32
|
if TYPE_CHECKING:
|
|
33
|
-
from
|
|
33
|
+
from typing import Any
|
|
34
34
|
|
|
35
|
-
from
|
|
35
|
+
from typing_extensions import Literal, Self, TypeAlias
|
|
36
|
+
|
|
37
|
+
from manim.typing import Point2DLike, Point3D, Point3DLike, Vector3D
|
|
36
38
|
from manim.utils.color import ParsableManimColor
|
|
37
39
|
|
|
38
40
|
from ..matrix import Matrix # Avoid circular import
|
|
39
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
|
+
|
|
40
66
|
|
|
41
67
|
class Line(TipableVMobject):
|
|
42
68
|
def __init__(
|
|
43
69
|
self,
|
|
44
|
-
start:
|
|
45
|
-
end:
|
|
70
|
+
start: Point3DLike | Mobject = LEFT,
|
|
71
|
+
end: Point3DLike | Mobject = RIGHT,
|
|
46
72
|
buff: float = 0,
|
|
47
73
|
path_arc: float | None = None,
|
|
48
|
-
**kwargs,
|
|
74
|
+
**kwargs: Any,
|
|
49
75
|
) -> None:
|
|
50
76
|
self.dim = 3
|
|
51
77
|
self.buff = buff
|
|
52
78
|
self.path_arc = path_arc
|
|
53
79
|
self._set_start_and_end_attrs(start, end)
|
|
54
80
|
super().__init__(**kwargs)
|
|
81
|
+
# TODO: Deal with the situation where path_arc is None
|
|
55
82
|
|
|
56
83
|
def generate_points(self) -> None:
|
|
57
84
|
self.set_points_by_ends(
|
|
58
85
|
start=self.start,
|
|
59
86
|
end=self.end,
|
|
60
87
|
buff=self.buff,
|
|
61
|
-
path_arc=self.path_arc,
|
|
88
|
+
path_arc=self.path_arc, # type: ignore[arg-type]
|
|
62
89
|
)
|
|
63
90
|
|
|
64
91
|
def set_points_by_ends(
|
|
65
92
|
self,
|
|
66
|
-
start:
|
|
67
|
-
end:
|
|
93
|
+
start: Point3DLike | Mobject,
|
|
94
|
+
end: Point3DLike | Mobject,
|
|
68
95
|
buff: float = 0,
|
|
69
96
|
path_arc: float = 0,
|
|
70
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)
|
|
71
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
|
|
72
118
|
arc = ArcBetweenPoints(self.start, self.end, angle=self.path_arc)
|
|
73
119
|
self.set_points(arc.points)
|
|
74
120
|
else:
|
|
75
|
-
self.set_points_as_corners([start, end])
|
|
121
|
+
self.set_points_as_corners(np.asarray([self.start, self.end]))
|
|
76
122
|
|
|
77
123
|
self._account_for_buff(buff)
|
|
78
124
|
|
|
79
125
|
init_points = generate_points
|
|
80
126
|
|
|
81
|
-
def _account_for_buff(self, buff: float) ->
|
|
127
|
+
def _account_for_buff(self, buff: float) -> None:
|
|
82
128
|
if buff == 0:
|
|
83
129
|
return
|
|
84
130
|
#
|
|
85
|
-
if self.path_arc == 0
|
|
86
|
-
length = self.get_length()
|
|
87
|
-
else:
|
|
88
|
-
length = self.get_arc_length()
|
|
131
|
+
length = self.get_length() if self.path_arc == 0 else self.get_arc_length()
|
|
89
132
|
#
|
|
90
133
|
if length < 2 * buff:
|
|
91
134
|
return
|
|
92
135
|
buff_proportion = buff / length
|
|
93
136
|
self.pointwise_become_partial(self, buff_proportion, 1 - buff_proportion)
|
|
94
|
-
return
|
|
137
|
+
return
|
|
95
138
|
|
|
96
|
-
def _set_start_and_end_attrs(
|
|
139
|
+
def _set_start_and_end_attrs(
|
|
140
|
+
self, start: Point3DLike | Mobject, end: Point3DLike | Mobject
|
|
141
|
+
) -> None:
|
|
97
142
|
# If either start or end are Mobjects, this
|
|
98
143
|
# gives their centers
|
|
99
144
|
rough_start = self._pointify(start)
|
|
@@ -107,7 +152,7 @@ class Line(TipableVMobject):
|
|
|
107
152
|
|
|
108
153
|
def _pointify(
|
|
109
154
|
self,
|
|
110
|
-
mob_or_point: Mobject |
|
|
155
|
+
mob_or_point: Mobject | Point3DLike,
|
|
111
156
|
direction: Vector3D | None = None,
|
|
112
157
|
) -> Point3D:
|
|
113
158
|
"""Transforms a mobject into its corresponding point. Does nothing if a point is passed.
|
|
@@ -133,7 +178,11 @@ class Line(TipableVMobject):
|
|
|
133
178
|
self.path_arc = new_value
|
|
134
179
|
self.init_points()
|
|
135
180
|
|
|
136
|
-
def put_start_and_end_on(
|
|
181
|
+
def put_start_and_end_on(
|
|
182
|
+
self,
|
|
183
|
+
start: Point3DLike,
|
|
184
|
+
end: Point3DLike,
|
|
185
|
+
) -> Self:
|
|
137
186
|
"""Sets starts and end coordinates of a line.
|
|
138
187
|
|
|
139
188
|
Examples
|
|
@@ -159,8 +208,8 @@ class Line(TipableVMobject):
|
|
|
159
208
|
if np.all(curr_start == curr_end):
|
|
160
209
|
# TODO, any problems with resetting
|
|
161
210
|
# these attrs?
|
|
162
|
-
self.start = start
|
|
163
|
-
self.end = end
|
|
211
|
+
self.start = np.asarray(start)
|
|
212
|
+
self.end = np.asarray(end)
|
|
164
213
|
self.generate_points()
|
|
165
214
|
return super().put_start_and_end_on(start, end)
|
|
166
215
|
|
|
@@ -173,7 +222,7 @@ class Line(TipableVMobject):
|
|
|
173
222
|
def get_angle(self) -> float:
|
|
174
223
|
return angle_of_vector(self.get_vector())
|
|
175
224
|
|
|
176
|
-
def get_projection(self, point:
|
|
225
|
+
def get_projection(self, point: Point3DLike) -> Point3D:
|
|
177
226
|
"""Returns the projection of a point onto a line.
|
|
178
227
|
|
|
179
228
|
Parameters
|
|
@@ -181,16 +230,15 @@ class Line(TipableVMobject):
|
|
|
181
230
|
point
|
|
182
231
|
The point to which the line is projected.
|
|
183
232
|
"""
|
|
184
|
-
|
|
185
233
|
start = self.get_start()
|
|
186
234
|
end = self.get_end()
|
|
187
235
|
unit_vect = normalize(end - start)
|
|
188
|
-
return start + np.dot(point - start, unit_vect) * unit_vect
|
|
236
|
+
return start + float(np.dot(point - start, unit_vect)) * unit_vect
|
|
189
237
|
|
|
190
238
|
def get_slope(self) -> float:
|
|
191
|
-
return np.tan(self.get_angle())
|
|
239
|
+
return float(np.tan(self.get_angle()))
|
|
192
240
|
|
|
193
|
-
def set_angle(self, angle: float, about_point:
|
|
241
|
+
def set_angle(self, angle: float, about_point: Point3DLike | None = None) -> Self:
|
|
194
242
|
if about_point is None:
|
|
195
243
|
about_point = self.get_start()
|
|
196
244
|
|
|
@@ -202,7 +250,8 @@ class Line(TipableVMobject):
|
|
|
202
250
|
return self
|
|
203
251
|
|
|
204
252
|
def set_length(self, length: float) -> Self:
|
|
205
|
-
|
|
253
|
+
scale_factor: float = length / self.get_length()
|
|
254
|
+
return self.scale(scale_factor)
|
|
206
255
|
|
|
207
256
|
|
|
208
257
|
class DashedLine(Line):
|
|
@@ -241,10 +290,10 @@ class DashedLine(Line):
|
|
|
241
290
|
|
|
242
291
|
def __init__(
|
|
243
292
|
self,
|
|
244
|
-
*args,
|
|
293
|
+
*args: Any,
|
|
245
294
|
dash_length: float = DEFAULT_DASH_LENGTH,
|
|
246
295
|
dashed_ratio: float = 0.5,
|
|
247
|
-
**kwargs,
|
|
296
|
+
**kwargs: Any,
|
|
248
297
|
) -> None:
|
|
249
298
|
self.dash_length = dash_length
|
|
250
299
|
self.dashed_ratio = dashed_ratio
|
|
@@ -267,7 +316,6 @@ class DashedLine(Line):
|
|
|
267
316
|
>>> DashedLine()._calculate_num_dashes()
|
|
268
317
|
20
|
|
269
318
|
"""
|
|
270
|
-
|
|
271
319
|
# Minimum number of dashes has to be 2
|
|
272
320
|
return max(
|
|
273
321
|
2,
|
|
@@ -284,7 +332,6 @@ class DashedLine(Line):
|
|
|
284
332
|
>>> DashedLine().get_start()
|
|
285
333
|
array([-1., 0., 0.])
|
|
286
334
|
"""
|
|
287
|
-
|
|
288
335
|
if len(self.submobjects) > 0:
|
|
289
336
|
return self.submobjects[0].get_start()
|
|
290
337
|
else:
|
|
@@ -300,7 +347,6 @@ class DashedLine(Line):
|
|
|
300
347
|
>>> DashedLine().get_end()
|
|
301
348
|
array([1., 0., 0.])
|
|
302
349
|
"""
|
|
303
|
-
|
|
304
350
|
if len(self.submobjects) > 0:
|
|
305
351
|
return self.submobjects[-1].get_end()
|
|
306
352
|
else:
|
|
@@ -316,8 +362,11 @@ class DashedLine(Line):
|
|
|
316
362
|
>>> DashedLine().get_first_handle()
|
|
317
363
|
array([-0.98333333, 0. , 0. ])
|
|
318
364
|
"""
|
|
319
|
-
|
|
320
|
-
|
|
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
|
|
321
370
|
|
|
322
371
|
def get_last_handle(self) -> Point3D:
|
|
323
372
|
"""Returns the point of the last handle.
|
|
@@ -329,8 +378,11 @@ class DashedLine(Line):
|
|
|
329
378
|
>>> DashedLine().get_last_handle()
|
|
330
379
|
array([0.98333333, 0. , 0. ])
|
|
331
380
|
"""
|
|
332
|
-
|
|
333
|
-
|
|
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
|
|
334
386
|
|
|
335
387
|
|
|
336
388
|
class TangentLine(Line):
|
|
@@ -372,7 +424,7 @@ class TangentLine(Line):
|
|
|
372
424
|
alpha: float,
|
|
373
425
|
length: float = 1,
|
|
374
426
|
d_alpha: float = 1e-6,
|
|
375
|
-
**kwargs,
|
|
427
|
+
**kwargs: Any,
|
|
376
428
|
) -> None:
|
|
377
429
|
self.length = length
|
|
378
430
|
self.d_alpha = d_alpha
|
|
@@ -415,10 +467,10 @@ class Elbow(VMobject, metaclass=ConvertToOpenGL):
|
|
|
415
467
|
self.add(elbow_group)
|
|
416
468
|
"""
|
|
417
469
|
|
|
418
|
-
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:
|
|
419
471
|
self.angle = angle
|
|
420
472
|
super().__init__(**kwargs)
|
|
421
|
-
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
|
|
473
|
+
self.set_points_as_corners(np.array([UP, UP + RIGHT, RIGHT]))
|
|
422
474
|
self.scale_to_fit_width(width, about_point=ORIGIN)
|
|
423
475
|
self.rotate(self.angle, about_point=ORIGIN)
|
|
424
476
|
|
|
@@ -513,24 +565,24 @@ class Arrow(Line):
|
|
|
513
565
|
|
|
514
566
|
def __init__(
|
|
515
567
|
self,
|
|
516
|
-
*args,
|
|
568
|
+
*args: Any,
|
|
517
569
|
stroke_width: float = 6,
|
|
518
570
|
buff: float = MED_SMALL_BUFF,
|
|
519
571
|
max_tip_length_to_length_ratio: float = 0.25,
|
|
520
572
|
max_stroke_width_to_length_ratio: float = 5,
|
|
521
|
-
**kwargs,
|
|
573
|
+
**kwargs: Any,
|
|
522
574
|
) -> None:
|
|
523
575
|
self.max_tip_length_to_length_ratio = max_tip_length_to_length_ratio
|
|
524
576
|
self.max_stroke_width_to_length_ratio = max_stroke_width_to_length_ratio
|
|
525
577
|
tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
|
|
526
|
-
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs)
|
|
578
|
+
super().__init__(*args, buff=buff, stroke_width=stroke_width, **kwargs) # type: ignore[misc]
|
|
527
579
|
# TODO, should this be affected when
|
|
528
580
|
# Arrow.set_stroke is called?
|
|
529
581
|
self.initial_stroke_width = self.stroke_width
|
|
530
582
|
self.add_tip(tip_shape=tip_shape)
|
|
531
583
|
self._set_stroke_width_from_length()
|
|
532
584
|
|
|
533
|
-
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]
|
|
534
586
|
r"""Scale an arrow, but keep stroke width and arrow tip size fixed.
|
|
535
587
|
|
|
536
588
|
|
|
@@ -590,7 +642,6 @@ class Arrow(Line):
|
|
|
590
642
|
>>> np.round(Arrow().get_normal_vector()) + 0. # add 0. to avoid negative 0 in output
|
|
591
643
|
array([ 0., 0., -1.])
|
|
592
644
|
"""
|
|
593
|
-
|
|
594
645
|
p0, p1, p2 = self.tip.get_start_anchors()[:3]
|
|
595
646
|
return normalize(np.cross(p2 - p1, p1 - p0))
|
|
596
647
|
|
|
@@ -610,7 +661,6 @@ class Arrow(Line):
|
|
|
610
661
|
>>> Arrow().get_default_tip_length()
|
|
611
662
|
0.35
|
|
612
663
|
"""
|
|
613
|
-
|
|
614
664
|
max_ratio = self.max_tip_length_to_length_ratio
|
|
615
665
|
return min(self.tip_length, max_ratio * self.get_length())
|
|
616
666
|
|
|
@@ -618,7 +668,11 @@ class Arrow(Line):
|
|
|
618
668
|
"""Sets stroke width based on length."""
|
|
619
669
|
max_ratio = self.max_stroke_width_to_length_ratio
|
|
620
670
|
if config.renderer == RendererType.OPENGL:
|
|
621
|
-
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]
|
|
622
676
|
width=min(self.initial_stroke_width, max_ratio * self.get_length()),
|
|
623
677
|
recurse=False,
|
|
624
678
|
)
|
|
@@ -661,7 +715,10 @@ class Vector(Arrow):
|
|
|
661
715
|
"""
|
|
662
716
|
|
|
663
717
|
def __init__(
|
|
664
|
-
self,
|
|
718
|
+
self,
|
|
719
|
+
direction: Point2DLike | Point3DLike = RIGHT,
|
|
720
|
+
buff: float = 0,
|
|
721
|
+
**kwargs: Any,
|
|
665
722
|
) -> None:
|
|
666
723
|
self.buff = buff
|
|
667
724
|
if len(direction) == 2:
|
|
@@ -674,7 +731,7 @@ class Vector(Arrow):
|
|
|
674
731
|
integer_labels: bool = True,
|
|
675
732
|
n_dim: int = 2,
|
|
676
733
|
color: ParsableManimColor | None = None,
|
|
677
|
-
**kwargs,
|
|
734
|
+
**kwargs: Any,
|
|
678
735
|
) -> Matrix:
|
|
679
736
|
"""Creates a label based on the coordinates of the vector.
|
|
680
737
|
|
|
@@ -710,7 +767,6 @@ class Vector(Arrow):
|
|
|
710
767
|
|
|
711
768
|
self.add(plane, vec_1, vec_2, label_1, label_2)
|
|
712
769
|
"""
|
|
713
|
-
|
|
714
770
|
# avoiding circular imports
|
|
715
771
|
from ..matrix import Matrix
|
|
716
772
|
|
|
@@ -778,7 +834,7 @@ class DoubleArrow(Arrow):
|
|
|
778
834
|
self.add(box, d1, d2, d3)
|
|
779
835
|
"""
|
|
780
836
|
|
|
781
|
-
def __init__(self, *args, **kwargs) -> None:
|
|
837
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
782
838
|
if "tip_shape_end" in kwargs:
|
|
783
839
|
kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
|
|
784
840
|
tip_shape_start = kwargs.pop("tip_shape_start", ArrowTriangleFilledTip)
|
|
@@ -900,14 +956,14 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
900
956
|
line1: Line,
|
|
901
957
|
line2: Line,
|
|
902
958
|
radius: float | None = None,
|
|
903
|
-
quadrant:
|
|
959
|
+
quadrant: AngleQuadrant = (1, 1),
|
|
904
960
|
other_angle: bool = False,
|
|
905
961
|
dot: bool = False,
|
|
906
962
|
dot_radius: float | None = None,
|
|
907
963
|
dot_distance: float = 0.55,
|
|
908
964
|
dot_color: ParsableManimColor = WHITE,
|
|
909
965
|
elbow: bool = False,
|
|
910
|
-
**kwargs,
|
|
966
|
+
**kwargs: Any,
|
|
911
967
|
) -> None:
|
|
912
968
|
super().__init__(**kwargs)
|
|
913
969
|
self.lines = (line1, line2)
|
|
@@ -944,9 +1000,9 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
944
1000
|
+ quadrant[0] * radius * line1.get_unit_vector()
|
|
945
1001
|
+ quadrant[1] * radius * line2.get_unit_vector()
|
|
946
1002
|
)
|
|
947
|
-
angle_mobject = Elbow(**kwargs)
|
|
1003
|
+
angle_mobject: VMobject = Elbow(**kwargs)
|
|
948
1004
|
angle_mobject.set_points_as_corners(
|
|
949
|
-
[anchor_angle_1, anchor_middle, anchor_angle_2],
|
|
1005
|
+
np.array([anchor_angle_1, anchor_middle, anchor_angle_2]),
|
|
950
1006
|
)
|
|
951
1007
|
else:
|
|
952
1008
|
angle_1 = angle_of_vector(anchor_angle_1 - inter)
|
|
@@ -1010,11 +1066,10 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1010
1066
|
>>> angle.get_lines()
|
|
1011
1067
|
VGroup(Line, Line)
|
|
1012
1068
|
"""
|
|
1013
|
-
|
|
1014
1069
|
return VGroup(*self.lines)
|
|
1015
1070
|
|
|
1016
1071
|
def get_value(self, degrees: bool = False) -> float:
|
|
1017
|
-
"""Get the value of an angle of the :class:`Angle` class.
|
|
1072
|
+
r"""Get the value of an angle of the :class:`Angle` class.
|
|
1018
1073
|
|
|
1019
1074
|
Parameters
|
|
1020
1075
|
----------
|
|
@@ -1039,17 +1094,18 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1039
1094
|
|
|
1040
1095
|
angle = Angle(line1, line2, radius=0.4)
|
|
1041
1096
|
|
|
1042
|
-
value = DecimalNumber(angle.get_value(degrees=True), unit="^{
|
|
1097
|
+
value = DecimalNumber(angle.get_value(degrees=True), unit=r"^{\circ}")
|
|
1043
1098
|
value.next_to(angle, UR)
|
|
1044
1099
|
|
|
1045
1100
|
self.add(line1, line2, angle, value)
|
|
1046
1101
|
"""
|
|
1047
|
-
|
|
1048
1102
|
return self.angle_value / DEGREES if degrees else self.angle_value
|
|
1049
1103
|
|
|
1050
1104
|
@staticmethod
|
|
1051
|
-
def from_three_points(
|
|
1052
|
-
|
|
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.
|
|
1053
1109
|
|
|
1054
1110
|
This constructs the angle :math:`\\angle ABC`.
|
|
1055
1111
|
|
|
@@ -1124,6 +1180,10 @@ class RightAngle(Angle):
|
|
|
1124
1180
|
"""
|
|
1125
1181
|
|
|
1126
1182
|
def __init__(
|
|
1127
|
-
self,
|
|
1183
|
+
self,
|
|
1184
|
+
line1: Line,
|
|
1185
|
+
line2: Line,
|
|
1186
|
+
length: float | None = None,
|
|
1187
|
+
**kwargs: Any,
|
|
1128
1188
|
) -> None:
|
|
1129
1189
|
super().__init__(line1, line2, radius=length, elbow=True, **kwargs)
|