mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 05:52:34 +08:00
ShowPartial works for vectorized mobjects
This commit is contained in:
@ -38,15 +38,7 @@ class ShowPartial(Animation):
|
||||
self.mobject.submobject_family()
|
||||
)
|
||||
for start, mob in pairs:
|
||||
lower_alpha, upper_alpha = self.get_bounds(alpha)
|
||||
lower_index, upper_index = [
|
||||
int(a * start.get_num_points())
|
||||
for a in lower_alpha, upper_alpha
|
||||
]
|
||||
for attr in mob.get_array_attrs():
|
||||
full_array = getattr(start, attr)
|
||||
partial_array = full_array[lower_index:upper_index]
|
||||
setattr(mob, attr, partial_array)
|
||||
mob.become_partial(start, *self.get_bounds(alpha))
|
||||
|
||||
def get_bounds(self, alpha):
|
||||
raise Exception("Not Implemented")
|
||||
|
@ -451,6 +451,14 @@ class Mobject(object):
|
||||
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def become_partial(self, mobject, a, b):
|
||||
"""
|
||||
Set points in such a way as to become only
|
||||
part of mobject.
|
||||
Inputs 0 <= a < b <= 1 determine what portion
|
||||
of mobject to become.
|
||||
"""
|
||||
raise Exception("Not implemented")
|
||||
|
||||
|
||||
|
||||
|
@ -127,6 +127,16 @@ class PointCloudMobject(Mobject):
|
||||
mobject1.rgbs, mobject2.rgbs, alpha
|
||||
)
|
||||
|
||||
def become_partial(self, mobject, a, b):
|
||||
lower_index, upper_index = [
|
||||
int(x * mobject.get_num_points())
|
||||
for x in a, b
|
||||
]
|
||||
for attr in self.get_array_attrs():
|
||||
full_array = getattr(mobject, attr)
|
||||
partial_array = full_array[lower_index:upper_index]
|
||||
setattr(self, attr, partial_array)
|
||||
|
||||
|
||||
#TODO, Make the two implementations bellow non-redundant
|
||||
class Mobject1D(PointCloudMobject):
|
||||
|
@ -132,9 +132,12 @@ class VectorizedMobject(Mobject):
|
||||
|
||||
## Information about line
|
||||
|
||||
def component_curves_iter(self):
|
||||
for i in range(0, len(self.points)-1, 3):
|
||||
yield bezier(self.points[i:i+4])
|
||||
def component_curves(self):
|
||||
for n in range(self.get_num_points()-1):
|
||||
yield self.get_nth_curve(n)
|
||||
|
||||
def get_nth_curve(self, n):
|
||||
return bezier(self.points[3*n:3*n+4])
|
||||
|
||||
def get_num_points(self):
|
||||
return (len(self.points) - 1)/3 + 1
|
||||
@ -153,6 +156,7 @@ class VectorizedMobject(Mobject):
|
||||
]
|
||||
|
||||
## Alignment
|
||||
|
||||
# def align_points_with_larger(self, larger_mobject):
|
||||
# assert(isinstance(larger_mobject, VectorizedMobject))
|
||||
# anchors, handles1, handles2 = self.get_anchors_and_handles()
|
||||
@ -179,7 +183,7 @@ class VectorizedMobject(Mobject):
|
||||
#curves are buckets, and we need to know how many new
|
||||
#anchor points to put into each one
|
||||
index_allocation = (np.arange(target_len) * num_curves)/target_len
|
||||
for index, curve in enumerate(self.component_curves_iter()):
|
||||
for index, curve in enumerate(self.component_curves()):
|
||||
num_inter_points = sum(index_allocation == index)
|
||||
step = 1./num_inter_points
|
||||
alphas = np.arange(0, 1+step, step)
|
||||
@ -211,6 +215,77 @@ class VectorizedMobject(Mobject):
|
||||
))
|
||||
|
||||
|
||||
def get_partial_bezier_points(self, x, pre_x = True):
|
||||
"""
|
||||
Input is a number number 0 <= x <= 1, which
|
||||
corresponds to some point along the curve.
|
||||
This point lies on some cubic. This function
|
||||
return the four bezeir points giving a partial
|
||||
version of that cubic. Either the part before x,
|
||||
if pre_x == True, otherwise the part after x
|
||||
"""
|
||||
if x >= 1.0:
|
||||
return np.array(4*[self.points[-1]])
|
||||
num_cubics = self.get_num_points()-1
|
||||
which_curve = int(x*num_cubics)
|
||||
alpha = num_cubics*(x%(1./num_cubics))
|
||||
cubic = self.get_nth_curve(which_curve)
|
||||
new_anchor = cubic(alpha)
|
||||
a1, h1, h2, a2 = self.points[3*which_curve:3*which_curve+4]
|
||||
if pre_x:
|
||||
return np.array([
|
||||
a1,
|
||||
interpolate(cubic(alpha/3), h1, alpha),
|
||||
interpolate(cubic(2*alpha/3), h2, alpha),
|
||||
new_anchor
|
||||
])
|
||||
else:
|
||||
return np.array([
|
||||
new_anchor,
|
||||
interpolate(h1, cubic((1-alpha)/3), alpha),
|
||||
interpolate(h2, cubic(2*(1-alpha/3), alpha)),
|
||||
a2
|
||||
])
|
||||
|
||||
|
||||
def become_partial(self, mobject, a, b):
|
||||
assert(isinstance(mobject, VectorizedMobject))
|
||||
#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
|
||||
self.open()
|
||||
if a <= 0 and b >= 1 and mobject.is_closed():
|
||||
self.close()
|
||||
num_cubics = mobject.get_num_points()-1
|
||||
if a <= 0:
|
||||
lower_index = 0
|
||||
start_points = np.zeros((0, 3))
|
||||
else:
|
||||
lower_index = 3*int(a*num_cubics)+4
|
||||
start_points = mobject.get_partial_bezier_points(
|
||||
a, pre_x = False
|
||||
)
|
||||
if b >= 1:
|
||||
upper_index = len(mobject.points)+1
|
||||
end_points = np.zeros((0, 3))
|
||||
else:
|
||||
upper_index = 3*int(b*num_cubics)
|
||||
end_points = mobject.get_partial_bezier_points(
|
||||
b, pre_x = True
|
||||
)
|
||||
new_points = reduce(
|
||||
lambda a, b : np.append(a, b, axis = 0),
|
||||
[
|
||||
start_points,
|
||||
mobject.points[lower_index:upper_index],
|
||||
end_points
|
||||
]
|
||||
)
|
||||
self.set_points(new_points, "handles_included")
|
||||
return self
|
||||
|
||||
|
||||
class VectorizedPoint(VectorizedMobject):
|
||||
CONFIG = {
|
||||
"color" : BLACK,
|
||||
|
Reference in New Issue
Block a user