manim 0.18.0.post0__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of manim might be problematic. Click here for more details.
- manim/__init__.py +3 -6
- manim/__main__.py +61 -20
- manim/_config/__init__.py +6 -3
- manim/_config/cli_colors.py +16 -8
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +14 -8
- manim/_config/utils.py +651 -472
- manim/animation/animation.py +152 -5
- manim/animation/composition.py +80 -39
- manim/animation/creation.py +196 -14
- manim/animation/fading.py +5 -9
- manim/animation/indication.py +103 -47
- manim/animation/movement.py +22 -5
- manim/animation/rotation.py +3 -2
- manim/animation/specialized.py +4 -6
- manim/animation/speedmodifier.py +10 -5
- manim/animation/transform.py +4 -5
- manim/animation/transform_matching_parts.py +1 -1
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +15 -6
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +70 -44
- manim/cli/checkhealth/checks.py +93 -75
- manim/cli/checkhealth/commands.py +14 -5
- manim/cli/default_group.py +157 -25
- manim/cli/init/commands.py +32 -24
- manim/cli/plugins/commands.py +16 -3
- manim/cli/render/commands.py +72 -60
- manim/cli/render/ease_of_access_options.py +4 -3
- manim/cli/render/global_options.py +51 -15
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +97 -32
- manim/constants.py +65 -19
- manim/gui/gui.py +2 -0
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +112 -78
- manim/mobject/geometry/boolean_ops.py +32 -25
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +132 -64
- manim/mobject/geometry/polygram.py +126 -30
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +38 -29
- manim/mobject/graph.py +414 -133
- manim/mobject/graphing/coordinate_systems.py +126 -64
- manim/mobject/graphing/functions.py +25 -15
- manim/mobject/graphing/number_line.py +24 -10
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +314 -165
- manim/mobject/opengl/opengl_compatibility.py +2 -0
- manim/mobject/opengl/opengl_geometry.py +30 -9
- manim/mobject/opengl/opengl_image_mobject.py +2 -0
- manim/mobject/opengl/opengl_mobject.py +509 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
- manim/mobject/opengl/opengl_surface.py +3 -2
- manim/mobject/opengl/opengl_three_dimensions.py +2 -0
- manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
- manim/mobject/svg/brace.py +63 -13
- manim/mobject/svg/svg_mobject.py +4 -3
- manim/mobject/table.py +11 -13
- manim/mobject/text/code_mobject.py +186 -548
- manim/mobject/text/numbers.py +9 -7
- manim/mobject/text/tex_mobject.py +23 -14
- manim/mobject/text/text_mobject.py +70 -24
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_d_utils.py +4 -4
- manim/mobject/three_d/three_dimensions.py +62 -34
- manim/mobject/types/image_mobject.py +42 -24
- manim/mobject/types/point_cloud_mobject.py +105 -67
- manim/mobject/types/vectorized_mobject.py +496 -228
- manim/mobject/value_tracker.py +5 -4
- manim/mobject/vector_field.py +5 -5
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +14 -8
- manim/renderer/cairo_renderer.py +20 -10
- manim/renderer/opengl_renderer.py +21 -23
- manim/renderer/opengl_renderer_window.py +2 -0
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +5 -2
- manim/renderer/vectorized_mobject_rendering.py +5 -0
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +90 -43
- manim/scene/scene_file_writer.py +316 -165
- manim/scene/section.py +17 -15
- manim/scene/three_d_scene.py +13 -21
- manim/scene/vector_space_scene.py +22 -9
- manim/typing.py +830 -70
- manim/utils/bezier.py +1667 -399
- manim/utils/caching.py +13 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +3 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +3 -0
- manim/utils/color/XKCD.py +3 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +844 -309
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +90 -40
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +234 -0
- manim/utils/docbuild/autocolor_directive.py +21 -17
- manim/utils/docbuild/manim_directive.py +50 -35
- manim/utils/docbuild/module_parsing.py +245 -0
- manim/utils/exceptions.py +6 -0
- manim/utils/family.py +5 -3
- manim/utils/family_ops.py +17 -4
- manim/utils/file_ops.py +26 -16
- manim/utils/hashing.py +9 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +14 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +57 -19
- manim/utils/opengl.py +83 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +21 -23
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +74 -39
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +125 -69
- manim/utils/testing/__init__.py +17 -0
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +33 -18
- manim/utils/testing/frames_comparison.py +27 -19
- manim/utils/tex.py +127 -197
- manim/utils/tex_file_writing.py +47 -45
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim/cli/new/__init__.py +0 -0
- manim/cli/new/group.py +0 -189
- manim/plugins/import_plugins.py +0 -43
- manim-0.18.0.post0.dist-info/RECORD +0 -217
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
|
@@ -2,17 +2,116 @@ r"""Mobjects that inherit from lines and contain a label along the length."""
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
__all__ = ["LabeledLine", "LabeledArrow"]
|
|
5
|
+
__all__ = ["Label", "LabeledLine", "LabeledArrow", "LabeledPolygram"]
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
6
10
|
|
|
7
11
|
from manim.constants import *
|
|
8
12
|
from manim.mobject.geometry.line import Arrow, Line
|
|
13
|
+
from manim.mobject.geometry.polygram import Polygram
|
|
9
14
|
from manim.mobject.geometry.shape_matchers import (
|
|
10
15
|
BackgroundRectangle,
|
|
11
16
|
SurroundingRectangle,
|
|
12
17
|
)
|
|
13
18
|
from manim.mobject.text.tex_mobject import MathTex, Tex
|
|
14
19
|
from manim.mobject.text.text_mobject import Text
|
|
15
|
-
from manim.
|
|
20
|
+
from manim.mobject.types.vectorized_mobject import VGroup
|
|
21
|
+
from manim.utils.color import WHITE
|
|
22
|
+
from manim.utils.polylabel import polylabel
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
from manim.typing import Point3DLike_Array
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Label(VGroup):
|
|
31
|
+
"""A Label consisting of text surrounded by a frame.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
label
|
|
36
|
+
Label that will be displayed.
|
|
37
|
+
label_config
|
|
38
|
+
A dictionary containing the configuration for the label.
|
|
39
|
+
This is only applied if ``label`` is of type ``str``.
|
|
40
|
+
box_config
|
|
41
|
+
A dictionary containing the configuration for the background box.
|
|
42
|
+
frame_config
|
|
43
|
+
A dictionary containing the configuration for the frame.
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
.. manim:: LabelExample
|
|
48
|
+
:save_last_frame:
|
|
49
|
+
:quality: high
|
|
50
|
+
|
|
51
|
+
class LabelExample(Scene):
|
|
52
|
+
def construct(self):
|
|
53
|
+
label = Label(
|
|
54
|
+
label=Text('Label Text', font='sans-serif'),
|
|
55
|
+
box_config = {
|
|
56
|
+
"color" : BLUE,
|
|
57
|
+
"fill_opacity" : 0.75
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
label.scale(3)
|
|
61
|
+
self.add(label)
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
label: str | Tex | MathTex | Text,
|
|
67
|
+
label_config: dict[str, Any] | None = None,
|
|
68
|
+
box_config: dict[str, Any] | None = None,
|
|
69
|
+
frame_config: dict[str, Any] | None = None,
|
|
70
|
+
**kwargs: Any,
|
|
71
|
+
) -> None:
|
|
72
|
+
super().__init__(**kwargs)
|
|
73
|
+
|
|
74
|
+
# Setup Defaults
|
|
75
|
+
default_label_config: dict[str, Any] = {
|
|
76
|
+
"color": WHITE,
|
|
77
|
+
"font_size": DEFAULT_FONT_SIZE,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
default_box_config: dict[str, Any] = {
|
|
81
|
+
"color": None,
|
|
82
|
+
"buff": 0.05,
|
|
83
|
+
"fill_opacity": 1,
|
|
84
|
+
"stroke_width": 0.5,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
default_frame_config: dict[str, Any] = {
|
|
88
|
+
"color": WHITE,
|
|
89
|
+
"buff": 0.05,
|
|
90
|
+
"stroke_width": 0.5,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Merge Defaults
|
|
94
|
+
label_config = default_label_config | (label_config or {})
|
|
95
|
+
box_config = default_box_config | (box_config or {})
|
|
96
|
+
frame_config = default_frame_config | (frame_config or {})
|
|
97
|
+
|
|
98
|
+
# Determine the type of label and instantiate the appropriate object
|
|
99
|
+
self.rendered_label: MathTex | Tex | Text
|
|
100
|
+
if isinstance(label, str):
|
|
101
|
+
self.rendered_label = MathTex(label, **label_config)
|
|
102
|
+
elif isinstance(label, (MathTex, Tex, Text)):
|
|
103
|
+
self.rendered_label = label
|
|
104
|
+
else:
|
|
105
|
+
raise TypeError("Unsupported label type. Must be MathTex, Tex, or Text.")
|
|
106
|
+
|
|
107
|
+
# Add a background box
|
|
108
|
+
self.background_rect = BackgroundRectangle(self.rendered_label, **box_config)
|
|
109
|
+
|
|
110
|
+
# Add a frame around the label
|
|
111
|
+
self.frame = SurroundingRectangle(self.rendered_label, **frame_config)
|
|
112
|
+
|
|
113
|
+
# Add components to the VGroup
|
|
114
|
+
self.add(self.background_rect, self.rendered_label, self.frame)
|
|
16
115
|
|
|
17
116
|
|
|
18
117
|
class LabeledLine(Line):
|
|
@@ -20,42 +119,38 @@ class LabeledLine(Line):
|
|
|
20
119
|
|
|
21
120
|
Parameters
|
|
22
121
|
----------
|
|
23
|
-
label
|
|
122
|
+
label
|
|
24
123
|
Label that will be displayed on the line.
|
|
25
|
-
label_position
|
|
124
|
+
label_position
|
|
26
125
|
A ratio in the range [0-1] to indicate the position of the label with respect to the length of the line. Default value is 0.5.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.. seealso::
|
|
39
|
-
:class:`LabeledArrow`
|
|
126
|
+
label_config
|
|
127
|
+
A dictionary containing the configuration for the label.
|
|
128
|
+
This is only applied if ``label`` is of type ``str``.
|
|
129
|
+
box_config
|
|
130
|
+
A dictionary containing the configuration for the background box.
|
|
131
|
+
frame_config
|
|
132
|
+
A dictionary containing the configuration for the frame.
|
|
133
|
+
|
|
134
|
+
.. seealso::
|
|
135
|
+
:class:`LabeledArrow`
|
|
40
136
|
|
|
41
137
|
Examples
|
|
42
138
|
--------
|
|
43
139
|
.. manim:: LabeledLineExample
|
|
44
140
|
:save_last_frame:
|
|
141
|
+
:quality: high
|
|
45
142
|
|
|
46
143
|
class LabeledLineExample(Scene):
|
|
47
144
|
def construct(self):
|
|
48
145
|
line = LabeledLine(
|
|
49
146
|
label = '0.5',
|
|
50
147
|
label_position = 0.8,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
148
|
+
label_config = {
|
|
149
|
+
"font_size" : 20
|
|
150
|
+
},
|
|
55
151
|
start=LEFT+DOWN,
|
|
56
152
|
end=RIGHT+UP)
|
|
57
153
|
|
|
58
|
-
|
|
59
154
|
line.set_length(line.get_length() * 2)
|
|
60
155
|
self.add(line)
|
|
61
156
|
"""
|
|
@@ -64,50 +159,29 @@ class LabeledLine(Line):
|
|
|
64
159
|
self,
|
|
65
160
|
label: str | Tex | MathTex | Text,
|
|
66
161
|
label_position: float = 0.5,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*args,
|
|
73
|
-
**kwargs,
|
|
162
|
+
label_config: dict[str, Any] | None = None,
|
|
163
|
+
box_config: dict[str, Any] | None = None,
|
|
164
|
+
frame_config: dict[str, Any] | None = None,
|
|
165
|
+
*args: Any,
|
|
166
|
+
**kwargs: Any,
|
|
74
167
|
) -> None:
|
|
75
|
-
label_color = ManimColor(label_color)
|
|
76
|
-
frame_fill_color = ManimColor(frame_fill_color)
|
|
77
|
-
if isinstance(label, str):
|
|
78
|
-
from manim import MathTex
|
|
79
|
-
|
|
80
|
-
rendered_label = MathTex(label, color=label_color, font_size=font_size)
|
|
81
|
-
else:
|
|
82
|
-
rendered_label = label
|
|
83
|
-
|
|
84
168
|
super().__init__(*args, **kwargs)
|
|
85
169
|
|
|
86
|
-
#
|
|
170
|
+
# Create Label
|
|
171
|
+
self.label = Label(
|
|
172
|
+
label=label,
|
|
173
|
+
label_config=label_config,
|
|
174
|
+
box_config=box_config,
|
|
175
|
+
frame_config=frame_config,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# Compute Label Position
|
|
87
179
|
line_start, line_end = self.get_start_and_end()
|
|
88
180
|
new_vec = (line_end - line_start) * label_position
|
|
89
181
|
label_coords = line_start + new_vec
|
|
90
182
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
box = BackgroundRectangle(
|
|
95
|
-
rendered_label,
|
|
96
|
-
buff=0.05,
|
|
97
|
-
color=frame_fill_color,
|
|
98
|
-
fill_opacity=frame_fill_opacity,
|
|
99
|
-
stroke_width=0.5,
|
|
100
|
-
)
|
|
101
|
-
self.add(box)
|
|
102
|
-
|
|
103
|
-
if label_frame:
|
|
104
|
-
box_frame = SurroundingRectangle(
|
|
105
|
-
rendered_label, buff=0.05, color=label_color, stroke_width=0.5
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
self.add(box_frame)
|
|
109
|
-
|
|
110
|
-
self.add(rendered_label)
|
|
183
|
+
self.label.move_to(label_coords)
|
|
184
|
+
self.add(self.label)
|
|
111
185
|
|
|
112
186
|
|
|
113
187
|
class LabeledArrow(LabeledLine, Arrow):
|
|
@@ -116,29 +190,26 @@ class LabeledArrow(LabeledLine, Arrow):
|
|
|
116
190
|
|
|
117
191
|
Parameters
|
|
118
192
|
----------
|
|
119
|
-
label
|
|
120
|
-
Label that will be displayed on the
|
|
121
|
-
label_position
|
|
193
|
+
label
|
|
194
|
+
Label that will be displayed on the Arrow.
|
|
195
|
+
label_position
|
|
122
196
|
A ratio in the range [0-1] to indicate the position of the label with respect to the length of the line. Default value is 0.5.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Background color to fill the label box. If no value is provided, the background color of the canvas will be used.
|
|
131
|
-
frame_fill_opacity : float | optional
|
|
132
|
-
Determine the opacity of the label box by passing a value in the range [0-1], where 0 indicates complete transparency and 1 means full opacity.
|
|
197
|
+
label_config
|
|
198
|
+
A dictionary containing the configuration for the label.
|
|
199
|
+
This is only applied if ``label`` is of type ``str``.
|
|
200
|
+
box_config
|
|
201
|
+
A dictionary containing the configuration for the background box.
|
|
202
|
+
frame_config
|
|
203
|
+
A dictionary containing the configuration for the frame.
|
|
133
204
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
:class:`LabeledLine`
|
|
205
|
+
.. seealso::
|
|
206
|
+
:class:`LabeledLine`
|
|
137
207
|
|
|
138
208
|
Examples
|
|
139
209
|
--------
|
|
140
210
|
.. manim:: LabeledArrowExample
|
|
141
211
|
:save_last_frame:
|
|
212
|
+
:quality: high
|
|
142
213
|
|
|
143
214
|
class LabeledArrowExample(Scene):
|
|
144
215
|
def construct(self):
|
|
@@ -149,7 +220,159 @@ class LabeledArrow(LabeledLine, Arrow):
|
|
|
149
220
|
|
|
150
221
|
def __init__(
|
|
151
222
|
self,
|
|
152
|
-
*args,
|
|
153
|
-
**kwargs,
|
|
223
|
+
*args: Any,
|
|
224
|
+
**kwargs: Any,
|
|
154
225
|
) -> None:
|
|
155
226
|
super().__init__(*args, **kwargs)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class LabeledPolygram(Polygram):
|
|
230
|
+
"""Constructs a polygram containing a label box at its pole of inaccessibility.
|
|
231
|
+
|
|
232
|
+
Parameters
|
|
233
|
+
----------
|
|
234
|
+
vertex_groups
|
|
235
|
+
Vertices passed to the :class:`~.Polygram` constructor.
|
|
236
|
+
label
|
|
237
|
+
Label that will be displayed on the Polygram.
|
|
238
|
+
precision
|
|
239
|
+
The precision used by the PolyLabel algorithm.
|
|
240
|
+
label_config
|
|
241
|
+
A dictionary containing the configuration for the label.
|
|
242
|
+
This is only applied if ``label`` is of type ``str``.
|
|
243
|
+
box_config
|
|
244
|
+
A dictionary containing the configuration for the background box.
|
|
245
|
+
frame_config
|
|
246
|
+
A dictionary containing the configuration for the frame.
|
|
247
|
+
|
|
248
|
+
.. note::
|
|
249
|
+
The PolyLabel Algorithm expects each vertex group to form a closed ring.
|
|
250
|
+
If the input is open, :class:`LabeledPolygram` will attempt to close it.
|
|
251
|
+
This may cause the polygon to intersect itself leading to unexpected results.
|
|
252
|
+
|
|
253
|
+
.. tip::
|
|
254
|
+
Make sure the precision corresponds to the scale of your inputs!
|
|
255
|
+
For instance, if the bounding box of your polygon stretches from 0 to 10,000, a precision of 1.0 or 10.0 should be sufficient.
|
|
256
|
+
|
|
257
|
+
Examples
|
|
258
|
+
--------
|
|
259
|
+
.. manim:: LabeledPolygramExample
|
|
260
|
+
:save_last_frame:
|
|
261
|
+
:quality: high
|
|
262
|
+
|
|
263
|
+
class LabeledPolygramExample(Scene):
|
|
264
|
+
def construct(self):
|
|
265
|
+
# Define Rings
|
|
266
|
+
ring1 = [
|
|
267
|
+
[-3.8, -2.4, 0], [-2.4, -2.5, 0], [-1.3, -1.6, 0], [-0.2, -1.7, 0],
|
|
268
|
+
[1.7, -2.5, 0], [2.9, -2.6, 0], [3.5, -1.5, 0], [4.9, -1.4, 0],
|
|
269
|
+
[4.5, 0.2, 0], [4.7, 1.6, 0], [3.5, 2.4, 0], [1.1, 2.5, 0],
|
|
270
|
+
[-0.1, 0.9, 0], [-1.2, 0.5, 0], [-1.6, 0.7, 0], [-1.4, 1.9, 0],
|
|
271
|
+
[-2.6, 2.6, 0], [-4.4, 1.2, 0], [-4.9, -0.8, 0], [-3.8, -2.4, 0]
|
|
272
|
+
]
|
|
273
|
+
ring2 = [
|
|
274
|
+
[0.2, -1.2, 0], [0.9, -1.2, 0], [1.4, -2.0, 0], [2.1, -1.6, 0],
|
|
275
|
+
[2.2, -0.5, 0], [1.4, 0.0, 0], [0.4, -0.2, 0], [0.2, -1.2, 0]
|
|
276
|
+
]
|
|
277
|
+
ring3 = [[-2.7, 1.4, 0], [-2.3, 1.7, 0], [-2.8, 1.9, 0], [-2.7, 1.4, 0]]
|
|
278
|
+
|
|
279
|
+
# Create Polygons (for reference)
|
|
280
|
+
p1 = Polygon(*ring1, fill_opacity=0.75)
|
|
281
|
+
p2 = Polygon(*ring2, fill_color=BLACK, fill_opacity=1)
|
|
282
|
+
p3 = Polygon(*ring3, fill_color=BLACK, fill_opacity=1)
|
|
283
|
+
|
|
284
|
+
# Create Labeled Polygram
|
|
285
|
+
polygram = LabeledPolygram(
|
|
286
|
+
*[ring1, ring2, ring3],
|
|
287
|
+
label=Text('Pole', font='sans-serif'),
|
|
288
|
+
precision=0.01,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# Display Circle (for reference)
|
|
292
|
+
circle = Circle(radius=polygram.radius, color=WHITE).move_to(polygram.pole)
|
|
293
|
+
|
|
294
|
+
self.add(p1, p2, p3)
|
|
295
|
+
self.add(polygram)
|
|
296
|
+
self.add(circle)
|
|
297
|
+
|
|
298
|
+
.. manim:: LabeledCountryExample
|
|
299
|
+
:save_last_frame:
|
|
300
|
+
:quality: high
|
|
301
|
+
|
|
302
|
+
import requests
|
|
303
|
+
import json
|
|
304
|
+
|
|
305
|
+
class LabeledCountryExample(Scene):
|
|
306
|
+
def construct(self):
|
|
307
|
+
# Fetch JSON data and process arcs
|
|
308
|
+
data = requests.get('https://cdn.jsdelivr.net/npm/us-atlas@3/nation-10m.json').json()
|
|
309
|
+
arcs, transform = data['arcs'], data['transform']
|
|
310
|
+
sarcs = [np.cumsum(arc, axis=0) * transform['scale'] + transform['translate'] for arc in arcs]
|
|
311
|
+
ssarcs = sorted(sarcs, key=len, reverse=True)[:1]
|
|
312
|
+
|
|
313
|
+
# Compute Bounding Box
|
|
314
|
+
points = np.concatenate(ssarcs)
|
|
315
|
+
mins, maxs = np.min(points, axis=0), np.max(points, axis=0)
|
|
316
|
+
|
|
317
|
+
# Build Axes
|
|
318
|
+
ax = Axes(
|
|
319
|
+
x_range=[mins[0], maxs[0], maxs[0] - mins[0]], x_length=10,
|
|
320
|
+
y_range=[mins[1], maxs[1], maxs[1] - mins[1]], y_length=7,
|
|
321
|
+
tips=False
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Adjust Coordinates
|
|
325
|
+
array = [[ax.c2p(*point) for point in sarc] for sarc in ssarcs]
|
|
326
|
+
|
|
327
|
+
# Add Polygram
|
|
328
|
+
polygram = LabeledPolygram(
|
|
329
|
+
*array,
|
|
330
|
+
label=Text('USA', font='sans-serif'),
|
|
331
|
+
precision=0.01,
|
|
332
|
+
fill_color=BLUE,
|
|
333
|
+
stroke_width=0,
|
|
334
|
+
fill_opacity=0.75
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Display Circle (for reference)
|
|
338
|
+
circle = Circle(radius=polygram.radius, color=WHITE).move_to(polygram.pole)
|
|
339
|
+
|
|
340
|
+
self.add(ax)
|
|
341
|
+
self.add(polygram)
|
|
342
|
+
self.add(circle)
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
def __init__(
|
|
346
|
+
self,
|
|
347
|
+
*vertex_groups: Point3DLike_Array,
|
|
348
|
+
label: str | Tex | MathTex | Text,
|
|
349
|
+
precision: float = 0.01,
|
|
350
|
+
label_config: dict[str, Any] | None = None,
|
|
351
|
+
box_config: dict[str, Any] | None = None,
|
|
352
|
+
frame_config: dict[str, Any] | None = None,
|
|
353
|
+
**kwargs: Any,
|
|
354
|
+
) -> None:
|
|
355
|
+
# Initialize the Polygram with the vertex groups
|
|
356
|
+
super().__init__(*vertex_groups, **kwargs)
|
|
357
|
+
|
|
358
|
+
# Create Label
|
|
359
|
+
self.label = Label(
|
|
360
|
+
label=label,
|
|
361
|
+
label_config=label_config,
|
|
362
|
+
box_config=box_config,
|
|
363
|
+
frame_config=frame_config,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Close Vertex Groups
|
|
367
|
+
rings = [
|
|
368
|
+
group if np.array_equal(group[0], group[-1]) else list(group) + [group[0]]
|
|
369
|
+
for group in vertex_groups
|
|
370
|
+
]
|
|
371
|
+
|
|
372
|
+
# Compute the Pole of Inaccessibility
|
|
373
|
+
cell = polylabel(rings, precision=precision)
|
|
374
|
+
self.pole, self.radius = np.pad(cell.c, (0, 1), "constant"), cell.d
|
|
375
|
+
|
|
376
|
+
# Position the label at the pole
|
|
377
|
+
self.label.move_to(self.pole)
|
|
378
|
+
self.add(self.label)
|