Refactored ShowCreation submobject management to Mobject class

This commit is contained in:
Grant Sanderson
2016-07-19 11:08:31 -07:00
parent a87b58a633
commit b4eac6d6a9
6 changed files with 120 additions and 32 deletions

View File

@ -4,6 +4,8 @@ import itertools as it
from helpers import *
from mobject import Mobject
from mobject.vectorized_mobject import VMobject
from mobject.tex_mobject import DecimalNumber
from animation import Animation
@ -36,24 +38,11 @@ class ShowPartial(Animation):
"submobject_mode" : None
}
def update_mobject(self, alpha):
pairs = zip(
self.starting_mobject.submobject_family(),
self.mobject.submobject_family()
self.mobject.become_partial(
self.starting_mobject,
*self.get_bounds(alpha),
submobject_partial_creation_mode = self.submobject_mode
)
for i, (start, mob) in enumerate(pairs):
if self.submobject_mode == "lagged_start":
sub_alpha = 2*alpha - float(i)/len(pairs)
sub_alpha = max(0, sub_alpha)
sub_alpha = min(1, sub_alpha)
elif self.submobject_mode == "one_at_a_time":
lower = float(i)/len(pairs)
upper = float(i+1)/len(pairs)
sub_alpha = (alpha-lower)/(upper-lower)
sub_alpha = max(0, sub_alpha)
sub_alpha = min(1, sub_alpha)
else:
sub_alpha = alpha
mob.become_partial(start, *self.get_bounds(sub_alpha))
def get_bounds(self, alpha):
raise Exception("Not Implemented")
@ -175,6 +164,55 @@ class MoveAlongPath(Animation):
point = self.path.points[int(alpha*n)]
self.mobject.shift(point-self.mobject.get_center())
class RangingValues(Animation):
CONFIG = {
"num_decimal_points" : 2,
"rate_func" : None,
"tracking_function" : None,
"tracked_mobject" : None,
"tracked_mobject_next_to_kwargs" : {},
}
def __init__(self, start_val, end_val, **kwargs):
digest_config(self, kwargs, locals())
Animation.__init__(self, self.get_mobject_at_alpha(0), **kwargs)
def update_mobject(self, alpha):
pairs = zip(
self.mobject.family_members_with_points(),
self.get_mobject_at_alpha(alpha).family_members_with_points()
)
for old, new in pairs:
##TODO, figure out a better way
old.__dict__.update(new.__dict__)
def get_number(self, alpha):
return interpolate(self.start_val, self.end_val, alpha)
def get_mobject_at_alpha(self, alpha):
mob = DecimalNumber(
self.get_number(alpha),
num_decimal_points=self.num_decimal_points
)
if self.tracking_function:
self.tracking_function(alpha, mob)
elif self.tracked_mobject:
mob.next_to(
self.tracked_mobject,
**self.tracked_mobject_next_to_kwargs
)
return mob
def set_tracking_function(self, func):
"""
func shoudl be of the form func(alpha, mobject), and
should dictate where to place running number during an
animation
"""
self.tracking_function = func
### Animation modifiers ###
class ApplyToCenters(Animation):

View File

@ -21,7 +21,9 @@ class Mobject(object):
"stroke_width" : DEFAULT_POINT_THICKNESS,
"name" : None,
"dim" : 3,
"target" : None
"target" : None,
#Options are lagged_start, one_at_a_time, all_at_once
"submobject_partial_creation_mode" : "lagged_start",
}
def __init__(self, *submobjects, **kwargs):
digest_config(self, kwargs)
@ -219,6 +221,13 @@ class Mobject(object):
self.shift(target_point - anchor_point + buff*direction)
return self
def shift_onto_screen(self):
space_lengths = [SPACE_WIDTH, SPACE_HEIGHT]
for vect in UP, DOWN, LEFT, RIGHT:
dim = np.argmax(np.abs(vect))
if abs(self.get_edge_center(vect)[dim]) > space_lengths[dim]:
self.to_edge(vect)
def stretch_to_fit(self, length, dim, stretch = True):
old_length = self.length_over_dim(dim)
if old_length == 0:
@ -423,12 +432,9 @@ class Mobject(object):
self.submobject_family()
)
def arrange_submobjects(self,
direction = RIGHT,
buff = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
center = True):
def arrange_submobjects(self, direction = RIGHT, center = True, **kwargs):
for m1, m2 in zip(self.submobjects, self.submobjects[1:]):
m2.next_to(m1, direction, buff = buff)
m2.next_to(m1, direction, **kwargs)
if center:
self.center()
return self
@ -533,13 +539,37 @@ class Mobject(object):
def interpolate_color(self, mobject1, mobject2, alpha):
raise Exception("Not implemented")
def become_partial(self, mobject, a, b):
def become_partial(self, mobject, a, b, submobject_partial_creation_mode = None):
"""
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.
"""
self.pointwise_become_partial(mobject, a, b)
#TODO, color
# self.interpolate_color(self, mobject, b)
spcm = submobject_partial_creation_mode or self.submobject_partial_creation_mode
pairs = zip(self.submobjects, mobject.submobjects)
for i, (self_sub, mob_sub) in enumerate(pairs):
if spcm == "lagged_start":
prop = float(i)/len(pairs)
sub_a = np.clip(2*a - prop, 0, 1)
sub_b = np.clip(2*b - prop, 0, 1)
elif spcm == "one_at_a_time":
lower = float(i)/len(pairs)
upper = float(i+1)/len(pairs)
sub_a = np.clip((a-lower)/(upper-lower), 0, 1)
sub_b = np.clip((b-lower)/(upper-lower), 0, 1)
elif spcm == "all_at_once":
sub_a, sub_b = a, b
else:
raise Exception("Invalid submobject partial creation mode")
self_sub.become_partial(mob_sub, sub_a, sub_b)
return self
def pointwise_become_partial(self, mobject, a, b):
raise Exception("Not implemented")
@ -557,3 +587,4 @@ class Mobject(object):

