manim 0.17.3__py3-none-any.whl → 0.18.0.post0__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 +1 -0
- manim/__main__.py +2 -0
- manim/_config/__init__.py +0 -1
- manim/_config/logger_utils.py +1 -0
- manim/_config/utils.py +14 -5
- manim/animation/changing.py +9 -5
- manim/animation/creation.py +8 -3
- manim/animation/indication.py +4 -4
- manim/animation/speedmodifier.py +2 -4
- manim/animation/updaters/mobject_update_utils.py +134 -16
- manim/camera/camera.py +31 -17
- manim/cli/checkhealth/__init__.py +0 -0
- manim/cli/checkhealth/checks.py +173 -0
- manim/cli/checkhealth/commands.py +81 -0
- manim/cli/render/global_options.py +6 -0
- manim/constants.py +58 -54
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +126 -91
- manim/mobject/geometry/boolean_ops.py +6 -10
- manim/mobject/geometry/labeled.py +155 -0
- manim/mobject/geometry/line.py +66 -50
- manim/mobject/geometry/polygram.py +23 -15
- manim/mobject/geometry/shape_matchers.py +24 -15
- manim/mobject/geometry/tips.py +62 -40
- manim/mobject/graph.py +3 -4
- manim/mobject/graphing/coordinate_systems.py +190 -139
- manim/mobject/graphing/number_line.py +5 -2
- manim/mobject/graphing/probability.py +4 -3
- manim/mobject/graphing/scale.py +7 -7
- manim/mobject/logo.py +108 -22
- manim/mobject/matrix.py +33 -37
- manim/mobject/mobject.py +327 -260
- manim/mobject/opengl/opengl_image_mobject.py +1 -1
- manim/mobject/opengl/opengl_mobject.py +18 -12
- manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
- manim/mobject/opengl/opengl_surface.py +1 -1
- manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
- manim/mobject/svg/brace.py +3 -1
- manim/mobject/svg/svg_mobject.py +9 -11
- manim/mobject/table.py +50 -54
- manim/mobject/text/numbers.py +48 -6
- manim/mobject/text/tex_mobject.py +8 -12
- manim/mobject/text/text_mobject.py +32 -24
- manim/mobject/three_d/three_d_utils.py +13 -8
- manim/mobject/three_d/three_dimensions.py +61 -43
- manim/mobject/types/image_mobject.py +5 -4
- manim/mobject/types/point_cloud_mobject.py +8 -6
- manim/mobject/types/vectorized_mobject.py +385 -258
- manim/mobject/vector_field.py +19 -11
- manim/plugins/import_plugins.py +1 -1
- manim/plugins/plugins_flags.py +1 -6
- manim/renderer/shader.py +2 -2
- manim/scene/scene.py +15 -7
- manim/scene/scene_file_writer.py +1 -2
- manim/scene/three_d_scene.py +1 -1
- manim/scene/vector_space_scene.py +17 -7
- manim/typing.py +133 -0
- manim/utils/bezier.py +267 -83
- manim/utils/color/AS2700.py +234 -0
- manim/utils/color/BS381.py +315 -0
- manim/utils/color/X11.py +530 -0
- manim/utils/color/XKCD.py +949 -0
- manim/utils/color/__init__.py +58 -0
- manim/utils/color/core.py +1036 -0
- manim/utils/color/manim_colors.py +220 -0
- manim/utils/docbuild/autocolor_directive.py +92 -0
- manim/utils/docbuild/manim_directive.py +40 -6
- manim/utils/file_ops.py +1 -1
- manim/utils/hashing.py +1 -1
- manim/utils/iterables.py +1 -1
- manim/utils/rate_functions.py +33 -0
- manim/utils/simple_functions.py +0 -18
- manim/utils/space_ops.py +55 -42
- manim/utils/testing/frames_comparison.py +9 -0
- manim/utils/tex.py +2 -0
- manim/utils/tex_file_writing.py +29 -2
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
- manim/communitycolors.py +0 -9
- manim/utils/color.py +0 -552
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
manim/mobject/geometry/arc.py
CHANGED
|
@@ -43,17 +43,16 @@ __all__ = [
|
|
|
43
43
|
]
|
|
44
44
|
|
|
45
45
|
import itertools
|
|
46
|
-
import math
|
|
47
46
|
import warnings
|
|
48
|
-
from typing import TYPE_CHECKING
|
|
47
|
+
from typing import TYPE_CHECKING
|
|
49
48
|
|
|
50
49
|
import numpy as np
|
|
51
|
-
from
|
|
50
|
+
from typing_extensions import Self
|
|
52
51
|
|
|
53
52
|
from manim.constants import *
|
|
54
53
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
55
|
-
from manim.mobject.types.vectorized_mobject import VMobject
|
|
56
|
-
from manim.utils.color import
|
|
54
|
+
from manim.mobject.types.vectorized_mobject import VGroup, VMobject
|
|
55
|
+
from manim.utils.color import BLACK, BLUE, RED, WHITE, ParsableManimColor
|
|
57
56
|
from manim.utils.iterables import adjacent_pairs
|
|
58
57
|
from manim.utils.space_ops import (
|
|
59
58
|
angle_of_vector,
|
|
@@ -64,9 +63,11 @@ from manim.utils.space_ops import (
|
|
|
64
63
|
)
|
|
65
64
|
|
|
66
65
|
if TYPE_CHECKING:
|
|
66
|
+
import manim.mobject.geometry.tips as tips
|
|
67
67
|
from manim.mobject.mobject import Mobject
|
|
68
68
|
from manim.mobject.text.tex_mobject import SingleStringMathTex, Tex
|
|
69
69
|
from manim.mobject.text.text_mobject import Text
|
|
70
|
+
from manim.typing import CubicBezierPoints, Point3D, QuadraticBezierPoints, Vector
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
@@ -89,21 +90,26 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
89
90
|
|
|
90
91
|
def __init__(
|
|
91
92
|
self,
|
|
92
|
-
tip_length=DEFAULT_ARROW_TIP_LENGTH,
|
|
93
|
-
normal_vector=OUT,
|
|
94
|
-
tip_style={},
|
|
93
|
+
tip_length: float = DEFAULT_ARROW_TIP_LENGTH,
|
|
94
|
+
normal_vector: Vector = OUT,
|
|
95
|
+
tip_style: dict = {},
|
|
95
96
|
**kwargs,
|
|
96
|
-
):
|
|
97
|
-
self.tip_length = tip_length
|
|
98
|
-
self.normal_vector = normal_vector
|
|
99
|
-
self.tip_style = tip_style
|
|
97
|
+
) -> None:
|
|
98
|
+
self.tip_length: float = tip_length
|
|
99
|
+
self.normal_vector: Vector = normal_vector
|
|
100
|
+
self.tip_style: dict = tip_style
|
|
100
101
|
super().__init__(**kwargs)
|
|
101
102
|
|
|
102
103
|
# Adding, Creating, Modifying tips
|
|
103
104
|
|
|
104
105
|
def add_tip(
|
|
105
|
-
self,
|
|
106
|
-
|
|
106
|
+
self,
|
|
107
|
+
tip: tips.ArrowTip | None = None,
|
|
108
|
+
tip_shape: type[tips.ArrowTip] | None = None,
|
|
109
|
+
tip_length: float | None = None,
|
|
110
|
+
tip_width: float | None = None,
|
|
111
|
+
at_start: bool = False,
|
|
112
|
+
) -> Self:
|
|
107
113
|
"""Adds a tip to the TipableVMobject instance, recognising
|
|
108
114
|
that the endpoints might need to be switched if it's
|
|
109
115
|
a 'starting tip' or not.
|
|
@@ -118,7 +124,11 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
118
124
|
return self
|
|
119
125
|
|
|
120
126
|
def create_tip(
|
|
121
|
-
self,
|
|
127
|
+
self,
|
|
128
|
+
tip_shape: type[tips.ArrowTip] | None = None,
|
|
129
|
+
tip_length: float = None,
|
|
130
|
+
tip_width: float = None,
|
|
131
|
+
at_start: bool = False,
|
|
122
132
|
):
|
|
123
133
|
"""Stylises the tip, positions it spatially, and returns
|
|
124
134
|
the newly instantiated tip to the caller.
|
|
@@ -127,7 +137,12 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
127
137
|
self.position_tip(tip, at_start)
|
|
128
138
|
return tip
|
|
129
139
|
|
|
130
|
-
def get_unpositioned_tip(
|
|
140
|
+
def get_unpositioned_tip(
|
|
141
|
+
self,
|
|
142
|
+
tip_shape: type[tips.ArrowTip] | None = None,
|
|
143
|
+
tip_length: float | None = None,
|
|
144
|
+
tip_width: float | None = None,
|
|
145
|
+
):
|
|
131
146
|
"""Returns a tip that has been stylistically configured,
|
|
132
147
|
but has not yet been given a position in space.
|
|
133
148
|
"""
|
|
@@ -151,7 +166,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
151
166
|
tip = tip_shape(length=tip_length, **style)
|
|
152
167
|
return tip
|
|
153
168
|
|
|
154
|
-
def position_tip(self, tip, at_start=False):
|
|
169
|
+
def position_tip(self, tip: tips.ArrowTip, at_start: bool = False):
|
|
155
170
|
# Last two control points, defining both
|
|
156
171
|
# the end, and the tangency direction
|
|
157
172
|
if at_start:
|
|
@@ -178,7 +193,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
178
193
|
tip.shift(anchor - tip.tip_point)
|
|
179
194
|
return tip
|
|
180
195
|
|
|
181
|
-
def reset_endpoints_based_on_tip(self, tip, at_start):
|
|
196
|
+
def reset_endpoints_based_on_tip(self, tip: tips.ArrowTip, at_start: bool) -> Self:
|
|
182
197
|
if self.get_length() == 0:
|
|
183
198
|
# Zero length, put_start_and_end_on wouldn't work
|
|
184
199
|
return self
|
|
@@ -189,7 +204,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
189
204
|
self.put_start_and_end_on(self.get_start(), tip.base)
|
|
190
205
|
return self
|
|
191
206
|
|
|
192
|
-
def asign_tip_attr(self, tip, at_start):
|
|
207
|
+
def asign_tip_attr(self, tip: tips.ArrowTip, at_start: bool) -> Self:
|
|
193
208
|
if at_start:
|
|
194
209
|
self.start_tip = tip
|
|
195
210
|
else:
|
|
@@ -198,15 +213,15 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
198
213
|
|
|
199
214
|
# Checking for tips
|
|
200
215
|
|
|
201
|
-
def has_tip(self):
|
|
216
|
+
def has_tip(self) -> bool:
|
|
202
217
|
return hasattr(self, "tip") and self.tip in self
|
|
203
218
|
|
|
204
|
-
def has_start_tip(self):
|
|
219
|
+
def has_start_tip(self) -> bool:
|
|
205
220
|
return hasattr(self, "start_tip") and self.start_tip in self
|
|
206
221
|
|
|
207
222
|
# Getters
|
|
208
223
|
|
|
209
|
-
def pop_tips(self):
|
|
224
|
+
def pop_tips(self) -> VGroup:
|
|
210
225
|
start, end = self.get_start_and_end()
|
|
211
226
|
result = self.get_group_class()()
|
|
212
227
|
if self.has_tip():
|
|
@@ -218,7 +233,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
218
233
|
self.put_start_and_end_on(start, end)
|
|
219
234
|
return result
|
|
220
235
|
|
|
221
|
-
def get_tips(self):
|
|
236
|
+
def get_tips(self) -> VGroup:
|
|
222
237
|
"""Returns a VGroup (collection of VMobjects) containing
|
|
223
238
|
the TipableVMObject instance's tips.
|
|
224
239
|
"""
|
|
@@ -238,28 +253,28 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
|
|
|
238
253
|
else:
|
|
239
254
|
return tips[0]
|
|
240
255
|
|
|
241
|
-
def get_default_tip_length(self):
|
|
256
|
+
def get_default_tip_length(self) -> float:
|
|
242
257
|
return self.tip_length
|
|
243
258
|
|
|
244
|
-
def get_first_handle(self):
|
|
259
|
+
def get_first_handle(self) -> Point3D:
|
|
245
260
|
return self.points[1]
|
|
246
261
|
|
|
247
|
-
def get_last_handle(self):
|
|
262
|
+
def get_last_handle(self) -> Point3D:
|
|
248
263
|
return self.points[-2]
|
|
249
264
|
|
|
250
|
-
def get_end(self):
|
|
265
|
+
def get_end(self) -> Point3D:
|
|
251
266
|
if self.has_tip():
|
|
252
267
|
return self.tip.get_start()
|
|
253
268
|
else:
|
|
254
269
|
return super().get_end()
|
|
255
270
|
|
|
256
|
-
def get_start(self):
|
|
271
|
+
def get_start(self) -> Point3D:
|
|
257
272
|
if self.has_start_tip():
|
|
258
273
|
return self.start_tip.get_start()
|
|
259
274
|
else:
|
|
260
275
|
return super().get_start()
|
|
261
276
|
|
|
262
|
-
def get_length(self):
|
|
277
|
+
def get_length(self) -> np.floating:
|
|
263
278
|
start, end = self.get_start_and_end()
|
|
264
279
|
return np.linalg.norm(start - end)
|
|
265
280
|
|
|
@@ -282,23 +297,23 @@ class Arc(TipableVMobject):
|
|
|
282
297
|
def __init__(
|
|
283
298
|
self,
|
|
284
299
|
radius: float = 1.0,
|
|
285
|
-
start_angle=0,
|
|
286
|
-
angle=TAU / 4,
|
|
287
|
-
num_components=9,
|
|
288
|
-
arc_center=ORIGIN,
|
|
300
|
+
start_angle: float = 0,
|
|
301
|
+
angle: float = TAU / 4,
|
|
302
|
+
num_components: int = 9,
|
|
303
|
+
arc_center: Point3D = ORIGIN,
|
|
289
304
|
**kwargs,
|
|
290
305
|
):
|
|
291
306
|
if radius is None: # apparently None is passed by ArcBetweenPoints
|
|
292
307
|
radius = 1.0
|
|
293
308
|
self.radius = radius
|
|
294
|
-
self.num_components = num_components
|
|
295
|
-
self.arc_center = arc_center
|
|
296
|
-
self.start_angle = start_angle
|
|
297
|
-
self.angle = angle
|
|
298
|
-
self._failed_to_get_center = False
|
|
309
|
+
self.num_components: int = num_components
|
|
310
|
+
self.arc_center: Point3D = arc_center
|
|
311
|
+
self.start_angle: float = start_angle
|
|
312
|
+
self.angle: float = angle
|
|
313
|
+
self._failed_to_get_center: bool = False
|
|
299
314
|
super().__init__(**kwargs)
|
|
300
315
|
|
|
301
|
-
def generate_points(self):
|
|
316
|
+
def generate_points(self) -> None:
|
|
302
317
|
self._set_pre_positioned_points()
|
|
303
318
|
self.scale(self.radius, about_point=ORIGIN)
|
|
304
319
|
self.shift(self.arc_center)
|
|
@@ -306,7 +321,7 @@ class Arc(TipableVMobject):
|
|
|
306
321
|
# Points are set a bit differently when rendering via OpenGL.
|
|
307
322
|
# TODO: refactor Arc so that only one strategy for setting points
|
|
308
323
|
# has to be used.
|
|
309
|
-
def init_points(self):
|
|
324
|
+
def init_points(self) -> None:
|
|
310
325
|
self.set_points(
|
|
311
326
|
Arc._create_quadratic_bezier_points(
|
|
312
327
|
angle=self.angle,
|
|
@@ -318,7 +333,9 @@ class Arc(TipableVMobject):
|
|
|
318
333
|
self.shift(self.arc_center)
|
|
319
334
|
|
|
320
335
|
@staticmethod
|
|
321
|
-
def _create_quadratic_bezier_points(
|
|
336
|
+
def _create_quadratic_bezier_points(
|
|
337
|
+
angle: float, start_angle: float = 0, n_components: int = 8
|
|
338
|
+
) -> QuadraticBezierPoints:
|
|
322
339
|
samples = np.array(
|
|
323
340
|
[
|
|
324
341
|
[np.cos(a), np.sin(a), 0]
|
|
@@ -338,7 +355,7 @@ class Arc(TipableVMobject):
|
|
|
338
355
|
points[2::3] = samples[2::2]
|
|
339
356
|
return points
|
|
340
357
|
|
|
341
|
-
def _set_pre_positioned_points(self):
|
|
358
|
+
def _set_pre_positioned_points(self) -> None:
|
|
342
359
|
anchors = np.array(
|
|
343
360
|
[
|
|
344
361
|
np.cos(a) * RIGHT + np.sin(a) * UP
|
|
@@ -361,7 +378,7 @@ class Arc(TipableVMobject):
|
|
|
361
378
|
handles2 = anchors[1:] - (d_theta / 3) * tangent_vectors[1:]
|
|
362
379
|
self.set_anchors_and_handles(anchors[:-1], handles1, handles2, anchors[1:])
|
|
363
380
|
|
|
364
|
-
def get_arc_center(self, warning=True):
|
|
381
|
+
def get_arc_center(self, warning: bool = True) -> Point3D:
|
|
365
382
|
"""Looks at the normals to the first two
|
|
366
383
|
anchors, and finds their intersection points
|
|
367
384
|
"""
|
|
@@ -387,11 +404,11 @@ class Arc(TipableVMobject):
|
|
|
387
404
|
self._failed_to_get_center = True
|
|
388
405
|
return np.array(ORIGIN)
|
|
389
406
|
|
|
390
|
-
def move_arc_center_to(self, point):
|
|
407
|
+
def move_arc_center_to(self, point: Point3D) -> Self:
|
|
391
408
|
self.shift(point - self.get_arc_center())
|
|
392
409
|
return self
|
|
393
410
|
|
|
394
|
-
def stop_angle(self):
|
|
411
|
+
def stop_angle(self) -> float:
|
|
395
412
|
return angle_of_vector(self.points[-1] - self.get_arc_center()) % TAU
|
|
396
413
|
|
|
397
414
|
|
|
@@ -414,7 +431,14 @@ class ArcBetweenPoints(Arc):
|
|
|
414
431
|
self.play(Create(arc))
|
|
415
432
|
"""
|
|
416
433
|
|
|
417
|
-
def __init__(
|
|
434
|
+
def __init__(
|
|
435
|
+
self,
|
|
436
|
+
start: Point3D,
|
|
437
|
+
end: Point3D,
|
|
438
|
+
angle: float = TAU / 4,
|
|
439
|
+
radius: float = None,
|
|
440
|
+
**kwargs,
|
|
441
|
+
) -> None:
|
|
418
442
|
if radius is not None:
|
|
419
443
|
self.radius = radius
|
|
420
444
|
if radius < 0:
|
|
@@ -428,8 +452,8 @@ class ArcBetweenPoints(Arc):
|
|
|
428
452
|
"""ArcBetweenPoints called with a radius that is
|
|
429
453
|
smaller than half the distance between the points.""",
|
|
430
454
|
)
|
|
431
|
-
arc_height = radius -
|
|
432
|
-
angle =
|
|
455
|
+
arc_height = radius - np.sqrt(radius**2 - halfdist**2)
|
|
456
|
+
angle = np.arccos((radius - arc_height) / radius) * sign
|
|
433
457
|
|
|
434
458
|
super().__init__(radius=radius, angle=angle, **kwargs)
|
|
435
459
|
if angle == 0:
|
|
@@ -441,11 +465,11 @@ class ArcBetweenPoints(Arc):
|
|
|
441
465
|
if not self._failed_to_get_center:
|
|
442
466
|
self.radius = np.linalg.norm(np.array(start) - np.array(center))
|
|
443
467
|
else:
|
|
444
|
-
self.radius =
|
|
468
|
+
self.radius = np.inf
|
|
445
469
|
|
|
446
470
|
|
|
447
471
|
class CurvedArrow(ArcBetweenPoints):
|
|
448
|
-
def __init__(self, start_point, end_point, **kwargs):
|
|
472
|
+
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
|
|
449
473
|
from manim.mobject.geometry.tips import ArrowTriangleFilledTip
|
|
450
474
|
|
|
451
475
|
tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
|
|
@@ -454,7 +478,7 @@ class CurvedArrow(ArcBetweenPoints):
|
|
|
454
478
|
|
|
455
479
|
|
|
456
480
|
class CurvedDoubleArrow(CurvedArrow):
|
|
457
|
-
def __init__(self, start_point, end_point, **kwargs):
|
|
481
|
+
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
|
|
458
482
|
if "tip_shape_end" in kwargs:
|
|
459
483
|
kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
|
|
460
484
|
from manim.mobject.geometry.tips import ArrowTriangleFilledTip
|
|
@@ -492,9 +516,9 @@ class Circle(Arc):
|
|
|
492
516
|
def __init__(
|
|
493
517
|
self,
|
|
494
518
|
radius: float | None = None,
|
|
495
|
-
color:
|
|
519
|
+
color: ParsableManimColor = RED,
|
|
496
520
|
**kwargs,
|
|
497
|
-
):
|
|
521
|
+
) -> None:
|
|
498
522
|
super().__init__(
|
|
499
523
|
radius=radius,
|
|
500
524
|
start_angle=0,
|
|
@@ -509,7 +533,7 @@ class Circle(Arc):
|
|
|
509
533
|
dim_to_match: int = 0,
|
|
510
534
|
stretch: bool = False,
|
|
511
535
|
buffer_factor: float = 1.2,
|
|
512
|
-
):
|
|
536
|
+
) -> Self:
|
|
513
537
|
"""Modifies a circle so that it surrounds a given mobject.
|
|
514
538
|
|
|
515
539
|
Parameters
|
|
@@ -556,7 +580,7 @@ class Circle(Arc):
|
|
|
556
580
|
self.width = np.sqrt(mobject.width**2 + mobject.height**2)
|
|
557
581
|
return self.scale(buffer_factor)
|
|
558
582
|
|
|
559
|
-
def point_at_angle(self, angle: float):
|
|
583
|
+
def point_at_angle(self, angle: float) -> Point3D:
|
|
560
584
|
"""Returns the position of a point on the circle.
|
|
561
585
|
|
|
562
586
|
Parameters
|
|
@@ -588,13 +612,11 @@ class Circle(Arc):
|
|
|
588
612
|
|
|
589
613
|
start_angle = angle_of_vector(self.points[0] - self.get_center())
|
|
590
614
|
proportion = (angle - start_angle) / TAU
|
|
591
|
-
proportion -=
|
|
615
|
+
proportion -= np.floor(proportion)
|
|
592
616
|
return self.point_from_proportion(proportion)
|
|
593
617
|
|
|
594
618
|
@staticmethod
|
|
595
|
-
def from_three_points(
|
|
596
|
-
p1: Sequence[float], p2: Sequence[float], p3: Sequence[float], **kwargs
|
|
597
|
-
):
|
|
619
|
+
def from_three_points(p1: Point3D, p2: Point3D, p3: Point3D, **kwargs) -> Self:
|
|
598
620
|
"""Returns a circle passing through the specified
|
|
599
621
|
three points.
|
|
600
622
|
|
|
@@ -654,13 +676,13 @@ class Dot(Circle):
|
|
|
654
676
|
|
|
655
677
|
def __init__(
|
|
656
678
|
self,
|
|
657
|
-
point:
|
|
679
|
+
point: Point3D = ORIGIN,
|
|
658
680
|
radius: float = DEFAULT_DOT_RADIUS,
|
|
659
681
|
stroke_width: float = 0,
|
|
660
682
|
fill_opacity: float = 1.0,
|
|
661
|
-
color:
|
|
683
|
+
color: ParsableManimColor = WHITE,
|
|
662
684
|
**kwargs,
|
|
663
|
-
):
|
|
685
|
+
) -> None:
|
|
664
686
|
super().__init__(
|
|
665
687
|
arc_center=point,
|
|
666
688
|
radius=radius,
|
|
@@ -677,11 +699,11 @@ class AnnotationDot(Dot):
|
|
|
677
699
|
def __init__(
|
|
678
700
|
self,
|
|
679
701
|
radius: float = DEFAULT_DOT_RADIUS * 1.3,
|
|
680
|
-
stroke_width=5,
|
|
681
|
-
stroke_color=WHITE,
|
|
682
|
-
fill_color=BLUE,
|
|
702
|
+
stroke_width: float = 5,
|
|
703
|
+
stroke_color: ParsableManimColor = WHITE,
|
|
704
|
+
fill_color: ParsableManimColor = BLUE,
|
|
683
705
|
**kwargs,
|
|
684
|
-
):
|
|
706
|
+
) -> None:
|
|
685
707
|
super().__init__(
|
|
686
708
|
radius=radius,
|
|
687
709
|
stroke_width=stroke_width,
|
|
@@ -770,14 +792,16 @@ class Ellipse(Circle):
|
|
|
770
792
|
self.add(ellipse_group)
|
|
771
793
|
"""
|
|
772
794
|
|
|
773
|
-
def __init__(self, width: float = 2, height: float = 1, **kwargs):
|
|
795
|
+
def __init__(self, width: float = 2, height: float = 1, **kwargs) -> None:
|
|
774
796
|
super().__init__(**kwargs)
|
|
775
797
|
self.stretch_to_fit_width(width)
|
|
776
798
|
self.stretch_to_fit_height(height)
|
|
777
799
|
|
|
778
800
|
|
|
779
801
|
class AnnularSector(Arc):
|
|
780
|
-
"""
|
|
802
|
+
"""A sector of an annulus.
|
|
803
|
+
|
|
804
|
+
|
|
781
805
|
Parameters
|
|
782
806
|
----------
|
|
783
807
|
inner_radius
|
|
@@ -822,15 +846,15 @@ class AnnularSector(Arc):
|
|
|
822
846
|
|
|
823
847
|
def __init__(
|
|
824
848
|
self,
|
|
825
|
-
inner_radius=1,
|
|
826
|
-
outer_radius=2,
|
|
827
|
-
angle=TAU / 4,
|
|
828
|
-
start_angle=0,
|
|
829
|
-
fill_opacity=1,
|
|
830
|
-
stroke_width=0,
|
|
831
|
-
color=WHITE,
|
|
849
|
+
inner_radius: float = 1,
|
|
850
|
+
outer_radius: float = 2,
|
|
851
|
+
angle: float = TAU / 4,
|
|
852
|
+
start_angle: float = 0,
|
|
853
|
+
fill_opacity: float = 1,
|
|
854
|
+
stroke_width: float = 0,
|
|
855
|
+
color: ParsableManimColor = WHITE,
|
|
832
856
|
**kwargs,
|
|
833
|
-
):
|
|
857
|
+
) -> None:
|
|
834
858
|
self.inner_radius = inner_radius
|
|
835
859
|
self.outer_radius = outer_radius
|
|
836
860
|
super().__init__(
|
|
@@ -842,7 +866,7 @@ class AnnularSector(Arc):
|
|
|
842
866
|
**kwargs,
|
|
843
867
|
)
|
|
844
868
|
|
|
845
|
-
def generate_points(self):
|
|
869
|
+
def generate_points(self) -> None:
|
|
846
870
|
inner_arc, outer_arc = (
|
|
847
871
|
Arc(
|
|
848
872
|
start_angle=self.start_angle,
|
|
@@ -862,7 +886,8 @@ class AnnularSector(Arc):
|
|
|
862
886
|
|
|
863
887
|
|
|
864
888
|
class Sector(AnnularSector):
|
|
865
|
-
"""
|
|
889
|
+
"""A sector of a circle.
|
|
890
|
+
|
|
866
891
|
Examples
|
|
867
892
|
--------
|
|
868
893
|
.. manim:: ExampleSector
|
|
@@ -877,7 +902,9 @@ class Sector(AnnularSector):
|
|
|
877
902
|
self.add(sector, sector2)
|
|
878
903
|
"""
|
|
879
904
|
|
|
880
|
-
def __init__(
|
|
905
|
+
def __init__(
|
|
906
|
+
self, outer_radius: float = 1, inner_radius: float = 0, **kwargs
|
|
907
|
+
) -> None:
|
|
881
908
|
super().__init__(inner_radius=inner_radius, outer_radius=outer_radius, **kwargs)
|
|
882
909
|
|
|
883
910
|
|
|
@@ -909,12 +936,12 @@ class Annulus(Circle):
|
|
|
909
936
|
self,
|
|
910
937
|
inner_radius: float | None = 1,
|
|
911
938
|
outer_radius: float | None = 2,
|
|
912
|
-
fill_opacity=1,
|
|
913
|
-
stroke_width=0,
|
|
914
|
-
color=WHITE,
|
|
915
|
-
mark_paths_closed=False,
|
|
939
|
+
fill_opacity: float = 1,
|
|
940
|
+
stroke_width: float = 0,
|
|
941
|
+
color: ParsableManimColor = WHITE,
|
|
942
|
+
mark_paths_closed: bool = False,
|
|
916
943
|
**kwargs,
|
|
917
|
-
):
|
|
944
|
+
) -> None:
|
|
918
945
|
self.mark_paths_closed = mark_paths_closed # is this even used?
|
|
919
946
|
self.inner_radius = inner_radius
|
|
920
947
|
self.outer_radius = outer_radius
|
|
@@ -922,7 +949,7 @@ class Annulus(Circle):
|
|
|
922
949
|
fill_opacity=fill_opacity, stroke_width=stroke_width, color=color, **kwargs
|
|
923
950
|
)
|
|
924
951
|
|
|
925
|
-
def generate_points(self):
|
|
952
|
+
def generate_points(self) -> None:
|
|
926
953
|
self.radius = self.outer_radius
|
|
927
954
|
outer_circle = Circle(radius=self.outer_radius)
|
|
928
955
|
inner_circle = Circle(radius=self.inner_radius)
|
|
@@ -935,7 +962,8 @@ class Annulus(Circle):
|
|
|
935
962
|
|
|
936
963
|
|
|
937
964
|
class CubicBezier(VMobject, metaclass=ConvertToOpenGL):
|
|
938
|
-
"""
|
|
965
|
+
"""A cubic Bézier curve.
|
|
966
|
+
|
|
939
967
|
Example
|
|
940
968
|
-------
|
|
941
969
|
.. manim:: BezierSplineExample
|
|
@@ -956,7 +984,14 @@ class CubicBezier(VMobject, metaclass=ConvertToOpenGL):
|
|
|
956
984
|
|
|
957
985
|
"""
|
|
958
986
|
|
|
959
|
-
def __init__(
|
|
987
|
+
def __init__(
|
|
988
|
+
self,
|
|
989
|
+
start_anchor: CubicBezierPoints,
|
|
990
|
+
start_handle: CubicBezierPoints,
|
|
991
|
+
end_handle: CubicBezierPoints,
|
|
992
|
+
end_anchor: CubicBezierPoints,
|
|
993
|
+
**kwargs,
|
|
994
|
+
) -> None:
|
|
960
995
|
super().__init__(**kwargs)
|
|
961
996
|
self.add_cubic_bezier_curve(start_anchor, start_handle, end_handle, end_anchor)
|
|
962
997
|
|
|
@@ -1042,12 +1077,12 @@ class ArcPolygon(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1042
1077
|
|
|
1043
1078
|
def __init__(
|
|
1044
1079
|
self,
|
|
1045
|
-
*vertices:
|
|
1080
|
+
*vertices: Point3D,
|
|
1046
1081
|
angle: float = PI / 4,
|
|
1047
1082
|
radius: float | None = None,
|
|
1048
1083
|
arc_config: list[dict] | None = None,
|
|
1049
1084
|
**kwargs,
|
|
1050
|
-
):
|
|
1085
|
+
) -> None:
|
|
1051
1086
|
n = len(vertices)
|
|
1052
1087
|
point_pairs = [(vertices[k], vertices[(k + 1) % n]) for k in range(n)]
|
|
1053
1088
|
|
|
@@ -1185,7 +1220,7 @@ class ArcPolygonFromArcs(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1185
1220
|
self.wait(2)
|
|
1186
1221
|
"""
|
|
1187
1222
|
|
|
1188
|
-
def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs):
|
|
1223
|
+
def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs) -> None:
|
|
1189
1224
|
if not all(isinstance(m, (Arc, ArcBetweenPoints)) for m in arcs):
|
|
1190
1225
|
raise ValueError(
|
|
1191
1226
|
"All ArcPolygon submobjects must be of type Arc/ArcBetweenPoints",
|
|
@@ -1204,7 +1239,7 @@ class ArcPolygonFromArcs(VMobject, metaclass=ConvertToOpenGL):
|
|
|
1204
1239
|
self.append_points(arc1.points)
|
|
1205
1240
|
line = Line(arc1.get_end(), arc2.get_start())
|
|
1206
1241
|
len_ratio = line.get_length() / arc1.get_arc_length()
|
|
1207
|
-
if
|
|
1242
|
+
if np.isnan(len_ratio) or np.isinf(len_ratio):
|
|
1208
1243
|
continue
|
|
1209
1244
|
line.insert_n_curves(int(arc1.get_num_curves() * len_ratio))
|
|
1210
1245
|
self.append_points(line.points)
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import typing
|
|
6
|
-
|
|
7
5
|
import numpy as np
|
|
8
6
|
from pathops import Path as SkiaPath
|
|
9
7
|
from pathops import PathVerb, difference, intersection, union, xor
|
|
@@ -11,6 +9,7 @@ from pathops import PathVerb, difference, intersection, union, xor
|
|
|
11
9
|
from manim import config
|
|
12
10
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
13
11
|
from manim.mobject.types.vectorized_mobject import VMobject
|
|
12
|
+
from manim.typing import Point2D_Array
|
|
14
13
|
|
|
15
14
|
from ...constants import RendererType
|
|
16
15
|
|
|
@@ -23,12 +22,9 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
|
|
|
23
22
|
objects (:class:`~.VMobject`).
|
|
24
23
|
"""
|
|
25
24
|
|
|
26
|
-
def __init__(self, *args, **kwargs):
|
|
27
|
-
super().__init__(*args, **kwargs)
|
|
28
|
-
|
|
29
25
|
def _convert_2d_to_3d_array(
|
|
30
26
|
self,
|
|
31
|
-
points:
|
|
27
|
+
points: Point2D_Array,
|
|
32
28
|
z_dim: float = 0.0,
|
|
33
29
|
) -> list[np.ndarray]:
|
|
34
30
|
"""Converts an iterable with coordinates in 2d to 3d by adding
|
|
@@ -43,7 +39,7 @@ class _BooleanOps(VMobject, metaclass=ConvertToOpenGL):
|
|
|
43
39
|
|
|
44
40
|
Returns
|
|
45
41
|
-------
|
|
46
|
-
|
|
42
|
+
Point2D_Array
|
|
47
43
|
A list of array converted to 3d.
|
|
48
44
|
|
|
49
45
|
Example
|
|
@@ -216,7 +212,7 @@ class Difference(_BooleanOps):
|
|
|
216
212
|
|
|
217
213
|
"""
|
|
218
214
|
|
|
219
|
-
def __init__(self, subject, clip, **kwargs) -> None:
|
|
215
|
+
def __init__(self, subject: VMobject, clip: VMobject, **kwargs) -> None:
|
|
220
216
|
super().__init__(**kwargs)
|
|
221
217
|
outpen = SkiaPath()
|
|
222
218
|
difference(
|
|
@@ -258,7 +254,7 @@ class Intersection(_BooleanOps):
|
|
|
258
254
|
|
|
259
255
|
"""
|
|
260
256
|
|
|
261
|
-
def __init__(self, *vmobjects, **kwargs) -> None:
|
|
257
|
+
def __init__(self, *vmobjects: VMobject, **kwargs) -> None:
|
|
262
258
|
if len(vmobjects) < 2:
|
|
263
259
|
raise ValueError("At least 2 mobjects needed for Intersection.")
|
|
264
260
|
|
|
@@ -311,7 +307,7 @@ class Exclusion(_BooleanOps):
|
|
|
311
307
|
|
|
312
308
|
"""
|
|
313
309
|
|
|
314
|
-
def __init__(self, subject, clip, **kwargs) -> None:
|
|
310
|
+
def __init__(self, subject: VMobject, clip: VMobject, **kwargs) -> None:
|
|
315
311
|
super().__init__(**kwargs)
|
|
316
312
|
outpen = SkiaPath()
|
|
317
313
|
xor(
|