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.
Files changed (163) hide show
  1. manim/__init__.py +11 -6
  2. manim/__main__.py +62 -19
  3. manim/_config/__init__.py +10 -9
  4. manim/_config/cli_colors.py +26 -9
  5. manim/_config/default.cfg +1 -3
  6. manim/_config/logger_utils.py +23 -13
  7. manim/_config/utils.py +662 -468
  8. manim/animation/animation.py +164 -18
  9. manim/animation/changing.py +34 -23
  10. manim/animation/composition.py +265 -67
  11. manim/animation/creation.py +208 -26
  12. manim/animation/fading.py +16 -18
  13. manim/animation/growing.py +35 -15
  14. manim/animation/indication.py +150 -76
  15. manim/animation/movement.py +56 -22
  16. manim/animation/numbers.py +64 -6
  17. manim/animation/rotation.py +78 -7
  18. manim/animation/specialized.py +6 -7
  19. manim/animation/speedmodifier.py +13 -10
  20. manim/animation/transform.py +14 -11
  21. manim/animation/transform_matching_parts.py +3 -4
  22. manim/animation/updaters/mobject_update_utils.py +152 -30
  23. manim/animation/updaters/update.py +10 -7
  24. manim/camera/camera.py +182 -118
  25. manim/camera/mapping_camera.py +34 -3
  26. manim/camera/moving_camera.py +95 -74
  27. manim/camera/multi_camera.py +23 -15
  28. manim/camera/three_d_camera.py +70 -52
  29. manim/cli/__init__.py +17 -0
  30. manim/cli/cfg/group.py +76 -44
  31. manim/cli/checkhealth/checks.py +192 -0
  32. manim/cli/checkhealth/commands.py +90 -0
  33. manim/cli/default_group.py +158 -25
  34. manim/cli/init/commands.py +33 -25
  35. manim/cli/plugins/commands.py +16 -3
  36. manim/cli/render/commands.py +72 -60
  37. manim/cli/render/ease_of_access_options.py +4 -3
  38. manim/cli/render/global_options.py +59 -17
  39. manim/cli/render/output_options.py +6 -5
  40. manim/cli/render/render_options.py +98 -33
  41. manim/constants.py +109 -59
  42. manim/data_structures.py +31 -0
  43. manim/mobject/frame.py +8 -5
  44. manim/mobject/geometry/__init__.py +1 -0
  45. manim/mobject/geometry/arc.py +277 -135
  46. manim/mobject/geometry/boolean_ops.py +32 -31
  47. manim/mobject/geometry/labeled.py +376 -0
  48. manim/mobject/geometry/line.py +192 -87
  49. manim/mobject/geometry/polygram.py +224 -58
  50. manim/mobject/geometry/shape_matchers.py +61 -25
  51. manim/mobject/geometry/tips.py +122 -48
  52. manim/mobject/graph.py +1027 -419
  53. manim/mobject/graphing/coordinate_systems.py +533 -278
  54. manim/mobject/graphing/functions.py +53 -32
  55. manim/mobject/graphing/number_line.py +123 -65
  56. manim/mobject/graphing/probability.py +88 -62
  57. manim/mobject/graphing/scale.py +33 -19
  58. manim/mobject/logo.py +118 -28
  59. manim/mobject/matrix.py +87 -83
  60. manim/mobject/mobject.py +912 -442
  61. manim/mobject/opengl/dot_cloud.py +16 -5
  62. manim/mobject/opengl/opengl_compatibility.py +4 -2
  63. manim/mobject/opengl/opengl_geometry.py +254 -153
  64. manim/mobject/opengl/opengl_image_mobject.py +3 -1
  65. manim/mobject/opengl/opengl_mobject.py +779 -482
  66. manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
  67. manim/mobject/opengl/opengl_surface.py +14 -92
  68. manim/mobject/opengl/opengl_three_dimensions.py +12 -8
  69. manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
  70. manim/mobject/svg/brace.py +173 -41
  71. manim/mobject/svg/svg_mobject.py +139 -53
  72. manim/mobject/table.py +61 -68
  73. manim/mobject/text/code_mobject.py +193 -539
  74. manim/mobject/text/numbers.py +81 -34
  75. manim/mobject/text/tex_mobject.py +130 -78
  76. manim/mobject/text/text_mobject.py +288 -164
  77. manim/mobject/three_d/polyhedra.py +111 -13
  78. manim/mobject/three_d/three_d_utils.py +17 -8
  79. manim/mobject/three_d/three_dimensions.py +239 -106
  80. manim/mobject/types/image_mobject.py +50 -30
  81. manim/mobject/types/point_cloud_mobject.py +120 -75
  82. manim/mobject/types/vectorized_mobject.py +841 -408
  83. manim/mobject/value_tracker.py +105 -38
  84. manim/mobject/vector_field.py +50 -31
  85. manim/opengl/__init__.py +3 -3
  86. manim/plugins/__init__.py +14 -1
  87. manim/plugins/plugins_flags.py +10 -14
  88. manim/renderer/cairo_renderer.py +65 -50
  89. manim/renderer/opengl_renderer.py +89 -69
  90. manim/renderer/opengl_renderer_window.py +39 -18
  91. manim/renderer/shader.py +123 -87
  92. manim/renderer/shader_wrapper.py +44 -28
  93. manim/renderer/vectorized_mobject_rendering.py +38 -10
  94. manim/scene/moving_camera_scene.py +32 -3
  95. manim/scene/scene.py +507 -242
  96. manim/scene/scene_file_writer.py +371 -220
  97. manim/scene/section.py +20 -16
  98. manim/scene/three_d_scene.py +14 -22
  99. manim/scene/vector_space_scene.py +223 -129
  100. manim/scene/zoomed_scene.py +46 -41
  101. manim/typing.py +990 -0
  102. manim/utils/bezier.py +1823 -371
  103. manim/utils/caching.py +12 -5
  104. manim/utils/color/AS2700.py +236 -0
  105. manim/utils/color/BS381.py +318 -0
  106. manim/utils/color/DVIPSNAMES.py +96 -0
  107. manim/utils/color/SVGNAMES.py +179 -0
  108. manim/utils/color/X11.py +533 -0
  109. manim/utils/color/XKCD.py +952 -0
  110. manim/utils/color/__init__.py +61 -0
  111. manim/utils/color/core.py +1667 -0
  112. manim/utils/color/manim_colors.py +218 -0
  113. manim/utils/commands.py +48 -20
  114. manim/utils/config_ops.py +39 -19
  115. manim/utils/debug.py +8 -7
  116. manim/utils/deprecation.py +86 -39
  117. manim/utils/docbuild/__init__.py +17 -0
  118. manim/utils/docbuild/autoaliasattr_directive.py +236 -0
  119. manim/utils/docbuild/autocolor_directive.py +99 -0
  120. manim/utils/docbuild/manim_directive.py +94 -41
  121. manim/utils/docbuild/module_parsing.py +245 -0
  122. manim/utils/exceptions.py +6 -0
  123. manim/utils/family.py +5 -3
  124. manim/utils/family_ops.py +17 -4
  125. manim/utils/file_ops.py +27 -17
  126. manim/utils/hashing.py +55 -45
  127. manim/utils/images.py +13 -7
  128. manim/utils/ipython_magic.py +13 -7
  129. manim/utils/iterables.py +163 -120
  130. manim/utils/module_ops.py +66 -24
  131. manim/utils/opengl.py +77 -24
  132. manim/utils/parameter_parsing.py +32 -0
  133. manim/utils/paths.py +30 -33
  134. manim/utils/polylabel.py +235 -0
  135. manim/utils/qhull.py +218 -0
  136. manim/utils/rate_functions.py +98 -32
  137. manim/utils/simple_functions.py +25 -33
  138. manim/utils/sounds.py +7 -1
  139. manim/utils/space_ops.py +188 -115
  140. manim/utils/testing/__init__.py +17 -0
  141. manim/utils/testing/_frames_testers.py +13 -8
  142. manim/utils/testing/_show_diff.py +5 -3
  143. manim/utils/testing/_test_class_makers.py +34 -18
  144. manim/utils/testing/frames_comparison.py +37 -19
  145. manim/utils/tex.py +130 -198
  146. manim/utils/tex_file_writing.py +77 -47
  147. manim/utils/tex_templates.py +2 -1
  148. manim/utils/unit.py +6 -5
  149. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
  150. manim-0.19.1.dist-info/RECORD +220 -0
  151. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
  152. manim-0.19.1.dist-info/entry_points.txt +3 -0
  153. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
  154. manim/cli/new/group.py +0 -189
  155. manim/communitycolors.py +0 -9
  156. manim/gui/__init__.py +0 -0
  157. manim/gui/gui.py +0 -82
  158. manim/plugins/import_plugins.py +0 -43
  159. manim/utils/color.py +0 -552
  160. manim-0.17.0.dist-info/RECORD +0 -206
  161. manim-0.17.0.dist-info/entry_points.txt +0 -4
  162. /manim/cli/{new → checkhealth}/__init__.py +0 -0
  163. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
