Skip to content

Commit 374eeeb

Browse files
authored
Optimize VMobject.pointwise_become_partial() (#3760)
* Optimize VMobject.pointwise_become_partial() * selftransformation -> self * Small factorization of nppc
1 parent 3a71411 commit 374eeeb

File tree

1 file changed

+64
-33
lines changed

1 file changed

+64
-33
lines changed

manim/mobject/types/vectorized_mobject.py

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,60 +1830,91 @@ def pointwise_become_partial(
18301830
a: float,
18311831
b: float,
18321832
) -> Self:
1833-
"""Given two bounds a and b, transforms the points of the self vmobject into the points of the vmobject
1834-
passed as parameter with respect to the bounds. Points here stand for control points of the bezier curves (anchors and handles)
1833+
"""Given a 2nd :class:`.VMobject` ``vmobject``, a lower bound ``a`` and
1834+
an upper bound ``b``, modify this :class:`.VMobject`'s points to
1835+
match the portion of the Bézier spline described by ``vmobject.points``
1836+
with the parameter ``t`` between ``a`` and ``b``.
18351837
18361838
Parameters
18371839
----------
18381840
vmobject
1839-
The vmobject that will serve as a model.
1841+
The :class:`.VMobject` that will serve as a model.
18401842
a
1841-
upper-bound.
1843+
The lower bound for ``t``.
18421844
b
1843-
lower-bound
1845+
The upper bound for ``t``
18441846
18451847
Returns
18461848
-------
1847-
:class:`VMobject`
1848-
``self``
1849+
:class:`.VMobject`
1850+
The :class:`.VMobject` itself, after the transformation.
1851+
1852+
Raises
1853+
------
1854+
TypeError
1855+
If ``vmobject`` is not an instance of :class:`VMobject`.
18491856
"""
1850-
assert isinstance(vmobject, VMobject)
1857+
if not isinstance(vmobject, VMobject):
1858+
raise TypeError(
1859+
f"Expected a VMobject, got value {vmobject} of type "
1860+
f"{type(vmobject).__name__}."
1861+
)
18511862
# Partial curve includes three portions:
1852-
# - A middle section, which matches the curve exactly
1853-
# - A start, which is some ending portion of an inner cubic
1854-
# - An end, which is the starting portion of a later inner cubic
1863+
# - A middle section, which matches the curve exactly.
1864+
# - A start, which is some ending portion of an inner cubic.
1865+
# - An end, which is the starting portion of a later inner cubic.
18551866
if a <= 0 and b >= 1:
18561867
self.set_points(vmobject.points)
18571868
return self
1858-
bezier_quads = vmobject.get_cubic_bezier_tuples()
1859-
num_cubics = len(bezier_quads)
1869+
num_curves = vmobject.get_num_curves()
1870+
if num_curves == 0:
1871+
self.clear_points()
1872+
return self
18601873

1861-
# The following two lines will compute which bezier curves of the given mobject need to be processed.
1862-
# The residue basically indicates de proportion of the selected bezier curve that have to be selected.
1863-
# Ex : if lower_index is 3, and lower_residue is 0.4, then the algorithm will append to the points 0.4 of the third bezier curve
1864-
lower_index, lower_residue = integer_interpolate(0, num_cubics, a)
1865-
upper_index, upper_residue = integer_interpolate(0, num_cubics, b)
1874+
# The following two lines will compute which Bézier curves of the given Mobject must be processed.
1875+
# The residue indicates the proportion of the selected Bézier curve which must be selected.
1876+
#
1877+
# Example: if num_curves is 10, a is 0.34 and b is 0.78, then:
1878+
# - lower_index is 3 and lower_residue is 0.4, which means the algorithm will look at the 3rd Bézier
1879+
# and select its part which ranges from t=0.4 to t=1.
1880+
# - upper_index is 7 and upper_residue is 0.8, which means the algorithm will look at the 7th Bézier
1881+
# and select its part which ranges from t=0 to t=0.8.
1882+
lower_index, lower_residue = integer_interpolate(0, num_curves, a)
1883+
upper_index, upper_residue = integer_interpolate(0, num_curves, b)
18661884

1867-
self.clear_points()
1868-
if num_cubics == 0:
1869-
return self
1885+
nppc = self.n_points_per_curve
1886+
# If both indices coincide, get a part of a single Bézier curve.
18701887
if lower_index == upper_index:
1871-
self.append_points(
1872-
partial_bezier_points(
1873-
bezier_quads[lower_index],
1874-
lower_residue,
1875-
upper_residue,
1876-
),
1888+
# Look at the "lower_index"-th Bézier curve and select its part from
1889+
# t=lower_residue to t=upper_residue.
1890+
self.points = partial_bezier_points(
1891+
vmobject.points[nppc * lower_index : nppc * (lower_index + 1)],
1892+
lower_residue,
1893+
upper_residue,
18771894
)
18781895
else:
1879-
self.append_points(
1880-
partial_bezier_points(bezier_quads[lower_index], lower_residue, 1),
1896+
# Allocate space for (upper_index-lower_index+1) Bézier curves.
1897+
self.points = np.empty((nppc * (upper_index - lower_index + 1), self.dim))
1898+
# Look at the "lower_index"-th Bezier curve and select its part from
1899+
# t=lower_residue to t=1. This is the first curve in self.points.
1900+
self.points[:nppc] = partial_bezier_points(
1901+
vmobject.points[nppc * lower_index : nppc * (lower_index + 1)],
1902+
lower_residue,
1903+
1,
18811904
)
1882-
for quad in bezier_quads[lower_index + 1 : upper_index]:
1883-
self.append_points(quad)
1884-
self.append_points(
1885-
partial_bezier_points(bezier_quads[upper_index], 0, upper_residue),
1905+
# If there are more curves between the "lower_index"-th and the
1906+
# "upper_index"-th Béziers, add them all to self.points.
1907+
self.points[nppc:-nppc] = vmobject.points[
1908+
nppc * (lower_index + 1) : nppc * upper_index
1909+
]
1910+
# Look at the "upper_index"-th Bézier curve and select its part from
1911+
# t=0 to t=upper_residue. This is the last curve in self.points.
1912+
self.points[-nppc:] = partial_bezier_points(
1913+
vmobject.points[nppc * upper_index : nppc * (upper_index + 1)],
1914+
0,
1915+
upper_residue,
18861916
)
1917+
18871918
return self
18881919

18891920
def get_subcurve(self, a: float, b: float) -> Self:

0 commit comments

Comments
 (0)