Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions manim/mobject/opengl/opengl_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,7 @@ def get_group_class(self):
# Alignment

def align_data_and_family(self, mobject):
self.null_point_align(mobject)
self.align_family(mobject)
self.align_data(mobject)

Expand All @@ -2263,6 +2264,26 @@ def align_data(self, mobject):
elif len(arr1) > len(arr2):
mob2.data[key] = resize_preserving_order(arr2, len(arr1))

def null_point_align_family(self, mobject):
for mob1, mob2 in zip(self.get_family(), mobject.get_family()):
mob1.null_point_align(mob2)

def null_point_align(self, mobject: OpenGLMobject):
"""If a :class:`~.OpenGLMobject` with points is being aligned to
one without, treat both as groups, and push
the one with points into its own submobjects
list.

Returns
-------
:class:`Mobject`
``self``
"""
for m1, m2 in (self, mobject), (mobject, self):
if (not m1.has_points()) and m2.has_points():
m2.push_self_into_submobjects()
return self

def align_points(self, mobject):
max_len = max(self.get_num_points(), mobject.get_num_points())
for mob in (self, mobject):
Expand Down Expand Up @@ -2348,11 +2369,14 @@ def construct(self):
continue

if key in ("points", "bounding_box"):
func = path_func
self.data[key] = path_func(
mobject1.data[key], mobject2.data[key], alpha
)
else:
func = interpolate
self.data[key][:] = interpolate(
mobject1.data[key], mobject2.data[key], alpha
)

self.data[key][:] = func(mobject1.data[key], mobject2.data[key], alpha)
for key in self.uniforms:
if key != "fixed_orientation_center":
self.uniforms[key] = interpolate(
Expand Down
78 changes: 32 additions & 46 deletions manim/mobject/opengl/opengl_vectorized_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ def __init__(
self.flat_stroke = flat_stroke
self.render_primitive = render_primitive
self.triangulation_locked = triangulation_locked
self.n_points_per_curve = n_points_per_curve

self.needs_new_triangulation = True
self.triangulation = np.zeros(0, dtype="i4")
Expand Down Expand Up @@ -783,10 +782,7 @@ def get_nth_curve_function_with_length(
sample_points = 10

curve = self.get_nth_curve_function(n)

points = np.array([curve(a) for a in np.linspace(0, 1, sample_points)])
diffs = points[1:] - points[:-1]
norms = np.apply_along_axis(np.linalg.norm, 1, diffs)
norms = self.get_nth_curve_length_pieces(n, sample_points)

length = np.sum(norms)

Expand Down Expand Up @@ -1303,56 +1299,46 @@ def pointwise_become_partial(
lower-bound
"""
assert isinstance(vmobject, OpenGLVMobject)
# Partial curve includes three portions:
# - A middle section, which matches the curve exactly
# - A start, which is some ending portion of an inner cubic
# - An end, which is the starting portion of a later inner cubic
if a <= 0 and b >= 1:
self.become(vmobject)
self.set_points(vmobject.points)
return self
num_curves = vmobject.get_num_curves()
nppc = self.n_points_per_curve
bezier_triplets = vmobject.get_bezier_tuples()
num_quadratics = len(bezier_triplets)

# Partial curve includes three portions:
# - A middle section, which matches the curve exactly
# - A start, which is some ending portion of an inner quadratic
# - An end, which is the starting portion of a later inner quadratic

lower_index, lower_residue = integer_interpolate(0, num_curves, a)
upper_index, upper_residue = integer_interpolate(0, num_curves, b)
i1 = nppc * lower_index
i2 = nppc * (lower_index + 1)
i3 = nppc * upper_index
i4 = nppc * (upper_index + 1)

vm_points = vmobject.points
new_points = vm_points.copy()
if num_curves == 0:
new_points[:] = 0
# The following two lines will compute which bezier curves of the given mobject need to be processed.
# The residue basically indicates de proportion of the selected bezier curve that have to be selected.
# 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
lower_index, lower_residue = integer_interpolate(0, num_quadratics, a)
upper_index, upper_residue = integer_interpolate(0, num_quadratics, b)

self.clear_points()
if num_quadratics == 0:
return self
if lower_index == upper_index:
tup = partial_quadratic_bezier_points(
vm_points[i1:i2],
lower_residue,
upper_residue,
self.append_points(
partial_quadratic_bezier_points(
bezier_triplets[lower_index],
lower_residue,
upper_residue,
),
)
new_points[:i1] = tup[0]
new_points[i1:i4] = tup
new_points[i4:] = tup[2]
new_points[nppc:] = new_points[nppc - 1]
else:
low_tup = partial_quadratic_bezier_points(
vm_points[i1:i2],
lower_residue,
1,
self.append_points(
partial_quadratic_bezier_points(
bezier_triplets[lower_index], lower_residue, 1
),
)
high_tup = partial_quadratic_bezier_points(
vm_points[i3:i4],
0,
upper_residue,
for quad in bezier_triplets[lower_index + 1 : upper_index]:
self.append_points(quad)
self.append_points(
partial_quadratic_bezier_points(
bezier_triplets[upper_index], 0, upper_residue
),
)
new_points[0:i1] = low_tup[0]
new_points[i1:i2] = low_tup
# Keep new_points i2:i3 as they are
new_points[i3:i4] = high_tup
new_points[i4:] = high_tup[2]
self.set_points(new_points)
return self

def get_subcurve(self, a: float, b: float) -> OpenGLVMobject:
Expand Down