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/camera/camera.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""A camera converts the mobjects contained in a Scene into an array of pixels."""
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
__all__ = ["Camera", "BackgroundColoredVMobjectDisplayer"]
|
|
@@ -9,27 +8,41 @@ import copy
|
|
|
9
8
|
import itertools as it
|
|
10
9
|
import operator as op
|
|
11
10
|
import pathlib
|
|
12
|
-
import
|
|
11
|
+
from collections.abc import Callable, Iterable
|
|
13
12
|
from functools import reduce
|
|
14
|
-
from typing import
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
15
14
|
|
|
16
15
|
import cairo
|
|
17
16
|
import numpy as np
|
|
17
|
+
import numpy.typing as npt
|
|
18
18
|
from PIL import Image
|
|
19
19
|
from scipy.spatial.distance import pdist
|
|
20
|
+
from typing_extensions import Self
|
|
21
|
+
|
|
22
|
+
from manim.typing import (
|
|
23
|
+
FloatRGBA_Array,
|
|
24
|
+
FloatRGBALike_Array,
|
|
25
|
+
ManimInt,
|
|
26
|
+
PixelArray,
|
|
27
|
+
Point3D,
|
|
28
|
+
Point3D_Array,
|
|
29
|
+
)
|
|
20
30
|
|
|
21
31
|
from .. import config, logger
|
|
22
32
|
from ..constants import *
|
|
23
33
|
from ..mobject.mobject import Mobject
|
|
24
|
-
from ..mobject.types.image_mobject import AbstractImageMobject
|
|
25
34
|
from ..mobject.types.point_cloud_mobject import PMobject
|
|
26
35
|
from ..mobject.types.vectorized_mobject import VMobject
|
|
27
|
-
from ..utils.color import color_to_int_rgba
|
|
36
|
+
from ..utils.color import ManimColor, ParsableManimColor, color_to_int_rgba
|
|
28
37
|
from ..utils.family import extract_mobject_family_members
|
|
29
38
|
from ..utils.images import get_full_raster_image_path
|
|
30
39
|
from ..utils.iterables import list_difference_update
|
|
31
40
|
from ..utils.space_ops import angle_of_vector
|
|
32
41
|
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from ..mobject.types.image_mobject import AbstractImageMobject
|
|
44
|
+
|
|
45
|
+
|
|
33
46
|
LINE_JOIN_MAP = {
|
|
34
47
|
LineJointType.AUTO: None, # TODO: this could be improved
|
|
35
48
|
LineJointType.ROUND: cairo.LineJoin.ROUND,
|
|
@@ -38,6 +51,14 @@ LINE_JOIN_MAP = {
|
|
|
38
51
|
}
|
|
39
52
|
|
|
40
53
|
|
|
54
|
+
CAP_STYLE_MAP = {
|
|
55
|
+
CapStyleType.AUTO: None, # TODO: this could be improved
|
|
56
|
+
CapStyleType.ROUND: cairo.LineCap.ROUND,
|
|
57
|
+
CapStyleType.BUTT: cairo.LineCap.BUTT,
|
|
58
|
+
CapStyleType.SQUARE: cairo.LineCap.SQUARE,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
41
62
|
class Camera:
|
|
42
63
|
"""Base camera class.
|
|
43
64
|
|
|
@@ -63,20 +84,22 @@ class Camera:
|
|
|
63
84
|
def __init__(
|
|
64
85
|
self,
|
|
65
86
|
background_image: str | None = None,
|
|
66
|
-
frame_center:
|
|
87
|
+
frame_center: Point3D = ORIGIN,
|
|
67
88
|
image_mode: str = "RGBA",
|
|
68
89
|
n_channels: int = 4,
|
|
69
90
|
pixel_array_dtype: str = "uint8",
|
|
70
91
|
cairo_line_width_multiple: float = 0.01,
|
|
71
92
|
use_z_index: bool = True,
|
|
72
|
-
background:
|
|
93
|
+
background: PixelArray | None = None,
|
|
73
94
|
pixel_height: int | None = None,
|
|
74
95
|
pixel_width: int | None = None,
|
|
75
96
|
frame_height: float | None = None,
|
|
76
97
|
frame_width: float | None = None,
|
|
77
98
|
frame_rate: float | None = None,
|
|
78
|
-
|
|
79
|
-
|
|
99
|
+
background_color: ParsableManimColor | None = None,
|
|
100
|
+
background_opacity: float | None = None,
|
|
101
|
+
**kwargs: Any,
|
|
102
|
+
) -> None:
|
|
80
103
|
self.background_image = background_image
|
|
81
104
|
self.frame_center = frame_center
|
|
82
105
|
self.image_mode = image_mode
|
|
@@ -85,6 +108,9 @@ class Camera:
|
|
|
85
108
|
self.cairo_line_width_multiple = cairo_line_width_multiple
|
|
86
109
|
self.use_z_index = use_z_index
|
|
87
110
|
self.background = background
|
|
111
|
+
self.background_colored_vmobject_displayer: (
|
|
112
|
+
BackgroundColoredVMobjectDisplayer | None
|
|
113
|
+
) = None
|
|
88
114
|
|
|
89
115
|
if pixel_height is None:
|
|
90
116
|
pixel_height = config["pixel_height"]
|
|
@@ -106,16 +132,23 @@ class Camera:
|
|
|
106
132
|
frame_rate = config["frame_rate"]
|
|
107
133
|
self.frame_rate = frame_rate
|
|
108
134
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
if background_color is None:
|
|
136
|
+
self._background_color: ManimColor = ManimColor.parse(
|
|
137
|
+
config["background_color"]
|
|
138
|
+
)
|
|
139
|
+
else:
|
|
140
|
+
self._background_color = ManimColor.parse(background_color)
|
|
141
|
+
if background_opacity is None:
|
|
142
|
+
self._background_opacity: float = config["background_opacity"]
|
|
143
|
+
else:
|
|
144
|
+
self._background_opacity = background_opacity
|
|
112
145
|
|
|
113
146
|
# This one is in the same boat as the above, but it doesn't have the
|
|
114
147
|
# same name as the corresponding key so it has to be handled on its own
|
|
115
148
|
self.max_allowable_norm = config["frame_width"]
|
|
116
149
|
|
|
117
150
|
self.rgb_max_val = np.iinfo(self.pixel_array_dtype).max
|
|
118
|
-
self.pixel_array_to_cairo_context = {}
|
|
151
|
+
self.pixel_array_to_cairo_context: dict[int, cairo.Context] = {}
|
|
119
152
|
|
|
120
153
|
# Contains the correct method to process a list of Mobjects of the
|
|
121
154
|
# corresponding class. If a Mobject is not an instance of a class in
|
|
@@ -126,7 +159,7 @@ class Camera:
|
|
|
126
159
|
self.resize_frame_shape()
|
|
127
160
|
self.reset()
|
|
128
161
|
|
|
129
|
-
def __deepcopy__(self, memo):
|
|
162
|
+
def __deepcopy__(self, memo: Any) -> Camera:
|
|
130
163
|
# This is to address a strange bug where deepcopying
|
|
131
164
|
# will result in a segfault, which is somehow related
|
|
132
165
|
# to the aggdraw library
|
|
@@ -134,24 +167,26 @@ class Camera:
|
|
|
134
167
|
return copy.copy(self)
|
|
135
168
|
|
|
136
169
|
@property
|
|
137
|
-
def background_color(self):
|
|
170
|
+
def background_color(self) -> ManimColor:
|
|
138
171
|
return self._background_color
|
|
139
172
|
|
|
140
173
|
@background_color.setter
|
|
141
|
-
def background_color(self, color):
|
|
174
|
+
def background_color(self, color: ManimColor) -> None:
|
|
142
175
|
self._background_color = color
|
|
143
176
|
self.init_background()
|
|
144
177
|
|
|
145
178
|
@property
|
|
146
|
-
def background_opacity(self):
|
|
179
|
+
def background_opacity(self) -> float:
|
|
147
180
|
return self._background_opacity
|
|
148
181
|
|
|
149
182
|
@background_opacity.setter
|
|
150
|
-
def background_opacity(self, alpha):
|
|
183
|
+
def background_opacity(self, alpha: float) -> None:
|
|
151
184
|
self._background_opacity = alpha
|
|
152
185
|
self.init_background()
|
|
153
186
|
|
|
154
|
-
def type_or_raise(
|
|
187
|
+
def type_or_raise(
|
|
188
|
+
self, mobject: Mobject
|
|
189
|
+
) -> type[VMobject] | type[PMobject] | type[AbstractImageMobject] | type[Mobject]:
|
|
155
190
|
"""Return the type of mobject, if it is a type that can be rendered.
|
|
156
191
|
|
|
157
192
|
If `mobject` is an instance of a class that inherits from a class that
|
|
@@ -178,10 +213,14 @@ class Camera:
|
|
|
178
213
|
:exc:`TypeError`
|
|
179
214
|
When mobject is not an instance of a class that can be rendered.
|
|
180
215
|
"""
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
216
|
+
from ..mobject.types.image_mobject import AbstractImageMobject
|
|
217
|
+
|
|
218
|
+
self.display_funcs: dict[
|
|
219
|
+
type[Mobject], Callable[[list[Mobject], PixelArray], Any]
|
|
220
|
+
] = {
|
|
221
|
+
VMobject: self.display_multiple_vectorized_mobjects, # type: ignore[dict-item]
|
|
222
|
+
PMobject: self.display_multiple_point_cloud_mobjects, # type: ignore[dict-item]
|
|
223
|
+
AbstractImageMobject: self.display_multiple_image_mobjects, # type: ignore[dict-item]
|
|
185
224
|
Mobject: lambda batch, pa: batch, # Do nothing
|
|
186
225
|
}
|
|
187
226
|
# We have to check each type in turn because we are dealing with
|
|
@@ -192,7 +231,7 @@ class Camera:
|
|
|
192
231
|
return _type
|
|
193
232
|
raise TypeError(f"Displaying an object of class {_type} is not supported")
|
|
194
233
|
|
|
195
|
-
def reset_pixel_shape(self, new_height: float, new_width: float):
|
|
234
|
+
def reset_pixel_shape(self, new_height: float, new_width: float) -> None:
|
|
196
235
|
"""This method resets the height and width
|
|
197
236
|
of a single pixel to the passed new_height and new_width.
|
|
198
237
|
|
|
@@ -209,7 +248,7 @@ class Camera:
|
|
|
209
248
|
self.resize_frame_shape()
|
|
210
249
|
self.reset()
|
|
211
250
|
|
|
212
|
-
def resize_frame_shape(self, fixed_dimension: int = 0):
|
|
251
|
+
def resize_frame_shape(self, fixed_dimension: int = 0) -> None:
|
|
213
252
|
"""
|
|
214
253
|
Changes frame_shape to match the aspect ratio
|
|
215
254
|
of the pixels, where fixed_dimension determines
|
|
@@ -234,7 +273,7 @@ class Camera:
|
|
|
234
273
|
self.frame_height = frame_height
|
|
235
274
|
self.frame_width = frame_width
|
|
236
275
|
|
|
237
|
-
def init_background(self):
|
|
276
|
+
def init_background(self) -> None:
|
|
238
277
|
"""Initialize the background.
|
|
239
278
|
If self.background_image is the path of an image
|
|
240
279
|
the image is set as background; else, the default
|
|
@@ -260,7 +299,9 @@ class Camera:
|
|
|
260
299
|
)
|
|
261
300
|
self.background[:, :] = background_rgba
|
|
262
301
|
|
|
263
|
-
def get_image(
|
|
302
|
+
def get_image(
|
|
303
|
+
self, pixel_array: PixelArray | list | tuple | None = None
|
|
304
|
+
) -> Image.Image:
|
|
264
305
|
"""Returns an image from the passed
|
|
265
306
|
pixel array, or from the current frame
|
|
266
307
|
if the passed pixel array is none.
|
|
@@ -272,7 +313,7 @@ class Camera:
|
|
|
272
313
|
|
|
273
314
|
Returns
|
|
274
315
|
-------
|
|
275
|
-
PIL.Image
|
|
316
|
+
PIL.Image.Image
|
|
276
317
|
The PIL image of the array.
|
|
277
318
|
"""
|
|
278
319
|
if pixel_array is None:
|
|
@@ -280,8 +321,8 @@ class Camera:
|
|
|
280
321
|
return Image.fromarray(pixel_array, mode=self.image_mode)
|
|
281
322
|
|
|
282
323
|
def convert_pixel_array(
|
|
283
|
-
self, pixel_array:
|
|
284
|
-
):
|
|
324
|
+
self, pixel_array: PixelArray | list | tuple, convert_from_floats: bool = False
|
|
325
|
+
) -> PixelArray:
|
|
285
326
|
"""Converts a pixel array from values that have floats in then
|
|
286
327
|
to proper RGB values.
|
|
287
328
|
|
|
@@ -307,8 +348,8 @@ class Camera:
|
|
|
307
348
|
return retval
|
|
308
349
|
|
|
309
350
|
def set_pixel_array(
|
|
310
|
-
self, pixel_array:
|
|
311
|
-
):
|
|
351
|
+
self, pixel_array: PixelArray | list | tuple, convert_from_floats: bool = False
|
|
352
|
+
) -> None:
|
|
312
353
|
"""Sets the pixel array of the camera to the passed pixel array.
|
|
313
354
|
|
|
314
355
|
Parameters
|
|
@@ -318,19 +359,21 @@ class Camera:
|
|
|
318
359
|
convert_from_floats
|
|
319
360
|
Whether or not to convert float values to proper RGB values, by default False
|
|
320
361
|
"""
|
|
321
|
-
converted_array = self.convert_pixel_array(
|
|
362
|
+
converted_array: PixelArray = self.convert_pixel_array(
|
|
363
|
+
pixel_array, convert_from_floats
|
|
364
|
+
)
|
|
322
365
|
if not (
|
|
323
366
|
hasattr(self, "pixel_array")
|
|
324
367
|
and self.pixel_array.shape == converted_array.shape
|
|
325
368
|
):
|
|
326
|
-
self.pixel_array = converted_array
|
|
369
|
+
self.pixel_array: PixelArray = converted_array
|
|
327
370
|
else:
|
|
328
371
|
# Set in place
|
|
329
372
|
self.pixel_array[:, :, :] = converted_array[:, :, :]
|
|
330
373
|
|
|
331
374
|
def set_background(
|
|
332
|
-
self, pixel_array:
|
|
333
|
-
):
|
|
375
|
+
self, pixel_array: PixelArray | list | tuple, convert_from_floats: bool = False
|
|
376
|
+
) -> None:
|
|
334
377
|
"""Sets the background to the passed pixel_array after converting
|
|
335
378
|
to valid RGB values.
|
|
336
379
|
|
|
@@ -346,7 +389,7 @@ class Camera:
|
|
|
346
389
|
# TODO, this should live in utils, not as a method of Camera
|
|
347
390
|
def make_background_from_func(
|
|
348
391
|
self, coords_to_colors_func: Callable[[np.ndarray], np.ndarray]
|
|
349
|
-
):
|
|
392
|
+
) -> PixelArray:
|
|
350
393
|
"""
|
|
351
394
|
Makes a pixel array for the background by using coords_to_colors_func to determine each pixel's color. Each input
|
|
352
395
|
pixel's color. Each input to coords_to_colors_func is an (x, y) pair in space (in ordinary space coordinates; not
|
|
@@ -363,7 +406,6 @@ class Camera:
|
|
|
363
406
|
np.array
|
|
364
407
|
The pixel array which can then be passed to set_background.
|
|
365
408
|
"""
|
|
366
|
-
|
|
367
409
|
logger.info("Starting set_background")
|
|
368
410
|
coords = self.get_coords_of_all_pixels()
|
|
369
411
|
new_background = np.apply_along_axis(coords_to_colors_func, 2, coords)
|
|
@@ -373,7 +415,7 @@ class Camera:
|
|
|
373
415
|
|
|
374
416
|
def set_background_from_func(
|
|
375
417
|
self, coords_to_colors_func: Callable[[np.ndarray], np.ndarray]
|
|
376
|
-
):
|
|
418
|
+
) -> None:
|
|
377
419
|
"""
|
|
378
420
|
Sets the background to a pixel array using coords_to_colors_func to determine each pixel's color. Each input
|
|
379
421
|
pixel's color. Each input to coords_to_colors_func is an (x, y) pair in space (in ordinary space coordinates; not
|
|
@@ -387,7 +429,7 @@ class Camera:
|
|
|
387
429
|
"""
|
|
388
430
|
self.set_background(self.make_background_from_func(coords_to_colors_func))
|
|
389
431
|
|
|
390
|
-
def reset(self):
|
|
432
|
+
def reset(self) -> Self:
|
|
391
433
|
"""Resets the camera's pixel array
|
|
392
434
|
to that of the background
|
|
393
435
|
|
|
@@ -399,7 +441,7 @@ class Camera:
|
|
|
399
441
|
self.set_pixel_array(self.background)
|
|
400
442
|
return self
|
|
401
443
|
|
|
402
|
-
def set_frame_to_background(self, background):
|
|
444
|
+
def set_frame_to_background(self, background: PixelArray) -> None:
|
|
403
445
|
self.set_pixel_array(background)
|
|
404
446
|
|
|
405
447
|
####
|
|
@@ -409,7 +451,7 @@ class Camera:
|
|
|
409
451
|
mobjects: Iterable[Mobject],
|
|
410
452
|
include_submobjects: bool = True,
|
|
411
453
|
excluded_mobjects: list | None = None,
|
|
412
|
-
):
|
|
454
|
+
) -> list[Mobject]:
|
|
413
455
|
"""Used to get the list of mobjects to display
|
|
414
456
|
with the camera.
|
|
415
457
|
|
|
@@ -441,7 +483,7 @@ class Camera:
|
|
|
441
483
|
mobjects = list_difference_update(mobjects, all_excluded)
|
|
442
484
|
return list(mobjects)
|
|
443
485
|
|
|
444
|
-
def is_in_frame(self, mobject: Mobject):
|
|
486
|
+
def is_in_frame(self, mobject: Mobject) -> bool:
|
|
445
487
|
"""Checks whether the passed mobject is in
|
|
446
488
|
frame or not.
|
|
447
489
|
|
|
@@ -468,7 +510,7 @@ class Camera:
|
|
|
468
510
|
],
|
|
469
511
|
)
|
|
470
512
|
|
|
471
|
-
def capture_mobject(self, mobject: Mobject, **kwargs: Any):
|
|
513
|
+
def capture_mobject(self, mobject: Mobject, **kwargs: Any) -> None:
|
|
472
514
|
"""Capture mobjects by storing it in :attr:`pixel_array`.
|
|
473
515
|
|
|
474
516
|
This is a single-mobject version of :meth:`capture_mobjects`.
|
|
@@ -484,7 +526,7 @@ class Camera:
|
|
|
484
526
|
"""
|
|
485
527
|
return self.capture_mobjects([mobject], **kwargs)
|
|
486
528
|
|
|
487
|
-
def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs):
|
|
529
|
+
def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs: Any) -> None:
|
|
488
530
|
"""Capture mobjects by printing them on :attr:`pixel_array`.
|
|
489
531
|
|
|
490
532
|
This is the essential function that converts the contents of a Scene
|
|
@@ -519,7 +561,7 @@ class Camera:
|
|
|
519
561
|
# NOTE: None of the methods below have been mentioned outside of their definitions. Their DocStrings are not as
|
|
520
562
|
# detailed as possible.
|
|
521
563
|
|
|
522
|
-
def get_cached_cairo_context(self, pixel_array:
|
|
564
|
+
def get_cached_cairo_context(self, pixel_array: PixelArray) -> cairo.Context | None:
|
|
523
565
|
"""Returns the cached cairo context of the passed
|
|
524
566
|
pixel array if it exists, and None if it doesn't.
|
|
525
567
|
|
|
@@ -535,7 +577,7 @@ class Camera:
|
|
|
535
577
|
"""
|
|
536
578
|
return self.pixel_array_to_cairo_context.get(id(pixel_array), None)
|
|
537
579
|
|
|
538
|
-
def cache_cairo_context(self, pixel_array:
|
|
580
|
+
def cache_cairo_context(self, pixel_array: PixelArray, ctx: cairo.Context) -> None:
|
|
539
581
|
"""Caches the passed Pixel array into a Cairo Context
|
|
540
582
|
|
|
541
583
|
Parameters
|
|
@@ -547,7 +589,7 @@ class Camera:
|
|
|
547
589
|
"""
|
|
548
590
|
self.pixel_array_to_cairo_context[id(pixel_array)] = ctx
|
|
549
591
|
|
|
550
|
-
def get_cairo_context(self, pixel_array:
|
|
592
|
+
def get_cairo_context(self, pixel_array: PixelArray) -> cairo.Context:
|
|
551
593
|
"""Returns the cairo context for a pixel array after
|
|
552
594
|
caching it to self.pixel_array_to_cairo_context
|
|
553
595
|
If that array has already been cached, it returns the
|
|
@@ -572,7 +614,7 @@ class Camera:
|
|
|
572
614
|
fh = self.frame_height
|
|
573
615
|
fc = self.frame_center
|
|
574
616
|
surface = cairo.ImageSurface.create_for_data(
|
|
575
|
-
pixel_array,
|
|
617
|
+
pixel_array.data,
|
|
576
618
|
cairo.FORMAT_ARGB32,
|
|
577
619
|
pw,
|
|
578
620
|
ph,
|
|
@@ -593,8 +635,8 @@ class Camera:
|
|
|
593
635
|
return ctx
|
|
594
636
|
|
|
595
637
|
def display_multiple_vectorized_mobjects(
|
|
596
|
-
self, vmobjects: list, pixel_array:
|
|
597
|
-
):
|
|
638
|
+
self, vmobjects: list[VMobject], pixel_array: PixelArray
|
|
639
|
+
) -> None:
|
|
598
640
|
"""Displays multiple VMobjects in the pixel_array
|
|
599
641
|
|
|
600
642
|
Parameters
|
|
@@ -617,8 +659,8 @@ class Camera:
|
|
|
617
659
|
)
|
|
618
660
|
|
|
619
661
|
def display_multiple_non_background_colored_vmobjects(
|
|
620
|
-
self, vmobjects:
|
|
621
|
-
):
|
|
662
|
+
self, vmobjects: Iterable[VMobject], pixel_array: PixelArray
|
|
663
|
+
) -> None:
|
|
622
664
|
"""Displays multiple VMobjects in the cairo context, as long as they don't have
|
|
623
665
|
background colors.
|
|
624
666
|
|
|
@@ -633,7 +675,7 @@ class Camera:
|
|
|
633
675
|
for vmobject in vmobjects:
|
|
634
676
|
self.display_vectorized(vmobject, ctx)
|
|
635
677
|
|
|
636
|
-
def display_vectorized(self, vmobject: VMobject, ctx: cairo.Context):
|
|
678
|
+
def display_vectorized(self, vmobject: VMobject, ctx: cairo.Context) -> Self:
|
|
637
679
|
"""Displays a VMobject in the cairo context
|
|
638
680
|
|
|
639
681
|
Parameters
|
|
@@ -654,7 +696,7 @@ class Camera:
|
|
|
654
696
|
self.apply_stroke(ctx, vmobject)
|
|
655
697
|
return self
|
|
656
698
|
|
|
657
|
-
def set_cairo_context_path(self, ctx: cairo.Context, vmobject: VMobject):
|
|
699
|
+
def set_cairo_context_path(self, ctx: cairo.Context, vmobject: VMobject) -> Self:
|
|
658
700
|
"""Sets a path for the cairo context with the vmobject passed
|
|
659
701
|
|
|
660
702
|
Parameters
|
|
@@ -673,7 +715,7 @@ class Camera:
|
|
|
673
715
|
# TODO, shouldn't this be handled in transform_points_pre_display?
|
|
674
716
|
# points = points - self.get_frame_center()
|
|
675
717
|
if len(points) == 0:
|
|
676
|
-
return
|
|
718
|
+
return self
|
|
677
719
|
|
|
678
720
|
ctx.new_path()
|
|
679
721
|
subpaths = vmobject.gen_subpaths_from_points_2d(points)
|
|
@@ -689,8 +731,8 @@ class Camera:
|
|
|
689
731
|
return self
|
|
690
732
|
|
|
691
733
|
def set_cairo_context_color(
|
|
692
|
-
self, ctx: cairo.Context, rgbas:
|
|
693
|
-
):
|
|
734
|
+
self, ctx: cairo.Context, rgbas: FloatRGBALike_Array, vmobject: VMobject
|
|
735
|
+
) -> Self:
|
|
694
736
|
"""Sets the color of the cairo context
|
|
695
737
|
|
|
696
738
|
Parameters
|
|
@@ -722,7 +764,7 @@ class Camera:
|
|
|
722
764
|
ctx.set_source(pat)
|
|
723
765
|
return self
|
|
724
766
|
|
|
725
|
-
def apply_fill(self, ctx: cairo.Context, vmobject: VMobject):
|
|
767
|
+
def apply_fill(self, ctx: cairo.Context, vmobject: VMobject) -> Self:
|
|
726
768
|
"""Fills the cairo context
|
|
727
769
|
|
|
728
770
|
Parameters
|
|
@@ -743,7 +785,7 @@ class Camera:
|
|
|
743
785
|
|
|
744
786
|
def apply_stroke(
|
|
745
787
|
self, ctx: cairo.Context, vmobject: VMobject, background: bool = False
|
|
746
|
-
):
|
|
788
|
+
) -> Self:
|
|
747
789
|
"""Applies a stroke to the VMobject in the cairo context.
|
|
748
790
|
|
|
749
791
|
Parameters
|
|
@@ -772,15 +814,19 @@ class Camera:
|
|
|
772
814
|
ctx.set_line_width(
|
|
773
815
|
width
|
|
774
816
|
* self.cairo_line_width_multiple
|
|
775
|
-
# This ensures lines have constant width as you zoom in on them.
|
|
776
817
|
* (self.frame_width / self.frame_width),
|
|
818
|
+
# This ensures lines have constant width as you zoom in on them.
|
|
777
819
|
)
|
|
778
820
|
if vmobject.joint_type != LineJointType.AUTO:
|
|
779
821
|
ctx.set_line_join(LINE_JOIN_MAP[vmobject.joint_type])
|
|
822
|
+
if vmobject.cap_style != CapStyleType.AUTO:
|
|
823
|
+
ctx.set_line_cap(CAP_STYLE_MAP[vmobject.cap_style])
|
|
780
824
|
ctx.stroke_preserve()
|
|
781
825
|
return self
|
|
782
826
|
|
|
783
|
-
def get_stroke_rgbas(
|
|
827
|
+
def get_stroke_rgbas(
|
|
828
|
+
self, vmobject: VMobject, background: bool = False
|
|
829
|
+
) -> FloatRGBA_Array:
|
|
784
830
|
"""Gets the RGBA array for the stroke of the passed
|
|
785
831
|
VMobject.
|
|
786
832
|
|
|
@@ -799,7 +845,7 @@ class Camera:
|
|
|
799
845
|
"""
|
|
800
846
|
return vmobject.get_stroke_rgbas(background)
|
|
801
847
|
|
|
802
|
-
def get_fill_rgbas(self, vmobject: VMobject):
|
|
848
|
+
def get_fill_rgbas(self, vmobject: VMobject) -> FloatRGBA_Array:
|
|
803
849
|
"""Returns the RGBA array of the fill of the passed VMobject
|
|
804
850
|
|
|
805
851
|
Parameters
|
|
@@ -814,25 +860,27 @@ class Camera:
|
|
|
814
860
|
"""
|
|
815
861
|
return vmobject.get_fill_rgbas()
|
|
816
862
|
|
|
817
|
-
def get_background_colored_vmobject_displayer(
|
|
863
|
+
def get_background_colored_vmobject_displayer(
|
|
864
|
+
self,
|
|
865
|
+
) -> BackgroundColoredVMobjectDisplayer:
|
|
818
866
|
"""Returns the background_colored_vmobject_displayer
|
|
819
867
|
if it exists or makes one and returns it if not.
|
|
820
868
|
|
|
821
869
|
Returns
|
|
822
870
|
-------
|
|
823
|
-
|
|
871
|
+
BackgroundColoredVMobjectDisplayer
|
|
824
872
|
Object that displays VMobjects that have the same color
|
|
825
873
|
as the background.
|
|
826
874
|
"""
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
return
|
|
875
|
+
if self.background_colored_vmobject_displayer is None:
|
|
876
|
+
self.background_colored_vmobject_displayer = (
|
|
877
|
+
BackgroundColoredVMobjectDisplayer(self)
|
|
878
|
+
)
|
|
879
|
+
return self.background_colored_vmobject_displayer
|
|
832
880
|
|
|
833
881
|
def display_multiple_background_colored_vmobjects(
|
|
834
|
-
self, cvmobjects:
|
|
835
|
-
):
|
|
882
|
+
self, cvmobjects: Iterable[VMobject], pixel_array: PixelArray
|
|
883
|
+
) -> Self:
|
|
836
884
|
"""Displays multiple vmobjects that have the same color as the background.
|
|
837
885
|
|
|
838
886
|
Parameters
|
|
@@ -858,8 +906,8 @@ class Camera:
|
|
|
858
906
|
# As a result, the other methods do not have as detailed docstrings as would be preferred.
|
|
859
907
|
|
|
860
908
|
def display_multiple_point_cloud_mobjects(
|
|
861
|
-
self, pmobjects:
|
|
862
|
-
):
|
|
909
|
+
self, pmobjects: Iterable[PMobject], pixel_array: PixelArray
|
|
910
|
+
) -> None:
|
|
863
911
|
"""Displays multiple PMobjects by modifying the passed pixel array.
|
|
864
912
|
|
|
865
913
|
Parameters
|
|
@@ -881,13 +929,15 @@ class Camera:
|
|
|
881
929
|
def display_point_cloud(
|
|
882
930
|
self,
|
|
883
931
|
pmobject: PMobject,
|
|
884
|
-
points:
|
|
885
|
-
rgbas:
|
|
932
|
+
points: Point3D_Array,
|
|
933
|
+
rgbas: FloatRGBA_Array,
|
|
886
934
|
thickness: float,
|
|
887
|
-
pixel_array:
|
|
888
|
-
):
|
|
889
|
-
"""Displays a PMobject by modifying the
|
|
935
|
+
pixel_array: PixelArray,
|
|
936
|
+
) -> None:
|
|
937
|
+
"""Displays a PMobject by modifying the pixel array suitably.
|
|
938
|
+
|
|
890
939
|
TODO: Write a description for the rgbas argument.
|
|
940
|
+
|
|
891
941
|
Parameters
|
|
892
942
|
----------
|
|
893
943
|
pmobject
|
|
@@ -930,8 +980,10 @@ class Camera:
|
|
|
930
980
|
pixel_array[:, :] = new_pa.reshape((ph, pw, rgba_len))
|
|
931
981
|
|
|
932
982
|
def display_multiple_image_mobjects(
|
|
933
|
-
self,
|
|
934
|
-
|
|
983
|
+
self,
|
|
984
|
+
image_mobjects: Iterable[AbstractImageMobject],
|
|
985
|
+
pixel_array: PixelArray,
|
|
986
|
+
) -> None:
|
|
935
987
|
"""Displays multiple image mobjects by modifying the passed pixel_array.
|
|
936
988
|
|
|
937
989
|
Parameters
|
|
@@ -946,7 +998,7 @@ class Camera:
|
|
|
946
998
|
|
|
947
999
|
def display_image_mobject(
|
|
948
1000
|
self, image_mobject: AbstractImageMobject, pixel_array: np.ndarray
|
|
949
|
-
):
|
|
1001
|
+
) -> None:
|
|
950
1002
|
"""Displays an ImageMobject by changing the pixel_array suitably.
|
|
951
1003
|
|
|
952
1004
|
Parameters
|
|
@@ -957,7 +1009,7 @@ class Camera:
|
|
|
957
1009
|
The Pixel array to put the imagemobject in.
|
|
958
1010
|
"""
|
|
959
1011
|
corner_coords = self.points_to_pixel_coords(image_mobject, image_mobject.points)
|
|
960
|
-
ul_coords, ur_coords, dl_coords = corner_coords
|
|
1012
|
+
ul_coords, ur_coords, dl_coords, _ = corner_coords
|
|
961
1013
|
right_vect = ur_coords - ul_coords
|
|
962
1014
|
down_vect = dl_coords - ul_coords
|
|
963
1015
|
center_coords = ul_coords + (right_vect + down_vect) / 2
|
|
@@ -965,8 +1017,8 @@ class Camera:
|
|
|
965
1017
|
sub_image = Image.fromarray(image_mobject.get_pixel_array(), mode="RGBA")
|
|
966
1018
|
|
|
967
1019
|
# Reshape
|
|
968
|
-
pixel_width = max(int(pdist([ul_coords, ur_coords])), 1)
|
|
969
|
-
pixel_height = max(int(pdist([ul_coords, dl_coords])), 1)
|
|
1020
|
+
pixel_width = max(int(pdist([ul_coords, ur_coords]).item()), 1)
|
|
1021
|
+
pixel_height = max(int(pdist([ul_coords, dl_coords]).item()), 1)
|
|
970
1022
|
sub_image = sub_image.resize(
|
|
971
1023
|
(pixel_width, pixel_height),
|
|
972
1024
|
resample=image_mobject.resampling_algorithm,
|
|
@@ -1003,7 +1055,9 @@ class Camera:
|
|
|
1003
1055
|
# Paint on top of existing pixel array
|
|
1004
1056
|
self.overlay_PIL_image(pixel_array, full_image)
|
|
1005
1057
|
|
|
1006
|
-
def overlay_rgba_array(
|
|
1058
|
+
def overlay_rgba_array(
|
|
1059
|
+
self, pixel_array: np.ndarray, new_array: np.ndarray
|
|
1060
|
+
) -> None:
|
|
1007
1061
|
"""Overlays an RGBA array on top of the given Pixel array.
|
|
1008
1062
|
|
|
1009
1063
|
Parameters
|
|
@@ -1015,7 +1069,7 @@ class Camera:
|
|
|
1015
1069
|
"""
|
|
1016
1070
|
self.overlay_PIL_image(pixel_array, self.get_image(new_array))
|
|
1017
1071
|
|
|
1018
|
-
def overlay_PIL_image(self, pixel_array: np.ndarray, image: Image):
|
|
1072
|
+
def overlay_PIL_image(self, pixel_array: np.ndarray, image: Image) -> None:
|
|
1019
1073
|
"""Overlays a PIL image on the passed pixel array.
|
|
1020
1074
|
|
|
1021
1075
|
Parameters
|
|
@@ -1030,7 +1084,7 @@ class Camera:
|
|
|
1030
1084
|
dtype="uint8",
|
|
1031
1085
|
)
|
|
1032
1086
|
|
|
1033
|
-
def adjust_out_of_range_points(self, points: np.ndarray):
|
|
1087
|
+
def adjust_out_of_range_points(self, points: np.ndarray) -> np.ndarray:
|
|
1034
1088
|
"""If any of the points in the passed array are out of
|
|
1035
1089
|
the viable range, they are adjusted suitably.
|
|
1036
1090
|
|
|
@@ -1061,9 +1115,9 @@ class Camera:
|
|
|
1061
1115
|
|
|
1062
1116
|
def transform_points_pre_display(
|
|
1063
1117
|
self,
|
|
1064
|
-
mobject,
|
|
1065
|
-
points,
|
|
1066
|
-
): # TODO: Write more detailed docstrings for this method.
|
|
1118
|
+
mobject: Mobject,
|
|
1119
|
+
points: Point3D_Array,
|
|
1120
|
+
) -> Point3D_Array: # TODO: Write more detailed docstrings for this method.
|
|
1067
1121
|
# NOTE: There seems to be an unused argument `mobject`.
|
|
1068
1122
|
|
|
1069
1123
|
# Subclasses (like ThreeDCamera) may want to
|
|
@@ -1076,9 +1130,9 @@ class Camera:
|
|
|
1076
1130
|
|
|
1077
1131
|
def points_to_pixel_coords(
|
|
1078
1132
|
self,
|
|
1079
|
-
mobject,
|
|
1080
|
-
points,
|
|
1081
|
-
): # TODO: Write more detailed docstrings for this method.
|
|
1133
|
+
mobject: Mobject,
|
|
1134
|
+
points: Point3D_Array,
|
|
1135
|
+
) -> npt.NDArray[ManimInt]: # TODO: Write more detailed docstrings for this method.
|
|
1082
1136
|
points = self.transform_points_pre_display(mobject, points)
|
|
1083
1137
|
shifted_points = points - self.frame_center
|
|
1084
1138
|
|
|
@@ -1098,7 +1152,7 @@ class Camera:
|
|
|
1098
1152
|
result[:, 1] = shifted_points[:, 1] * height_mult + height_add
|
|
1099
1153
|
return result.astype("int")
|
|
1100
1154
|
|
|
1101
|
-
def on_screen_pixels(self, pixel_coords: np.ndarray):
|
|
1155
|
+
def on_screen_pixels(self, pixel_coords: np.ndarray) -> PixelArray:
|
|
1102
1156
|
"""Returns array of pixels that are on the screen from a given
|
|
1103
1157
|
array of pixel_coordinates
|
|
1104
1158
|
|
|
@@ -1122,26 +1176,29 @@ class Camera:
|
|
|
1122
1176
|
],
|
|
1123
1177
|
)
|
|
1124
1178
|
|
|
1125
|
-
def adjusted_thickness(self, thickness: float):
|
|
1126
|
-
"""
|
|
1179
|
+
def adjusted_thickness(self, thickness: float) -> float:
|
|
1180
|
+
"""Computes the adjusted stroke width for a zoomed camera.
|
|
1127
1181
|
|
|
1128
1182
|
Parameters
|
|
1129
1183
|
----------
|
|
1130
1184
|
thickness
|
|
1185
|
+
The stroke width of a mobject.
|
|
1131
1186
|
|
|
1132
1187
|
Returns
|
|
1133
1188
|
-------
|
|
1134
1189
|
float
|
|
1135
|
-
|
|
1190
|
+
The adjusted stroke width that reflects zooming in with
|
|
1191
|
+
the camera.
|
|
1136
1192
|
"""
|
|
1137
1193
|
# TODO: This seems...unsystematic
|
|
1138
|
-
big_sum = op.add(config["pixel_height"], config["pixel_width"])
|
|
1139
|
-
this_sum = op.add(self.pixel_height, self.pixel_width)
|
|
1194
|
+
big_sum: float = op.add(config["pixel_height"], config["pixel_width"])
|
|
1195
|
+
this_sum: float = op.add(self.pixel_height, self.pixel_width)
|
|
1140
1196
|
factor = big_sum / this_sum
|
|
1141
1197
|
return 1 + (thickness - 1) * factor
|
|
1142
1198
|
|
|
1143
|
-
def get_thickening_nudges(self, thickness: float):
|
|
1144
|
-
"""
|
|
1199
|
+
def get_thickening_nudges(self, thickness: float) -> PixelArray:
|
|
1200
|
+
"""Determine a list of vectors used to nudge
|
|
1201
|
+
two-dimensional pixel coordinates.
|
|
1145
1202
|
|
|
1146
1203
|
Parameters
|
|
1147
1204
|
----------
|
|
@@ -1156,7 +1213,9 @@ class Camera:
|
|
|
1156
1213
|
_range = list(range(-thickness // 2 + 1, thickness // 2 + 1))
|
|
1157
1214
|
return np.array(list(it.product(_range, _range)))
|
|
1158
1215
|
|
|
1159
|
-
def thickened_coordinates(
|
|
1216
|
+
def thickened_coordinates(
|
|
1217
|
+
self, pixel_coords: np.ndarray, thickness: float
|
|
1218
|
+
) -> PixelArray:
|
|
1160
1219
|
"""Returns thickened coordinates for a passed array of pixel coords and
|
|
1161
1220
|
a thickness to thicken by.
|
|
1162
1221
|
|
|
@@ -1178,7 +1237,7 @@ class Camera:
|
|
|
1178
1237
|
return pixel_coords.reshape((size // 2, 2))
|
|
1179
1238
|
|
|
1180
1239
|
# TODO, reimplement using cairo matrix
|
|
1181
|
-
def get_coords_of_all_pixels(self):
|
|
1240
|
+
def get_coords_of_all_pixels(self) -> PixelArray:
|
|
1182
1241
|
"""Returns the cartesian coordinates of each pixel.
|
|
1183
1242
|
|
|
1184
1243
|
Returns
|
|
@@ -1215,28 +1274,31 @@ class Camera:
|
|
|
1215
1274
|
# NOTE: The methods of the following class have not been mentioned outside of their definitions.
|
|
1216
1275
|
# Their DocStrings are not as detailed as preferred.
|
|
1217
1276
|
class BackgroundColoredVMobjectDisplayer:
|
|
1277
|
+
"""Auxiliary class that handles displaying vectorized mobjects with
|
|
1278
|
+
a set background image.
|
|
1279
|
+
|
|
1280
|
+
Parameters
|
|
1281
|
+
----------
|
|
1282
|
+
camera
|
|
1283
|
+
Camera object to use.
|
|
1284
|
+
"""
|
|
1285
|
+
|
|
1218
1286
|
def __init__(self, camera: Camera):
|
|
1219
|
-
"""
|
|
1220
|
-
Parameters
|
|
1221
|
-
----------
|
|
1222
|
-
camera
|
|
1223
|
-
Camera object to use.
|
|
1224
|
-
"""
|
|
1225
1287
|
self.camera = camera
|
|
1226
|
-
self.file_name_to_pixel_array_map = {}
|
|
1288
|
+
self.file_name_to_pixel_array_map: dict[str, PixelArray] = {}
|
|
1227
1289
|
self.pixel_array = np.array(camera.pixel_array)
|
|
1228
1290
|
self.reset_pixel_array()
|
|
1229
1291
|
|
|
1230
|
-
def reset_pixel_array(self):
|
|
1292
|
+
def reset_pixel_array(self) -> None:
|
|
1231
1293
|
self.pixel_array[:, :] = 0
|
|
1232
1294
|
|
|
1233
1295
|
def resize_background_array(
|
|
1234
1296
|
self,
|
|
1235
|
-
background_array:
|
|
1297
|
+
background_array: PixelArray,
|
|
1236
1298
|
new_width: float,
|
|
1237
1299
|
new_height: float,
|
|
1238
1300
|
mode: str = "RGBA",
|
|
1239
|
-
):
|
|
1301
|
+
) -> PixelArray:
|
|
1240
1302
|
"""Resizes the pixel array representing the background.
|
|
1241
1303
|
|
|
1242
1304
|
Parameters
|
|
@@ -1261,8 +1323,8 @@ class BackgroundColoredVMobjectDisplayer:
|
|
|
1261
1323
|
return np.array(resized_image)
|
|
1262
1324
|
|
|
1263
1325
|
def resize_background_array_to_match(
|
|
1264
|
-
self, background_array:
|
|
1265
|
-
):
|
|
1326
|
+
self, background_array: PixelArray, pixel_array: PixelArray
|
|
1327
|
+
) -> PixelArray:
|
|
1266
1328
|
"""Resizes the background array to match the passed pixel array.
|
|
1267
1329
|
|
|
1268
1330
|
Parameters
|
|
@@ -1281,7 +1343,9 @@ class BackgroundColoredVMobjectDisplayer:
|
|
|
1281
1343
|
mode = "RGBA" if pixel_array.shape[2] == 4 else "RGB"
|
|
1282
1344
|
return self.resize_background_array(background_array, width, height, mode)
|
|
1283
1345
|
|
|
1284
|
-
def get_background_array(
|
|
1346
|
+
def get_background_array(
|
|
1347
|
+
self, image: Image.Image | pathlib.Path | str
|
|
1348
|
+
) -> PixelArray:
|
|
1285
1349
|
"""Gets the background array that has the passed file_name.
|
|
1286
1350
|
|
|
1287
1351
|
Parameters
|
|
@@ -1310,7 +1374,7 @@ class BackgroundColoredVMobjectDisplayer:
|
|
|
1310
1374
|
self.file_name_to_pixel_array_map[image_key] = back_array
|
|
1311
1375
|
return back_array
|
|
1312
1376
|
|
|
1313
|
-
def display(self, *cvmobjects: VMobject):
|
|
1377
|
+
def display(self, *cvmobjects: VMobject) -> PixelArray | None:
|
|
1314
1378
|
"""Displays the colored VMobjects.
|
|
1315
1379
|
|
|
1316
1380
|
Parameters
|