From afdb7554efa9889cbcb6eaadae88aec108affa5c Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Sat, 8 Aug 2015 20:42:34 -0700 Subject: [PATCH] Began reanimating much of inventing math. Also there is DelayByOrder now, which is awesome --- animation/animation.py | 21 ---- animation/simple_animations.py | 51 ++++++++++ sample_script.py | 21 ++-- scripts/inventing_math.py | 167 ++++++++++++++++++++----------- scripts/inventing_math_images.py | 20 ++++ 5 files changed, 188 insertions(+), 92 deletions(-) create mode 100644 scripts/inventing_math_images.py diff --git a/animation/animation.py b/animation/animation.py index d5e1dcd7..b6082ff2 100644 --- a/animation/animation.py +++ b/animation/animation.py @@ -111,27 +111,6 @@ class Animation(object): self.update(1) -class Succession(Animation): - def __init__(self, *animations, **kwargs): - if "run_time" in kwargs: - run_time = kwargs.pop("run_time") - else: - run_time = sum([anim.run_time for anim in animations]) - self.num_anims = len(animations) - self.anims = animations - mobject = animations[0].mobject - Animation.__init__(self, mobject, run_time = run_time, **kwargs) - - def __str__(self): - return self.__class__.__name__ + \ - "".join(map(str, self.anims)) - - def update(self, alpha): - scaled_alpha = alpha*self.num_anims - self.mobject = self.anims - for index in range(len(self.anims)): - self.anims[index].update(scaled_alpha - index) - diff --git a/animation/simple_animations.py b/animation/simple_animations.py index 74415ecb..5288a37b 100644 --- a/animation/simple_animations.py +++ b/animation/simple_animations.py @@ -8,6 +8,35 @@ from mobject import * from constants import * from helpers import * + +class DelayByOrder(Animation): + """ + Modifier of animation. + + Warning: This will not work on all animation types, but + when it does, it will be pretty cool + """ + def __init__(self, animation, max_power = 5, **kwargs): + self.animation = animation + self.max_power = max_power + kwargs = dict([ + (attr, getattr(animation, attr)) + for attr in "run_time", "alpha_func" + ]) + self.num_mobject_points = animation.mobject.get_num_points() + Animation.__init__(self, animation.mobject, **kwargs) + self.name = self.__class__.__name__ + str(self.animation) + + def update_mobject(self, alpha): + dim = self.mobject.DIM + alpha_array = np.array([ + [alpha**power]*dim + for n in range(self.num_mobject_points) + for prop in [(n+1.0)/self.num_mobject_points] + for power in [1+prop*(self.max_power-1)] + ]) + self.animation.update_mobject(alpha_array) + class Rotating(Animation): def __init__(self, mobject, @@ -60,6 +89,7 @@ class FadeIn(Animation): self.mobject.points = self.starting_mobject.points #TODO, Why do you need to do this? Shouldn't points always align? + class ShowCreation(Animation): def update_mobject(self, alpha): #TODO, shoudl I make this more efficient? @@ -131,6 +161,27 @@ class ComplexHomotopy(Homotopy): self.name = "ComplexHomotopy" + \ to_cammel_case(complex_homotopy.__name__) +class Succession(Animation): + def __init__(self, *animations, **kwargs): + if "run_time" in kwargs: + run_time = kwargs.pop("run_time") + else: + run_time = sum([anim.run_time for anim in animations]) + self.num_anims = len(animations) + self.anims = animations + mobject = animations[0].mobject + Animation.__init__(self, mobject, run_time = run_time, **kwargs) + + def __str__(self): + return self.__class__.__name__ + \ + "".join(map(str, self.anims)) + + def update(self, alpha): + scaled_alpha = alpha*self.num_anims + self.mobject = self.anims + for index in range(len(self.anims)): + self.anims[index].update(scaled_alpha - index) + ####### Pi Creature Stuff ############# diff --git a/sample_script.py b/sample_script.py index bd3f34c8..102aeb65 100644 --- a/sample_script.py +++ b/sample_script.py @@ -16,18 +16,15 @@ from script_wrapper import command_line_create_scene class SampleScene(RearrangeEquation): def construct(self): - start_terms = "a + b = c".split(" ") - end_terms = "a = c - b + 0".split(" ") - index_map = { - 0 : 0, - 1 : 3, - 2 : 4, - 3 : 1, - 4 : 2, - } - RearrangeEquation.construct( - self, start_terms, end_terms, index_map - ) + dot = Dot().shift(UP) + self.add(dot) + self.dither() + self.animate(DelayByOrder(Transform( + dot, + Line(DOWN, UP) + ))) + self.dither() + diff --git a/scripts/inventing_math.py b/scripts/inventing_math.py index 16990af3..77893e4d 100644 --- a/scripts/inventing_math.py +++ b/scripts/inventing_math.py @@ -15,6 +15,8 @@ from region import * from scene import Scene, RearrangeEquation from script_wrapper import command_line_create_scene +from inventing_math_images import * + MOVIE_PREFIX = "inventing_math/" DIVERGENT_SUM_TEXT = [ "1", @@ -152,7 +154,10 @@ class IntroduceDivergentSum(Scene): def construct(self): equation = divergent_sum().split() sum_value = None - brace = underbrace().shift(0.75*DOWN) + brace = underbrace( + equation[0].get_border_point(DOWN+LEFT), + equation[1].get_border_point(DOWN+RIGHT) + ).shift(0.2*DOWN) min_x_coord = min(equation[0].points[:,0]) for x in range(NUM_WRITTEN_TERMS): self.add(equation[x]) @@ -180,7 +185,7 @@ class IntroduceDivergentSum(Scene): flip_through = FlipThroughNumbers( lambda x : 2**(x+1)-1, start = NUM_WRITTEN_TERMS-1, - end = 40, + end = 50, start_center = brace.get_center() + 0.5*DOWN, end_center = end_brace.get_center() + 0.5*DOWN, **kwargs @@ -190,17 +195,8 @@ class IntroduceDivergentSum(Scene): Transform(brace, end_brace, **kwargs), flip_through, ) - kwargs = {"run_time" : 0.5, "alpha_func" : rush_from} self.clear() - self.add(CompoundMobject(*equation[:-1])) - self.animate( - Transform( - flip_through.mobject, - equation[-1], - **kwargs - ), - FadeOut(brace, **kwargs), - ) + self.add(*equation) self.dither() class ClearlyNonsense(Scene): @@ -237,57 +233,110 @@ class ClearlyNonsense(Scene): self.animate(ShowCreation(right_arrow)) self.dither() -class ReasonsForMakingVideo(Scene): +class OutlineOfVideo(Scene): def construct(self): - text = text_mobject([ - """ - \\begin{itemize} - \\item Understand what ``$ - """, - "".join(DIVERGENT_SUM_TEXT), - """ - $'' is saying. - """, - """ - \\item Nonsense-Driven Construction - \\end{itemize} - """ - ], size = "\\Small") - text.scale(1.5).to_edge(LEFT).shift(UP).highlight("white") - text.highlight("green", lambda (x, y, z) : x < -SPACE_WIDTH + 1) - line_one_first, equation, line_one_last, line_two = text.split() - line_two.shift(2*DOWN) - div_sum = divergent_sum().scale(0.5).shift(3*UP) - - self.add(div_sum) - self.animate( - ApplyMethod(div_sum.replace, equation), - FadeIn(line_one_first), - FadeIn(line_one_last) + conv_sum = convergent_sum().scale(0.5) + div_sum = divergent_sum().scale(0.5) + overbrace = underbrace( + conv_sum.get_left(), + conv_sum.get_right() + ).rotate(np.pi, RIGHT).shift(0.75*UP*conv_sum.get_height()) + dots = conv_sum.split()[-2].highlight("green") + dots.sort_points() + arrow = Arrow( + dots.get_bottom(), + direction = UP+LEFT ) - self.dither() - self.add(line_two) - self.dither() + u_brace = underbrace(div_sum.get_left(), div_sum.get_right()) + u_brace.shift(1.5*div_sum.get_bottom()) + for mob in conv_sum, overbrace, arrow, dots: + mob.shift(2*UP) + for mob in div_sum, u_brace: + mob.shift(DOWN) + texts = [ + text_mobject(words).highlight("yellow") + for words in [ + "1. Discover this", + "2. Clarify what this means", + "3. Discover this", + ["4. Invent ", "\\textbf{new math}"] + ] + ] + last_one_split = texts[-1].split() + last_one_split[1].highlight("skyblue") + texts[-1] = CompoundMobject(*last_one_split) + texts[0].shift(overbrace.get_top()+texts[0].get_height()*UP) + texts[1].shift(sum([ + arrow.get_border_point(DOWN+RIGHT), + texts[1].get_height()*DOWN + ])) + texts[2].shift(u_brace.get_bottom()+texts[3].get_height()*DOWN) + texts[3].to_edge(DOWN) -class DiscoverAndDefine(Scene): - def construct(self): - sum_mob = tex_mobject("\\sum_{n = 1}^\\infty a_n") - discover = text_mobject("What does it feel like to discover these?") - define = text_mobject([ - "What does it feel like to", - "\\emph{define} ", - "them?" - ]) - sum_mob.shift(2*UP) - define.shift(2*DOWN) - define_parts = define.split() - define_parts[1].highlight("skyblue") + groups = [ + [texts[0], overbrace, conv_sum], + [texts[1], arrow, dots], + [texts[2], u_brace, div_sum], + [texts[3]] + ] + for group in groups: + self.animate(*[ + DelayByOrder(FadeIn(element)) + for element in group + ]) + self.dither() - self.add(sum_mob) - self.animate(FadeIn(discover)) - self.dither() - self.animate(FadeIn(CompoundMobject(*define_parts))) - self.dither() +# # class ReasonsForMakingVideo(Scene): +# # def construct(self): +# # text = text_mobject([ +# # """ +# # \\begin{itemize} +# # \\item Understand what ``$ +# # """, +# # "".join(DIVERGENT_SUM_TEXT), +# # """ +# # $'' is saying. +# # """, +# # """ +# # \\item Nonsense-Driven Construction +# # \\end{itemize} +# # """ +# # ], size = "\\Small") +# # text.scale(1.5).to_edge(LEFT).shift(UP).highlight("white") +# # text.highlight("green", lambda (x, y, z) : x < -SPACE_WIDTH + 1) +# # line_one_first, equation, line_one_last, line_two = text.split() +# # line_two.shift(2*DOWN) +# # div_sum = divergent_sum().scale(0.5).shift(3*UP) + +# # self.add(div_sum) +# # self.animate( +# # ApplyMethod(div_sum.replace, equation), +# # FadeIn(line_one_first), +# # FadeIn(line_one_last) +# # ) +# # self.dither() +# # self.add(line_two) +# # self.dither() + +# class DiscoverAndDefine(Scene): +# def construct(self): +# sum_mob = tex_mobject("\\sum_{n = 1}^\\infty a_n") +# discover = text_mobject("What does it feel like to discover these?") +# define = text_mobject([ +# "What does it feel like to", +# "\\emph{define} ", +# "them?" +# ]) +# sum_mob.shift(2*UP) +# define.shift(2*DOWN) +# define_parts = define.split() +# define_parts[1].highlight("skyblue") + +# self.add(sum_mob) +# self.animate(FadeIn(discover)) +# self.dither() +# self.animate(FadeIn(CompoundMobject(*define_parts))) +# self.dither() class YouAsMathematician(Scene): def construct(self): diff --git a/scripts/inventing_math_images.py b/scripts/inventing_math_images.py new file mode 100644 index 00000000..de1014c8 --- /dev/null +++ b/scripts/inventing_math_images.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import numpy as np +import itertools as it +from copy import deepcopy +import sys + + +from animation import * +from mobject import * +from constants import * +from region import * +from scene import Scene +from script_wrapper import command_line_create_scene + + +class BuildFromTheStart(Scene): + def construct(self): + self.add(text_mobject("Build from the start...")) +