View File

@ -129,7 +129,7 @@ class PMobject(Mobject):
mobject1.rgbs, mobject2.rgbs, alpha
)
def become_partial(self, mobject, a, b):
def pointwise_become_partial(self, mobject, a, b):
lower_index, upper_index = [
int(x * mobject.get_num_points())
for x in a, b

View File

@ -7,7 +7,7 @@ TEXT_MOB_SCALE_VAL = 0.05
class TexSymbol(VMobjectFromSVGPathstring):
def become_partial(self, mobject, a, b):
def pointwise_become_partial(self, mobject, a, b):
#TODO, this assumes a = 0
if b < 0.5:
b = 2*b
@ -17,7 +17,7 @@ class TexSymbol(VMobjectFromSVGPathstring):
width = 2 - 2*b
opacity = 2*b - 1
b = 1
VMobjectFromSVGPathstring.become_partial(
VMobjectFromSVGPathstring.pointwise_become_partial(
self, mobject, 0, b
)
self.set_stroke(width = width)
@ -64,10 +64,7 @@ class TexMobject(SVGMobject):
def handle_list_expression(self):
#TODO, next_to not sufficient?
subs = [
# TexMobject(expr)
self.__class__(
expr
)
TexMobject(expr)
for expr in self.expression
]
self.initial_scale_val = 1
@ -110,6 +107,27 @@ class Brace(TexMobject):
for mob in mobject, self:
mob.rotate(angle)
class DecimalNumber(TexMobject):
CONFIG = {
"num_decimal_points" : 2,
"digit_to_digit_buff" : 0.05
}
def __init__(self, float_num, **kwargs):
digest_config(self, kwargs)
num_string = '%.*f' % (self.num_decimal_points, float_num)
TexMobject.__init__(self, list(num_string))
self.arrange_submobjects(
buff = self.digit_to_digit_buff,
aligned_edge = DOWN
)
if float_num < 0:
minus = self.submobjects[0]
minus.next_to(
self.submobjects[1], LEFT,
buff = self.digit_to_digit_buff
)
def tex_hash(expression, template_tex_file):
return str(hash(expression + template_tex_file))

View File

@ -300,7 +300,7 @@ class VMobject(Mobject):
# print getattr(mobject2, attr)
setattr(self, attr, getattr(mobject2, attr))
def become_partial(self, mobject, a, b):
def pointwise_become_partial(self, mobject, a, b):
assert(isinstance(mobject, VMobject))
#Partial curve includes three portions:
#-A middle section, which matches the curve exactly

View File

@ -133,6 +133,7 @@ class Arrow(Line):
"buff" : 0.3,
"propogate_style_to_family" : False,
"preserve_tip_size_when_scaling" : True,
"submobject_partial_creation_mode" : "one_at_a_time",
}
def __init__(self, *args, **kwargs):
if len(args) == 1: