Write class is looking pretty nice.

This commit is contained in:
Grant Sanderson
2016-04-20 19:24:54 -07:00
parent cb3fff7da5
commit 2c17488fb2
6 changed files with 75 additions and 29 deletions

View File

@ -33,7 +33,7 @@ class Rotating(Animation):
class ShowPartial(Animation): class ShowPartial(Animation):
CONFIG = { CONFIG = {
"one_submobject_at_a_time" : False "submobject_mode" : None
} }
def update_mobject(self, alpha): def update_mobject(self, alpha):
pairs = zip( pairs = zip(
@ -41,7 +41,11 @@ class ShowPartial(Animation):
self.mobject.submobject_family() self.mobject.submobject_family()
) )
for i, (start, mob) in enumerate(pairs): for i, (start, mob) in enumerate(pairs):
if self.one_submobject_at_a_time: 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) lower = float(i)/len(pairs)
upper = float(i+1)/len(pairs) upper = float(i+1)/len(pairs)
sub_alpha = (alpha-lower)/(upper-lower) sub_alpha = (alpha-lower)/(upper-lower)
@ -61,10 +65,17 @@ class ShowCreation(ShowPartial):
class ShowCreationPerSubmobject(ShowCreation): class ShowCreationPerSubmobject(ShowCreation):
CONFIG = { CONFIG = {
"one_submobject_at_a_time" : True, "submobject_mode" : "one_at_a_time",
"run_time" : 3 "run_time" : 3
} }
class Write(ShowCreation):
CONFIG = {
"run_time" : 3,
"rate_func" : None,
"submobject_mode" : "lagged_start",
}
class ShowPassingFlash(ShowPartial): class ShowPassingFlash(ShowPartial):
CONFIG = { CONFIG = {
"time_width" : 0.1 "time_width" : 0.1

View File

@ -470,11 +470,14 @@ class Mobject(object):
for index in indices: for index in indices:
submob = self.submobjects[index] submob = self.submobjects[index]
if submob in new_submobjects: if submob in new_submobjects:
submob = submob.copy() submob = self.repeat_submobject(submob)
new_submobjects.append(submob) new_submobjects.append(submob)
self.submobjects = new_submobjects self.submobjects = new_submobjects
return self return self
def repeat_submobject(self, submob):
return submob.copy()
def interpolate(self, mobject1, mobject2, alpha, path_func): def interpolate(self, mobject1, mobject2, alpha, path_func):
""" """
Turns target_mobject into an interpolation between mobject1 Turns target_mobject into an interpolation between mobject1

View File

@ -32,7 +32,9 @@ class SVGMobject(VMobject):
for child in element.childNodes for child in element.childNodes
]) ])
elif element.tagName == 'path': elif element.tagName == 'path':
result.append(self.path_to_mobject(element)) result.append(self.path_string_to_mobject(
element.getAttribute('d')
))
elif element.tagName == 'use': elif element.tagName == 'use':
result += self.use_to_mobjects(element) result += self.use_to_mobjects(element)
elif element.tagName == 'rect': elif element.tagName == 'rect':
@ -50,21 +52,18 @@ class SVGMobject(VMobject):
self.handle_transforms(g_element, mob) self.handle_transforms(g_element, mob)
return mob.submobjects return mob.submobjects
def path_to_mobject(self, path_element): def path_string_to_mobject(self, path_string):
return VMobjectFromSVGPathstring( return VMobjectFromSVGPathstring(path_string)
path_element.getAttribute('d')
)
def use_to_mobjects(self, use_element): def use_to_mobjects(self, use_element):
#Remove initial "#" character #Remove initial "#" character
ref = use_element.getAttribute("xlink:href")[1:] ref = use_element.getAttribute("xlink:href")[1:]
try: if ref not in self.ref_to_element:
return self.get_mobjects_from(
self.ref_to_element[ref]
)
except:
warnings.warn("%s not recognized"%ref) warnings.warn("%s not recognized"%ref)
return return VMobject()
return self.get_mobjects_from(
self.ref_to_element[ref]
)
# <circle class="st1" cx="143.8" cy="268" r="22.6"/> # <circle class="st1" cx="143.8" cy="268" r="22.6"/>
@ -184,7 +183,7 @@ class VMobjectFromSVGPathstring(VMobject):
if not is_closed(points): if not is_closed(points):
#Both handles and new anchor are the start #Both handles and new anchor are the start
new_points = points[[0, 0, 0]] new_points = points[[0, 0, 0]]
self.mark_paths_closed = True # self.mark_paths_closed = True
self.growing_path.add_control_points(new_points) self.growing_path.add_control_points(new_points)
def string_to_points(self, coord_string): def string_to_points(self, coord_string):

View File

