@@ -2345,6 +2345,69 @@ def __init__(self, vmobject, **kwargs):
23452345 part .match_style (vmobject )
23462346 self .add (part )
23472347
2348+ def point_from_proportion (self , alpha : float ) -> np .ndarray :
2349+ """Gets the point at a proportion along the path of the :class:`CurvesAsSubmobjects`.
2350+
2351+ Parameters
2352+ ----------
2353+ alpha
2354+ The proportion along the the path of the :class:`CurvesAsSubmobjects`.
2355+
2356+ Returns
2357+ -------
2358+ :class:`numpy.ndarray`
2359+ The point on the :class:`CurvesAsSubmobjects`.
2360+
2361+ Raises
2362+ ------
2363+ :exc:`ValueError`
2364+ If ``alpha`` is not between 0 and 1.
2365+ :exc:`Exception`
2366+ If the :class:`CurvesAsSubmobjects` has no submobjects, or no submobject has points.
2367+ """
2368+ if alpha < 0 or alpha > 1 :
2369+ raise ValueError (f"Alpha { alpha } not between 0 and 1." )
2370+
2371+ self ._throw_error_if_no_submobjects ()
2372+ submobjs_with_pts = self ._get_submobjects_with_points ()
2373+
2374+ if alpha == 1 :
2375+ return submobjs_with_pts [- 1 ].points [- 1 ]
2376+
2377+ submobjs_arc_lengths = tuple (
2378+ part .get_arc_length () for part in submobjs_with_pts
2379+ )
2380+
2381+ total_length = sum (submobjs_arc_lengths )
2382+ target_length = alpha * total_length
2383+ current_length = 0
2384+
2385+ for i , part in enumerate (submobjs_with_pts ):
2386+ part_length = submobjs_arc_lengths [i ]
2387+ if current_length + part_length >= target_length :
2388+ residue = (target_length - current_length ) / part_length
2389+ return part .point_from_proportion (residue )
2390+
2391+ current_length += part_length
2392+
2393+ def _throw_error_if_no_submobjects (self ):
2394+ if len (self .submobjects ) == 0 :
2395+ caller_name = sys ._getframe (1 ).f_code .co_name
2396+ raise Exception (
2397+ f"Cannot call CurvesAsSubmobjects.{ caller_name } for a CurvesAsSubmobject with no submobjects"
2398+ )
2399+
2400+ def _get_submobjects_with_points (self ):
2401+ submobjs_with_pts = tuple (
2402+ part for part in self .submobjects if len (part .points ) > 0
2403+ )
2404+ if len (submobjs_with_pts ) == 0 :
2405+ caller_name = sys ._getframe (1 ).f_code .co_name
2406+ raise Exception (
2407+ f"Cannot call CurvesAsSubmobjects.{ caller_name } for a CurvesAsSubmobject whose submobjects have no points"
2408+ )
2409+ return submobjs_with_pts
2410+
23482411
23492412class DashedVMobject (VMobject , metaclass = ConvertToOpenGL ):
23502413 """A :class:`VMobject` composed of dashes instead of lines.
0 commit comments