@@ -2,30 +2,32 @@ from __future__ import annotations
2
2
 
3
3
  import itertools as it
4
4
  import operator as op
5
+ from collections.abc import Callable, Iterable, Sequence
5
6
  from functools import reduce, wraps
6
- from typing import Callable, Iterable, Optional, Sequence
7
+ from typing import Any
7
8
 
8
9
  import moderngl
9
10
  import numpy as np
10
- from colour import Color
11
+ from typing_extensions import Self
11
12
 
12
13
  from manim import config
13
14
  from manim.constants import *
14
15
  from manim.mobject.opengl.opengl_mobject import OpenGLMobject, OpenGLPoint
15
16
  from manim.renderer.shader_wrapper import ShaderWrapper
17
+ from manim.typing import Point3D, Point3DLike, Point3DLike_Array
16
18
  from manim.utils.bezier import (
17
19
  bezier,
20
+ bezier_remap,
18
21
  get_quadratic_approximation_of_cubic,
19
22
  get_smooth_cubic_bezier_handle_points,
20
23
  integer_interpolate,
21
24
  interpolate,
22
- partial_quadratic_bezier_points,
25
+ partial_bezier_points,
23
26
  proportions_along_bezier_curve_for_point,
24
- quadratic_bezier_remap,
25
27
  )
