From aba43479f0ea6997114151bf2f40224dfb89c29a Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Mon, 5 Mar 2018 20:25:01 -0800 Subject: [PATCH] Poor man's merge --- animation/simple_animations.py | 28 +++++++++++++++------------- mobject/vectorized_mobject.py | 13 +++++++------ topics/number_line.py | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/animation/simple_animations.py b/animation/simple_animations.py index 484e161f..f035353a 100644 --- a/animation/simple_animations.py +++ b/animation/simple_animations.py @@ -358,7 +358,6 @@ class Succession(Animation): Each arg will either be an animation, or an animation class followed by its arguments (and potentially a dict for configuration). - For example, Succession( ShowCreation(circle), @@ -443,13 +442,12 @@ class Succession(Animation): # Beware: This does NOT take care of calling update(0) on the subanimation. # This was important to avoid a pernicious possibility in which subanimations were called - # with update(0) twice, which could in turn call a sub-Succession with update(0) four times, + # with update twice, which could in turn call a sub-Succession with update four times, # continuing exponentially. def jump_to_start_of_anim(self, index): if index != self.current_anim_index: self.mobject.remove(*self.mobject.submobjects) # Should probably have a cleaner "remove_all" method... - for m in self.scene_mobjects_at_time[index].submobjects: - self.mobject.add(m) + self.mobject.add(*self.scene_mobjects_at_time[index].submobjects) self.mobject.add(self.animations[index].mobject) for i in range(index): @@ -459,10 +457,9 @@ class Succession(Animation): self.current_alpha = self.critical_alphas[index] def update_mobject(self, alpha): - if alpha == self.current_alpha: - return - if self.num_anims == 0: + # This probably doesn't matter for anything, but just in case, + # we want it in the future, we set current_alpha even in this case self.current_alpha = alpha return @@ -505,16 +502,14 @@ class AnimationGroup(Animation): "rate_func" : None } def __init__(self, *sub_anims, **kwargs): - digest_config(self, kwargs, locals()) sub_anims = filter (lambda x : not(x.empty), sub_anims) + digest_config(self, locals()) + self.update_config(**kwargs) # Handles propagation to self.sub_anims + if len(sub_anims) == 0: self.empty = True self.run_time = 0 else: - for anim in sub_anims: - # If AnimationGroup is called with any configuration, - # it is propagated to the sub_animations - anim.update_config(**kwargs) self.run_time = max([a.run_time for a in sub_anims]) everything = Mobject(*[a.mobject for a in sub_anims]) Animation.__init__(self, everything, **kwargs) @@ -527,6 +522,14 @@ class AnimationGroup(Animation): for anim in self.sub_anims: anim.clean_up(*args, **kwargs) + def update_config(self, **kwargs): + Animation.update_config(self, **kwargs) + + # If AnimationGroup is called with any configuration, + # it is propagated to the sub_animations + for anim in self.sub_anims: + anim.update_config(**kwargs) + class EmptyAnimation(Animation): CONFIG = { "run_time" : 0, @@ -535,4 +538,3 @@ class EmptyAnimation(Animation): def __init__(self, *args, **kwargs): return Animation.__init__(self, Group(), *args, **kwargs) - diff --git a/mobject/vectorized_mobject.py b/mobject/vectorized_mobject.py index a3ac3372..0b13a3bb 100644 --- a/mobject/vectorized_mobject.py +++ b/mobject/vectorized_mobject.py @@ -54,10 +54,14 @@ class VMobject(Mobject): if fill_opacity is not None: self.fill_opacity = fill_opacity if family: - kwargs = locals() - kwargs.pop("self") for mob in self.submobjects: - mob.set_style_data(**kwargs) + mob.set_style_data( + stroke_color = stroke_color, + stroke_width = stroke_width, + fill_color = fill_color, + fill_opacity = fill_opacity, + family = family + ) return self def set_fill(self, color = None, opacity = None, family = True): @@ -244,7 +248,6 @@ class VMobject(Mobject): a single "path", in the svg sense of the word. However, one such path may really consist of separate continuous components if there is a move_to command. - These other portions of the path will be treated as submobjects, but will be tracked in a separate special list for when it comes time to display. @@ -287,7 +290,6 @@ class VMobject(Mobject): If the distance between a given handle point H and its associated anchor point A is d, then it changes H to be a distances factor*d away from A, but so that the line from A to H doesn't change. - This is mostly useful in the context of applying a (differentiable) function, to preserve tangency properties. One would pull all the handles closer to their anchors, apply the function then push them out @@ -481,4 +483,3 @@ class VectorizedPoint(VMobject): def set_location(self,new_loc): self.set_points(np.array([new_loc])) - diff --git a/topics/number_line.py b/topics/number_line.py index 3848feba..cd8da287 100644 --- a/topics/number_line.py +++ b/topics/number_line.py @@ -222,6 +222,28 @@ class Axes(VGroup): return graph def input_to_graph_point(self, x, graph): + if hasattr(graph, "underlying_function"): + return self.coords_to_point(x, graph.underlying_function(x)) + else: + #binary search + lh, rh = 0, 1 + while abs(lh - rh) > 0.001: + mh = np.mean([lh, rh]) + hands = [lh, mh, rh] + points = map(graph.point_from_proportion, hands) + lx, mx, rx = map(self.x_axis.point_to_number, points) + if lx <= x and rx >= x: + if mx > x: + rh = mh + else: + lh = mh + elif lx <= x and rx <= x: + return points[2] + elif lx >= x and rx >= x: + return points[0] + elif lx > x and rx < x: + lh, rh = rh, lh + return points[1] return self.coords_to_point(x, graph.underlying_function(x)) class ThreeDAxes(Axes):