@ -1,8 +1,28 @@
from vectorized_mobject import VMobject from vectorized_mobject import VMobject
from svg_mobject import SVGMobject from svg_mobject import SVGMobject, VMobjectFromSVGPathstring
from helpers import * from helpers import *
TEX_MOB_SCALE_VAL = 0.05 TEX_MOB_SCALE_VAL = 0.1
TEXT_MOB_SCALE_VAL = 0.2
class TexSymbol(VMobjectFromSVGPathstring):
def become_partial(self, mobject, a, b):
#TODO, this assumes a = 0
if b < 0.5:
b = 2*b
width = 1
opacity = 0
else:
width = 2 - 2*b
opacity = 2*b - 1
b = 1
VMobjectFromSVGPathstring.become_partial(
self, mobject, 0, b
)
self.set_stroke(width = width)
self.set_fill(opacity = opacity)
class TexMobject(SVGMobject): class TexMobject(SVGMobject):
CONFIG = { CONFIG = {
@ -13,6 +33,7 @@ class TexMobject(SVGMobject):
"should_center" : True, "should_center" : True,
"next_to_direction" : RIGHT, "next_to_direction" : RIGHT,
"next_to_buff" : 0.2, "next_to_buff" : 0.2,
"initial_scale_val" : TEX_MOB_SCALE_VAL,
} }
def __init__(self, expression, **kwargs): def __init__(self, expression, **kwargs):
digest_config(self, kwargs, locals()) digest_config(self, kwargs, locals())
@ -20,6 +41,12 @@ class TexMobject(SVGMobject):
self.move_into_position() self.move_into_position()
self.organize_submobjects() self.organize_submobjects()
def path_string_to_mobject(self, path_string):
#Overwrite superclass default to use
#specialized path_string mobject
return TexSymbol(path_string)
def generate_points(self): def generate_points(self):
if isinstance(self.expression, list): if isinstance(self.expression, list):
self.handle_list_expression() self.handle_list_expression()
@ -34,7 +61,8 @@ class TexMobject(SVGMobject):
def handle_list_expression(self): def handle_list_expression(self):
#TODO, next_to not sufficient? #TODO, next_to not sufficient?
subs = [ subs = [
TexMobject(expr) # TexMobject(expr)
self.__class__(expr)
for expr in self.expression for expr in self.expression
] ]
for sm1, sm2 in zip(subs, subs[1:]): for sm1, sm2 in zip(subs, subs[1:]):
@ -53,13 +81,15 @@ class TexMobject(SVGMobject):
def move_into_position(self): def move_into_position(self):
self.center() self.center()
self.scale(TEX_MOB_SCALE_VAL) self.scale(self.initial_scale_val)
self.init_colors() self.init_colors()
class TextMobject(TexMobject): class TextMobject(TexMobject):
CONFIG = { CONFIG = {
"template_tex_file" : TEMPLATE_TEXT_FILE, "template_tex_file" : TEMPLATE_TEXT_FILE,
"initial_scale_val" : TEXT_MOB_SCALE_VAL,
} }

View File

@ -146,9 +146,8 @@ class VMobject(Mobject):
but will be tracked in a separate special list for when but will be tracked in a separate special list for when
it comes time to display. it comes time to display.
""" """
subpath_mobject = VMobject( subpath_mobject = self.copy()#TODO, better way?
is_subpath = True subpath_mobject.is_subpath = True
)
subpath_mobject.set_points(points) subpath_mobject.set_points(points)
self.add(subpath_mobject) self.add(subpath_mobject)
return subpath_mobject return subpath_mobject
@ -190,9 +189,9 @@ class VMobject(Mobject):
Mobject.align_points(self, mobject) Mobject.align_points(self, mobject)
is_subpath = self.is_subpath or mobject.is_subpath is_subpath = self.is_subpath or mobject.is_subpath
self.is_subpath = mobject.is_subpath = is_subpath self.is_subpath = mobject.is_subpath = is_subpath
mark_closed = self.mark_paths_closed and mobject.mark_paths_closed mark_closed = self.mark_paths_closed and mobject.mark_paths_closed
self.mark_paths_closed = mobject.mark_paths_closed = mark_closed self.mark_paths_closed = mobject.mark_paths_closed = mark_closed
return self return self
def align_points_with_larger(self, larger_mobject): def align_points_with_larger(self, larger_mobject):
assert(isinstance(larger_mobject, VMobject)) assert(isinstance(larger_mobject, VMobject))
@ -208,7 +207,7 @@ class VMobject(Mobject):
self.points = np.zeros((1, 3)) self.points = np.zeros((1, 3))
n = n-1 n = n-1
if curr == 1: if curr == 1:
self.points = np.repeat(self.points, n+1) self.points = np.repeat(self.points, 3*n+1, axis = 0)
return self return self
points = np.array([self.points[0]]) points = np.array([self.points[0]])
num_curves = curr-1 num_curves = curr-1
@ -237,6 +236,11 @@ class VMobject(Mobject):
center = self.get_center() center = self.get_center()
return VectorizedPoint(center) return VectorizedPoint(center)
def repeat_submobject(self, submobject):
if submobject.is_subpath:
return VectorizedPoint(submobject.points[0])
return submobject.copy()
def interpolate_color(self, mobject1, mobject2, alpha): def interpolate_color(self, mobject1, mobject2, alpha):
attrs = [ attrs = [
"stroke_rgb", "stroke_rgb",
@ -285,7 +289,7 @@ class VectorizedPoint(VMobject):
} }
def __init__(self, location = ORIGIN, **kwargs): def __init__(self, location = ORIGIN, **kwargs):
VMobject.__init__(self, **kwargs) VMobject.__init__(self, **kwargs)
self.set_points([location]) self.set_points(np.array([location]))

View File

@ -85,8 +85,7 @@ class Line(VMobject):
def pointify(self, mob_or_point): def pointify(self, mob_or_point):
if isinstance(mob_or_point, Mobject): if isinstance(mob_or_point, Mobject):
return mob_or_point.get_center() return mob_or_point.get_center()
else: return np.array(mob_or_point)
return np.array(mob_or_point)
def generate_points(self): def generate_points(self):
self.set_points_as_corners([self.start, self.end]) self.set_points_as_corners([self.start, self.end])