26
- from manim.utils.color import *
28
+ from manim.utils.color import BLACK, WHITE, ManimColor, ParsableManimColor
27
29
  from manim.utils.config_ops import _Data
28
- from manim.utils.iterables import listify, make_even, resize_with_interpolation
30
+ from manim.utils.iterables import make_even, resize_with_interpolation, tuplify
29
31
  from manim.utils.space_ops import (
30
32
  angle_between_vectors,
31
33
  cross2d,
@@ -35,6 +37,15 @@ from manim.utils.space_ops import (
35
37
  z_to_vector,
36
38
  )
37
39
 
40
+ __all__ = [
41
+ "triggers_refreshed_triangulation",
42
+ "OpenGLVMobject",
43
+ "OpenGLVGroup",
44
+ "OpenGLVectorizedPoint",
45
+ "OpenGLCurvesAsSubmobjects",
46
+ "OpenGLDashedVMobject",
47
+ ]
48
+
38
49
 
39
50
  def triggers_refreshed_triangulation(func):
40
51
  @wraps(func)
@@ -74,6 +85,9 @@ class OpenGLVMobject(OpenGLMobject):
74
85
  stroke_shader_folder = "quadratic_bezier_stroke"
75
86
  fill_shader_folder = "quadratic_bezier_fill"
76
87
 
88
+ # TODO: although these are called "rgba" in singular, they are used as
89
+ # FloatRGBA_Arrays and should be called instead "rgbas" in plural for consistency.
90
+ # The same should probably apply for "stroke_width" and "unit_normal".
77
91
  fill_rgba = _Data()
78
92
  stroke_rgba = _Data()
79
93
  stroke_width = _Data()
@@ -81,9 +95,9 @@ class OpenGLVMobject(OpenGLMobject):
81
95
 
82
96
  def __init__(
83
97
  self,
84
- fill_color: Color | None = None,
98
+ fill_color: ParsableManimColor | None = None,
85
99
  fill_opacity: float = 0.0,
86
- stroke_color: Color | None = None,
100
+ stroke_color: ParsableManimColor | None = None,
87
101
  stroke_opacity: float = 1.0,
88
102
  stroke_width: float = DEFAULT_STROKE_WIDTH,
89
103
  draw_stroke_behind_fill: bool = False,
@@ -137,13 +151,6 @@ class OpenGLVMobject(OpenGLMobject):
137
151
  self.needs_new_triangulation = True
138
152
  self.triangulation = np.zeros(0, dtype="i4")
139
153
  self.orientation = 1
140
- super().__init__(**kwargs)
141
- self.refresh_unit_normal()
142
-
143
- if fill_color:
144
- self.fill_color = Color(fill_color)
145
- if stroke_color:
146
- self.stroke_color = Color(stroke_color)
147
154
 
148
155
  self.fill_data = None
149
156
  self.stroke_data = None
@@ -151,6 +158,17 @@ class OpenGLVMobject(OpenGLMobject):
151
158
  self.stroke_shader_wrapper = None
152
159
  self.init_shader_data()
153
160
 
161
+ super().__init__(**kwargs)
162
+ self.refresh_unit_normal()
163
+
164
+ if fill_color is not None:
165
+ self.fill_color = ManimColor.parse(fill_color)
166
+ if stroke_color is not None:
167
+ self.stroke_color = ManimColor.parse(stroke_color)
168
+
169
+ def _assert_valid_submobjects(self, submobjects: Iterable[OpenGLVMobject]) -> Self:
170
+ return self._assert_valid_submobjects_internal(submobjects, OpenGLVMobject)
171
+
154
172
  def get_group_class(self):
155
173
  return OpenGLVGroup
156
174
 
@@ -158,6 +176,15 @@ class OpenGLVMobject(OpenGLMobject):
158
176
  def get_mobject_type_class():
159
177
  return OpenGLVMobject
160
178
 
179
+ @property
180
+ def submobjects(self) -> Sequence[OpenGLVMobject]:
181
+ return self._submobjects if hasattr(self, "_submobjects") else []
182
+
183
+ @submobjects.setter
184
+ def submobjects(self, submobject_list: Iterable[OpenGLVMobject]) -> None:
185
+ self.remove(*self.submobjects)
186
+ self.add(*submobject_list)
187
+
161
188
  def init_data(self):
162
189
  super().init_data()
163
190
  self.data.pop("rgbas")
@@ -184,7 +211,7 @@ class OpenGLVMobject(OpenGLMobject):
184
211
 
185
212
  def set_fill(
186
213
  self,
187
- color: Color | None = None,
214
+ color: ParsableManimColor | None = None,
188
215
  opacity: float | None = None,
189
216
  recurse: bool = True,
190
217
  ) -> OpenGLVMobject:
@@ -256,7 +283,10 @@ class OpenGLVMobject(OpenGLMobject):
256
283
 
257
284
  if width is not None:
258
285
  for mob in self.get_family(recurse):
259
- mob.stroke_width = np.array([[width] for width in listify(width)])
286
+ if isinstance(width, np.ndarray):
287
+ mob.stroke_width = width
288
+ else:
289
+ mob.stroke_width = np.array([[width] for width in tuplify(width)])
260
290
 
261
291
  if background is not None:
262
292
  for mob in self.get_family(recurse):
@@ -311,6 +341,7 @@ class OpenGLVMobject(OpenGLMobject):
311
341
  vmobject_style = vmobject.get_style()
312
342
  if config.renderer == RendererType.OPENGL:
313
343
  vmobject_style["stroke_width"] = vmobject_style["stroke_width"][0][0]
344
+ vmobject_style["fill_opacity"] = self.get_fill_opacity()
314
345
  self.set_style(**vmobject_style, recurse=False)
315
346
  if recurse:
316
347
  # Does its best to match up submobject lists, and
@@ -350,14 +381,15 @@ class OpenGLVMobject(OpenGLMobject):
350
381
  super().fade(darkness, recurse)
351
382
  return self
352
383
 
384
+ # Todo im not quite sure why we are doing this
353
385
  def get_fill_colors(self):
354
- return [Color(rgb_to_hex(rgba[:3])) for rgba in self.fill_rgba]
386
+ return [ManimColor.from_rgb(rgba[:3]) for rgba in self.fill_rgba]
355
387
 
356
388
  def get_fill_opacities(self):
357
389
  return self.fill_rgba[:, 3]
358
390
 
359
391
  def get_stroke_colors(self):
360
- return [Color(rgb_to_hex(rgba[:3])) for rgba in self.stroke_rgba]
392
+ return [ManimColor.from_rgb(rgba[:3]) for rgba in self.stroke_rgba]
361
393
 
362
394
  def get_stroke_opacities(self):
363
395
  return self.stroke_rgba[:, 3]
@@ -391,7 +423,7 @@ class OpenGLVMobject(OpenGLMobject):
391
423
  return self.get_stroke_opacities()[0]
392
424
 
393
425
  def get_color(self):
394
- if self.has_stroke():
426
+ if not self.has_fill():
395
427
  return self.get_stroke_color()
396
428
  return self.get_fill_color()
397
429
 
@@ -447,7 +479,13 @@ class OpenGLVMobject(OpenGLMobject):
447
479
  self.append_points([point])
448
480
  return self
449
481
 
450
- def add_cubic_bezier_curve(self, anchor1, handle1, handle2, anchor2):
482
+ def add_cubic_bezier_curve(
483
+ self,
484
+ anchor1: Point3DLike,
485
+ handle1: Point3DLike,
486
+ handle2: Point3DLike,
487
+ anchor2: Point3DLike,
488
+ ):
451
489
  new_points = get_quadratic_approximation_of_cubic(
452
490
  anchor1,
453
491
  handle1,
@@ -457,9 +495,7 @@ class OpenGLVMobject(OpenGLMobject):
457
495
  self.append_points(new_points)
458
496
 
459
497
  def add_cubic_bezier_curve_to(self, handle1, handle2, anchor):
460
- """
461
- Add cubic bezier curve to the path.
462
- """
498
+ """Add cubic bezier curve to the path."""
463
499
  self.throw_error_if_no_points()
464
500
  quadratic_approx = get_quadratic_approximation_of_cubic(
465
501
  self.get_last_point(),
@@ -544,7 +580,7 @@ class OpenGLVMobject(OpenGLMobject):
544
580
  alphas = np.linspace(0, 1, n + 1)
545
581
  new_points.extend(
546
582
  [
547
- partial_quadratic_bezier_points(tup, a1, a2)
583
+ partial_bezier_points(tup, a1, a2)
548
584
  for a1, a2 in zip(alphas, alphas[1:])
549
585
  ],
550
586
  )
@@ -558,7 +594,7 @@ class OpenGLVMobject(OpenGLMobject):
558
594
  self.add_line_to(point)
559
595
  return points
560
596
 
561
- def set_points_as_corners(self, points: Iterable[float]) -> OpenGLVMobject:
597
+ def set_points_as_corners(self, points: Point3DLike_Array) -> OpenGLVMobject:
562
598
  """Given an array of points, set them as corner of the vmobject.
563
599
 
564
600
  To achieve that, this algorithm sets handles aligned with the anchors such that the resultant bezier curve will be the segment
@@ -581,7 +617,9 @@ class OpenGLVMobject(OpenGLMobject):
581
617
  )
582
618
  return self
583
619
 
584
- def set_points_smoothly(self, points, true_smooth=False):
620
+ def set_points_smoothly(
621
+ self, points: Point3DLike_Array, true_smooth: bool = False
622
+ ) -> Self:
585
623
  self.set_points_as_corners(points)
586
624
  self.make_smooth()
587
625
  return self
@@ -802,7 +840,6 @@ class OpenGLVMobject(OpenGLMobject):
802
840
  length : :class:`float`
803
841
  The length of the nth curve.
804
842
  """
805
-
806
843
  if sample_points is None:
807
844
  sample_points = 10
808
845
 
@@ -842,7 +879,6 @@ class OpenGLVMobject(OpenGLMobject):
842
879
  length : :class:`float`
843
880
  The length of the nth curve.
844
881
  """
845
-
846
882
  _, length = self.get_nth_curve_function_with_length(n, sample_points)
847
883
 
848
884
  return length
@@ -857,7 +893,6 @@ class OpenGLVMobject(OpenGLMobject):
857
893
  Iterable[Callable[[float], np.ndarray]]
858
894
  The functions for the curves.
859
895
  """
860
-
861
896
  num_curves = self.get_num_curves()
862
897
 
863
898
  for n in range(num_curves):
@@ -907,13 +942,12 @@ class OpenGLVMobject(OpenGLMobject):
907
942
  Iterable[Tuple[Callable[[float], np.ndarray], float]]
908
943
  The functions and lengths of the curves.
909
944
  """
910
-
911
945
  num_curves = self.get_num_curves()
912
946
 
913
947
  for n in range(num_curves):
914
948
  yield self.get_nth_curve_function_with_length(n, **kwargs)
915
949
 
916
- def point_from_proportion(self, alpha: float) -> np.ndarray:
950
+ def point_from_proportion(self, alpha: float) -> Point3D:
917
951
  """Gets the point at a proportion along the path of the :class:`OpenGLVMobject`.
918
952
 
919
953
  Parameters
@@ -923,7 +957,7 @@ class OpenGLVMobject(OpenGLMobject):
923
957
 
924
958
  Returns
925
959
  -------
926
- :class:`numpy.ndarray`
960
+ :class:`Point3D`
927
961
  The point on the :class:`OpenGLVMobject`.
928
962
 
929
963
  Raises
@@ -933,7 +967,6 @@ class OpenGLVMobject(OpenGLMobject):
933
967
  :exc:`Exception`
934
968
  If the :class:`OpenGLVMobject` has no points.
935
969
  """
936
-
937
970
  if alpha < 0 or alpha > 1:
938
971
  raise ValueError(f"Alpha {alpha} not between 0 and 1.")
939
972
 
@@ -943,7 +976,9 @@ class OpenGLVMobject(OpenGLMobject):
943
976
 
944
977
  curves_and_lengths = tuple(self.get_curve_functions_with_lengths())
945
978
 
946
- target_length = alpha * np.sum(length for _, length in curves_and_lengths)
979
+ target_length = alpha * np.sum(
980
+ np.fromiter((length for _, length in curves_and_lengths), dtype=np.float64)
981
+ )
947
982
  current_length = 0
948
983
 
949
984
  for curve, length in curves_and_lengths:
@@ -959,7 +994,7 @@ class OpenGLVMobject(OpenGLMobject):
959
994
 
960
995
  def proportion_from_point(
961
996
  self,
962
- point: Iterable[float | int],
997
+ point: Point3DLike,
963
998
  ) -> float:
964
999
  """Returns the proportion along the path of the :class:`OpenGLVMobject`
965
1000
  a particular given point is at.
@@ -1013,7 +1048,7 @@ class OpenGLVMobject(OpenGLMobject):
1013
1048
 
1014
1049
  return alpha
1015
1050
 
1016
- def get_anchors_and_handles(self):
1051
+ def get_anchors_and_handles(self) -> Iterable[np.ndarray]:
1017
1052
  """
1018
1053
  Returns anchors1, handles, anchors2,
1019
1054
  where (anchors1[i], handles[i], anchors2[i])
@@ -1045,27 +1080,21 @@ class OpenGLVMobject(OpenGLMobject):
1045
1080
  nppc = self.n_points_per_curve
1046
1081
  return self.points[nppc - 1 :: nppc]
1047
1082
 
1048
- def get_anchors(self) -> np.ndarray:
1083
+ def get_anchors(self) -> Iterable[np.ndarray]:
1049
1084
  """Returns the anchors of the curves forming the OpenGLVMobject.
1050
1085
 
1051
1086
  Returns
1052
1087
  -------
1053
- np.ndarray
1088
+ Iterable[np.ndarray]
1054
1089
  The anchors.
1055
1090
  """
1056
1091
  points = self.points
1057
1092
  if len(points) == 1:
1058
1093
  return points
1059
- return np.array(
1060
- list(
1061
- it.chain(
1062
- *zip(
1063
- self.get_start_anchors(),
1064
- self.get_end_anchors(),
1065
- )
1066
- ),
1067
- ),
1068
- )
1094
+
1095
+ s = self.get_start_anchors()
1096
+ e = self.get_end_anchors()
1097
+ return list(it.chain.from_iterable(zip(s, e)))
1069
1098
 
1070
1099
  def get_points_without_null_curves(self, atol=1e-9):
1071
1100
  nppc = self.n_points_per_curve
@@ -1092,7 +1121,6 @@ class OpenGLVMobject(OpenGLMobject):
1092
1121
  float
1093
1122
  The length of the :class:`OpenGLVMobject`.
1094
1123
  """
1095
-
1096
1124
  return np.sum(
1097
1125
  length
1098
1126
  for _, length in self.get_curve_functions_with_lengths(
@@ -1213,8 +1241,8 @@ class OpenGLVMobject(OpenGLMobject):
1213
1241
  return path
1214
1242
 
1215
1243
  for n in range(n_subpaths):
1216
- sp1 = get_nth_subpath(subpaths1, n)
1217
- sp2 = get_nth_subpath(subpaths2, n)
1244
+ sp1 = np.asarray(get_nth_subpath(subpaths1, n))
1245
+ sp2 = np.asarray(get_nth_subpath(subpaths2, n))
1218
1246
  diff1 = max(0, (len(sp2) - len(sp1)) // nppc)
1219
1247
  diff2 = max(0, (len(sp1) - len(sp2)) // nppc)
1220
1248
  sp1 = self.insert_n_curves_to_point_list(diff1, sp1)
@@ -1268,30 +1296,12 @@ class OpenGLVMobject(OpenGLMobject):
1268
1296
  if len(points) == 1:
1269
1297
  return np.repeat(points, nppc * n, 0)
1270
1298
 
1271
- bezier_groups = self.get_bezier_tuples_from_points(points)
1272
- norms = np.array([np.linalg.norm(bg[nppc - 1] - bg[0]) for bg in bezier_groups])
1273
- total_norm = sum(norms)
1274
- # Calculate insertions per curve (ipc)
1275
- if total_norm < 1e-6:
1276
- ipc = [n] + [0] * (len(bezier_groups) - 1)
1277
- else:
1278
- ipc = np.round(n * norms / sum(norms)).astype(int)
1279
-
1280
- diff = n - sum(ipc)
1281
- for _ in range(diff):
1282
- ipc[np.argmin(ipc)] += 1
1283
- for _ in range(-diff):
1284
- ipc[np.argmax(ipc)] -= 1
1285
-
1286
- new_points = []
1287
- for group, n_inserts in zip(bezier_groups, ipc):
1288
- # What was once a single quadratic curve defined
1289
- # by "group" will now be broken into n_inserts + 1
1290
- # smaller quadratic curves
1291
- alphas = np.linspace(0, 1, n_inserts + 2)
1292
- for a1, a2 in zip(alphas, alphas[1:]):
1293
- new_points += partial_quadratic_bezier_points(group, a1, a2)
1294
- return np.vstack(new_points)
1299
+ bezier_tuples = self.get_bezier_tuples_from_points(points)
1300
+ current_number_of_curves = len(bezier_tuples)
1301
+ new_number_of_curves = current_number_of_curves + n
1302
+ new_bezier_tuples = bezier_remap(bezier_tuples, new_number_of_curves)
1303
+ new_points = new_bezier_tuples.reshape(-1, 3)
1304
+ return new_points
1295
1305
 
1296
1306
  def interpolate(self, mobject1, mobject2, alpha, *args, **kwargs):
1297
1307
  super().interpolate(mobject1, mobject2, alpha, *args, **kwargs)
@@ -1301,7 +1311,7 @@ class OpenGLVMobject(OpenGLMobject):
1301
1311
  if self.has_fill():
1302
1312
  tri1 = mobject1.get_triangulation()
1303
1313
  tri2 = mobject2.get_triangulation()
1304
- if len(tri1) != len(tri1) or not np.all(tri1 == tri2):
1314
+ if len(tri1) != len(tri2) or not np.all(tri1 == tri2):
1305
1315
  self.refresh_triangulation()
1306
1316
  return self
1307
1317
 
@@ -1344,7 +1354,7 @@ class OpenGLVMobject(OpenGLMobject):
1344
1354
  return self
1345
1355
  if lower_index == upper_index:
1346
1356
  self.append_points(
1347
- partial_quadratic_bezier_points(
1357
+ partial_bezier_points(
1348
1358
  bezier_triplets[lower_index],
1349
1359
  lower_residue,
1350
1360
  upper_residue,
@@ -1352,24 +1362,18 @@ class OpenGLVMobject(OpenGLMobject):
1352
1362
  )
1353
1363
  else:
1354
1364
  self.append_points(
1355
- partial_quadratic_bezier_points(
1356
- bezier_triplets[lower_index], lower_residue, 1
1357
- ),
1365
+ partial_bezier_points(bezier_triplets[lower_index], lower_residue, 1),
1358
1366
  )
1359
1367
  inner_points = bezier_triplets[lower_index + 1 : upper_index]
1360
1368
  if len(inner_points) > 0:
1361
1369
  if remap:
1362
- new_triplets = quadratic_bezier_remap(
1363
- inner_points, num_quadratics - 2
1364
- )
1370
+ new_triplets = bezier_remap(inner_points, num_quadratics - 2)
1365
1371
  else:
1366
1372
  new_triplets = bezier_triplets
1367
1373
 
1368
1374
  self.append_points(np.asarray(new_triplets).reshape(-1, 3))
1369
1375
  self.append_points(
1370
- partial_quadratic_bezier_points(
1371
- bezier_triplets[upper_index], 0, upper_residue
1372
- ),
1376
+ partial_bezier_points(bezier_triplets[upper_index], 0, upper_residue),
1373
1377
  )
1374
1378
  return self
1375
1379
 
@@ -1396,7 +1400,7 @@ class OpenGLVMobject(OpenGLMobject):
1396
1400
 
1397
1401
  # Related to triangulation
1398
1402
 
1399
- def refresh_triangulation(self):
1403
+ def refresh_triangulation(self) -> Self:
1400
1404
  for mob in self.get_family():
1401
1405
  mob.needs_new_triangulation = True
1402
1406
  return self
@@ -1518,6 +1522,7 @@ class OpenGLVMobject(OpenGLMobject):
1518
1522
  self.fill_shader_wrapper.vert_data = self.get_fill_shader_data()
1519
1523
  self.fill_shader_wrapper.vert_indices = self.get_triangulation()
1520
1524
  self.fill_shader_wrapper.uniforms = self.get_fill_uniforms()
1525
+ self.fill_shader_wrapper.depth_test = self.depth_test
1521
1526
 
1522
1527
  def get_stroke_shader_wrapper(self):
1523
1528
  self.update_stroke_shader_wrapper()
@@ -1526,6 +1531,7 @@ class OpenGLVMobject(OpenGLMobject):
1526
1531
  def update_stroke_shader_wrapper(self):
1527
1532
  self.stroke_shader_wrapper.vert_data = self.get_stroke_shader_data()
1528
1533
  self.stroke_shader_wrapper.uniforms = self.get_stroke_uniforms()
1534
+ self.stroke_shader_wrapper.depth_test = self.depth_test
1529
1535
 
1530
1536
  def get_shader_wrapper_list(self):
1531
1537
  # Build up data lists
@@ -1673,9 +1679,7 @@ class OpenGLVGroup(OpenGLVMobject):
1673
1679
  self.add(circles_group)
1674
1680
  """
1675
1681
 
1676
- def __init__(self, *vmobjects, **kwargs):
1677
- if not all([isinstance(m, OpenGLVMobject) for m in vmobjects]):
1678
- raise Exception("All submobjects must be of type OpenGLVMobject")
1682
+ def __init__(self, *vmobjects: OpenGLVMobject, **kwargs: Any):
1679
1683
  super().__init__(**kwargs)
1680
1684
  self.add(*vmobjects)
1681
1685
 
@@ -1741,8 +1745,6 @@ class OpenGLVGroup(OpenGLVMobject):
1741
1745
  (gr-circle_red).animate.shift(RIGHT)
1742
1746
  )
1743
1747
  """
1744
- if not all(isinstance(m, OpenGLVMobject) for m in vmobjects):
1745
- raise TypeError("All submobjects must be of type OpenGLVMobject")
1746
1748
  return super().add(*vmobjects)
1747
1749
 
1748
1750
  def __add__(self, vmobject):
@@ -1788,8 +1790,7 @@ class OpenGLVGroup(OpenGLVMobject):
1788
1790
 
1789
1791
  >>> config.renderer = original_renderer
1790
1792
  """
1791
- if not all(isinstance(m, OpenGLVMobject) for m in value):
1792
- raise TypeError("All submobjects must be of type OpenGLVMobject")
1793
+ self._assert_valid_submobjects(tuplify(value))
1793
1794
  self.submobjects[key] = value
1794
1795
 
1795
1796
 
@@ -1879,7 +1880,7 @@ class OpenGLDashedVMobject(OpenGLVMobject):
1879
1880
  vmobject: OpenGLVMobject,
1880
1881
  num_dashes: int = 15,
1881
1882
  dashed_ratio: float = 0.5,
1882
- color: Color = WHITE,
1883
+ color: ParsableManimColor = WHITE,
1883
1884
  **kwargs,
1884
1885
  ):
1885
1886
  self.dashed_ratio = dashed_ratio
@@ -1890,10 +1891,7 @@ class OpenGLDashedVMobject(OpenGLVMobject):
1890
1891
  if num_dashes > 0:
1891
1892
  # Assuming total length is 1
1892
1893
  dash_len = r / n
1893
- if vmobject.is_closed():
1894
- void_len = (1 - r) / n
1895
- else:
1896
- void_len = (1 - r) / (n - 1)
1894
+ void_len = (1 - r) / n if vmobject.is_closed() else (1 - r) / (n - 1)
1897
1895
 
1898
1896
  self.add(
1899
1897
  *(