More music_and_measure, animate->play, making NumberLine better

This commit is contained in:
Grant Sanderson
2015-09-25 19:43:53 -07:00
parent 9045af276e
commit 8f2a8f032e
19 changed files with 908 additions and 380 deletions

View File

@@ -27,7 +27,6 @@ class Animation(object):
raise Exception("Invalid mobject parameter, must be \
subclass or instance of Mobject")
self.starting_mobject = copy.deepcopy(self.mobject)
self.reference_mobjects = [self.starting_mobject]
self.alpha_func = alpha_func or (lambda x : x)
self.run_time = run_time
#TODO, Adress the idea of filtering the animation
@@ -36,6 +35,7 @@ class Animation(object):
self.restricted_width = SPACE_WIDTH
self.spacial_center = np.zeros(3)
self.name = name or self.__class__.__name__ + str(self.mobject)
self.update(0)
def __str__(self):
return self.name

View File

@@ -187,7 +187,6 @@ class Succession(Animation):
for index in range(len(self.anims)):
self.anims[index].update(scaled_alpha - index)
####### Pi Creature Stuff #############
class WalkPiCreature(Animation):

View File

@@ -39,25 +39,27 @@ class Transform(Animation):
self.interpolation_function = interpolation_function
count1, count2 = mobject1.get_num_points(), mobject2.get_num_points()
if count2 == 0:
mobject2.add_points([(SPACE_WIDTH, SPACE_HEIGHT, 0)])
mobject2.add_points([SPACE_WIDTH*RIGHT+SPACE_HEIGHT*UP])
count2 = mobject2.get_num_points()
Mobject.align_data(mobject1, mobject2)
Animation.__init__(self, mobject1, run_time = run_time, *args, **kwargs)
self.ending_mobject = mobject2
if black_out_extra_points and count2 < count1:
self.black_out_extra_points(count1, count2)
Animation.__init__(self, mobject1, run_time = run_time, *args, **kwargs)
self.name += "To" + str(mobject2)
self.mobject.SHOULD_BUFF_POINTS = \
mobject1.SHOULD_BUFF_POINTS and mobject2.SHOULD_BUFF_POINTS
self.reference_mobjects.append(mobject2)
self.name += "To" + str(mobject2)
if black_out_extra_points and count2 < count1:
#Ensure redundant pixels fade to black
indices = np.arange(
0, count1-1, float(count1) / count2
).astype('int')
temp = np.zeros(mobject2.points.shape)
temp[indices] = mobject2.rgbs[indices]
mobject2.rgbs = temp
self.non_redundant_m2_indices = indices
def black_out_extra_points(self, count1, count2):
#Ensure redundant pixels fade to black
indices = np.arange(
0, count1-1, float(count1) / count2
).astype('int')
temp = np.zeros(self.ending_mobject.points.shape)
temp[indices] = self.ending_mobject.rgbs[indices]
self.ending_mobject.rgbs = temp
self.non_redundant_m2_indices = indices
def update_mobject(self, alpha):
self.mobject.points = self.interpolation_function(

View File

@@ -55,9 +55,9 @@ class PiCreature(CompoundMobject):
CompoundMobject.__init__(self, *self.get_parts())
return self
def TODO_what_should_I_do_with_this(self):
for part_name, mob in zip(self.part_names, self.split()):
setattr(self, part_name, mob)
# def TODO_what_should_I_do_with_this(self):
# for part_name, mob in zip(self.part_names, self.split()):
# setattr(self, part_name, mob)
def get_parts(self):

View File

@@ -92,27 +92,48 @@ class Grid(Mobject1D):
class NumberLine(Mobject1D):
def __init__(self,
radius = SPACE_WIDTH+1,
interval_size = 0.5, tick_size = 0.1,
*args, **kwargs):
self.radius = int(radius)
self.interval_size = interval_size
radius = SPACE_WIDTH,
unit_length_to_spacial_width = 1,
tick_size = 0.1,
tick_frequency = 0.5,
number_at_center = 0,
numbers_with_elongated_ticks = [0],
longer_tick_multiple = 2,
**kwargs):
#TODO, There must be better (but still safe) way to add all
#these config arguments as attributes.
self.radius = radius
self.unit_length_to_spacial_width = unit_length_to_spacial_width
self.tick_size = tick_size
Mobject1D.__init__(self, *args, **kwargs)
self.tick_frequency = tick_frequency
self.numbers_with_elongated_ticks = numbers_with_elongated_ticks
self.number_at_center = number_at_center
self.longer_tick_multiple = longer_tick_multiple
numerical_radius = float(radius) / unit_length_to_spacial_width
self.left_num = number_at_center - numerical_radius
self.right_num = number_at_center + numerical_radius
Mobject1D.__init__(self, **kwargs)
def generate_points(self):
self.add_points([
(x, 0, 0)
for x in np.arange(-self.radius, self.radius, self.epsilon)
(b*x, 0, 0)
for x in np.arange(0, self.radius, self.epsilon)
for b in [-1, 1]
])
self.index_of_left = np.argmin(self.points[:,0])
self.index_of_right = np.argmax(self.points[:,0])
spacial_tick_frequency = self.tick_frequency*self.unit_length_to_spacial_width
self.add_points([
(x, y, 0)
for x in np.arange(-self.radius, self.radius, self.interval_size)
(b*x, y, 0)
for x in np.arange(0, self.radius, spacial_tick_frequency)
for y in np.arange(-self.tick_size, self.tick_size, self.epsilon)
for b in ([1, -1] if x > 0 else [1])
])
self.elongate_tick_at(0)
for number in self.numbers_with_elongated_ticks:
self.elongate_tick_at(number, self.longer_tick_multiple)
def elongate_tick_at(self, x, multiple = 2):
def elongate_tick_at(self, number, multiple = 2):
x = self.number_to_point(number)[0]
self.add_points([
[x, y, 0]
for y in np.arange(
@@ -123,17 +144,37 @@ class NumberLine(Mobject1D):
])
return self
def add_numbers(self, intervals_per_number = 2):
max_val = int(self.radius/self.interval_size/intervals_per_number)
for x in range(-max_val, max_val+1):
num = tex_mobject(str(x)).scale(0.5)
num.shift(
DOWN*4*self.tick_size + \
RIGHT*x*self.interval_size*intervals_per_number
)
self.add(num)
def number_to_point(self, number):
return interpolate(
self.points[self.index_of_left],
self.points[self.index_of_right],
float(number-self.left_num)/(self.right_num - self.left_num)
)
def add_numbers(self, *numbers):
if len(numbers) == 0:
numbers = range(int(self.left_num), int(self.right_num+1))
for number in numbers:
mob = tex_mobject(str(number)).scale(0.5)
mob.shift(self.number_to_point(number))
mob.shift(DOWN*4*self.tick_size)
self.add(mob)
return self
class UnitInterval(NumberLine):
DEFAULT_CONFIG = {
"radius" : SPACE_WIDTH-1,
"unit_length_to_spacial_width" : 2*(SPACE_WIDTH-1),
"tick_frequency" : 0.1,
"number_at_center" : 0.5,
"numbers_with_elongated_ticks" : [0, 1],
}
def __init__(self, **kwargs):
config = self.DEFAULT_CONFIG
config.update(kwargs)
NumberLine.__init__(self, **config)
class Axes(CompoundMobject):
def __init__(self, *args, **kwargs):
x_axis = NumberLine(*args, **kwargs)

View File

@@ -21,6 +21,7 @@ class Mobject(object):
DEFAULT_COLOR = Color("skyblue")
SHOULD_BUFF_POINTS = GENERALLY_BUFF_POINTS
EDGE_BUFFER = 0.5
NEXT_TO_BUFFER = 0.2
def __init__(self,
color = None,
@@ -152,12 +153,17 @@ class Mobject(object):
self.shift(shift_val)
return self
def next_to(self, mobject, direction = RIGHT, buff = EDGE_BUFFER):
self.shift(
mobject.get_edge_center(direction) - \
self.get_edge_center(-direction) + \
buff * direction
)
def next_to(self, mobject,
direction = RIGHT,
buff = NEXT_TO_BUFFER,
aligned_edge = None):
if aligned_edge is not None:
anchor_point = self.get_corner(aligned_edge-direction)
target_point = mobject.get_corner(aligned_edge+direction)
else:
anchor_point = self.get_edge_center(-direction)
target_point = mobject.get_edge_center(direction)
self.shift(target_point - anchor_point + buff*direction)
return self
def scale(self, scale_factor):
@@ -225,8 +231,16 @@ class Mobject(object):
self.rgbs[:,:] = rgb
return self
def to_original_color(self):
self.highlight(self.color)
return self
def fade_to(self, color, alpha):
self.rgbs = interpolate(self.rgbs, Color(color).rgb, alpha)
return self
def fade(self, brightness = 0.5):
self.rgbs *= brightness
self.fade_to("black", brightness)
return self
def filter_out(self, condition):
@@ -268,6 +282,13 @@ class Mobject(object):
result[dim] = max_or_min_func(self.points[:,dim])
return result
def get_corner(self, direction):
return sum([
self.get_edge_center(RIGHT*direction[0]),
self.get_edge_center(UP*direction[1]),
-self.get_center()
])
def get_top(self):
return self.get_edge_center(UP)

View File

@@ -102,7 +102,7 @@ class Arrow(Line):
def add_tip(self, tip_length):
vect = self.start-self.end
vect *= tip_length/np.linalg.norm(vect)
vect = vect*tip_length/np.linalg.norm(vect)
self.add_points([
interpolate(self.end, self.end+v, t)
for t in np.arange(0, 1, tip_length*self.epsilon)
@@ -217,8 +217,8 @@ class Bubble(Mobject):
return self
class SpeechBubble(Bubble):
INITIAL_WIDTH = 6
INITIAL_HEIGHT = 4
INITIAL_WIDTH = 4
INITIAL_HEIGHT = 2
def __init__(self, *args, **kwargs):
Mobject.__init__(self, *args, **kwargs)
complex_power = 0.9

View File

@@ -56,7 +56,7 @@ class RearrangeEquation(Scene):
if leave_start_terms:
self.add(CompoundMobject(*start_mobs))
self.dither()
self.animate(*[
self.play(*[
Transform(*pair, **transform_kwargs)
for pair in mobject_pairs
])

View File

@@ -52,7 +52,7 @@ class CountingScene(Scene):
self.dither(frame_time)
mob.highlight(original_color)
if mode == "show_creation":
self.animate(ShowCreation(mob, run_time = frame_time))
self.play(ShowCreation(mob, run_time = frame_time))
if mode == "show":
self.add(mob)
self.dither(frame_time)

View File

@@ -220,10 +220,10 @@ class GraphScene(Scene):
def draw_vertices(self, **kwargs):
self.clear()
self.animate(ShowCreation(CompoundMobject(*self.vertices), **kwargs))
self.play(ShowCreation(CompoundMobject(*self.vertices), **kwargs))
def draw_edges(self):
self.animate(*[
self.play(*[
ShowCreation(edge, run_time = 1.0)
for edge in self.edges
])
@@ -235,7 +235,7 @@ class GraphScene(Scene):
Dot(point, radius = 3*Dot.DEFAULT_RADIUS, color = "lightgreen")
for point in self.points
])
self.animate(Transform(
self.play(Transform(
start, end, alpha_func = there_and_back,
**kwargs
))
@@ -246,7 +246,7 @@ class GraphScene(Scene):
def replace_vertices_with(self, mobject):
mobject.center()
diameter = max(mobject.get_height(), mobject.get_width())
self.animate(*[
self.play(*[
CounterclockwiseTransform(
vertex,
deepcopy(mobject).shift(vertex.get_center())
@@ -267,7 +267,7 @@ class GraphScene(Scene):
for angle, edge in zip(angles, self.edges)
]
if fade_in:
self.animate(*[
self.play(*[
FadeIn(ann, **kwargs)
for ann in self.edge_annotations
])
@@ -282,7 +282,7 @@ class GraphScene(Scene):
Line(self.points[i], self.points[j]).highlight(color)
for i, j in zip(cycle, next_in_cycle)
])
self.animate(
self.play(
ShowCreation(self.traced_cycle),
run_time = run_time
)

15
scene/number_line.py Normal file
View File

@@ -0,0 +1,15 @@
import numpy as np
import itertools as it
from scene import Scene
from mobject import *
from animation import *
from region import *
from constants import *
from helpers import *
class NumberLineScene(Scene):
def construct(self):
pass

View File

@@ -98,7 +98,7 @@ class Scene(object):
self.background = self.original_background
return self
def animate(self, *animations, **kwargs):
def play(self, *animations, **kwargs):
if "run_time" in kwargs:
run_time = kwargs["run_time"]
else:
@@ -127,7 +127,7 @@ class Scene(object):
progress_bar.finish()
return self
def animate_over_time_range(self, t0, t1, *animations):
def play_over_time_range(self, t0, t1, *animations):
needed_scene_time = max(abs(t0), abs(t1))
existing_scene_time = len(self.frames)*self.frame_duration
if existing_scene_time < needed_scene_time:

View File

@@ -235,7 +235,7 @@ class Introduction(Scene):
self.add(words)
self.dither()
self.animate(DelayByOrder(Transform(words, hand)))
self.play(DelayByOrder(Transform(words, hand)))
self.dither()
@@ -261,9 +261,9 @@ class ShowReadingRule(Scene):
self.add(answer[0])
counts = map(finger_tip_power_of_2, range(5))
for count in counts:
self.animate(SpinInFromNothing(count, run_time = 0.3))
self.play(SpinInFromNothing(count, run_time = 0.3))
self.dither()
self.animate(ShimmerIn(answer[1]))
self.play(ShimmerIn(answer[1]))
for count in sample_counts:
self.clear()
self.add(*answer)
@@ -283,7 +283,7 @@ class ShowReadingRule(Scene):
).to_corner(UP+RIGHT).split()
self.add(hand, *count_mobs)
self.dither()
self.animate(*[
self.play(*[
Transform(count_mobs[n/2], sum_mobs[n])
if n%2 == 0 and n/2 < len(counts)
else FadeIn(sum_mobs[n])
@@ -325,7 +325,7 @@ class ShowIncrementRule(Scene):
if pause:
self.background = oh.frames[COUNT_TO_FRAME_NUM[start]]
self.add(phrase)
self.animate(ShimmerIn(self.get_arrow_set(start)))
self.play(ShimmerIn(self.get_arrow_set(start)))
self.dither()
self.clear()
self.reset_background()
@@ -391,7 +391,7 @@ class MindFindsShortcuts(Scene):
seven
)
self.dither()
self.animate(
self.play(
Transform(compound, Arrow(hand, seven).highlight("yellow")),
ShimmerIn(text_mobject("Directly recognize").shift(1.5*DOWN+2*RIGHT))
)
@@ -413,7 +413,7 @@ class MindFindsShortcuts(Scene):
self.add(words2, hands[23])
self.dither()
self.animate(
self.play(
Transform(
deepcopy(hands[16]).highlight("black").center().shift(hands[23].get_center()),
hands[16]
@@ -427,7 +427,7 @@ class MindFindsShortcuts(Scene):
FadeIn(plus)
)
self.dither()
self.animate(ShimmerIn(equals23))
self.play(ShimmerIn(equals23))
self.dither()
@@ -452,7 +452,7 @@ class FinishCountingExampleSentence(Scene):
comp = CompoundMobject(sixteen, two)
self.add(hand, comp, words)
self.dither()
self.animate(Transform(comp, eightteen))
self.play(Transform(comp, eightteen))
self.dither()
class Question(Scene):
@@ -474,7 +474,7 @@ class WithToes(Scene):
]).split()
self.add(words[0])
self.dither()
self.animate(ShimmerIn(words[1]))
self.play(ShimmerIn(words[1]))
self.dither()

View File

@@ -48,7 +48,7 @@ class PreferOtherProofDialogue(Scene):
self.add(student, teacher, teacher_bubble, teacher_bubble.text)
self.dither(2)
self.animate(Transform(
self.play(Transform(
Dot(student_bubble.tip).highlight("black"),
CompoundMobject(student_bubble, student_bubble.text)
))
@@ -76,7 +76,7 @@ class IllustrateDuality(GraphScene):
"run_time" : 5.0,
"alpha_func" : special_alpha
}
self.animate(*[
self.play(*[
Transform(*edge_pair, **kwargs)
for edge_pair in zip(self.edges, self.dual_edges)
] + [
@@ -129,7 +129,7 @@ class IntroduceGraph(GraphScene):
"run_time" : 5.0
}
self.add(not_okay)
self.animate(*[
self.play(*[
Transform(*pair, **kwargs)
for pair in zip(
self.edges + self.vertices,
@@ -142,7 +142,7 @@ class IntroduceGraph(GraphScene):
self.remove(planar_explanation)
self.add(not_okay)
self.remove(*edges_to_remove)
self.animate(ShowCreation(
self.play(ShowCreation(
CompoundMobject(*edges_to_remove),
alpha_func = lambda t : 1 - t,
run_time = 1.0
@@ -164,7 +164,7 @@ class OldIntroduceGraphs(GraphScene):
self.replace_vertices_with(Face().scale(0.4))
friends = text_mobject("Friends").scale(EDGE_ANNOTATION_SCALE_VAL)
self.annotate_edges(friends.shift((0, friends.get_height()/2, 0)))
self.animate(*[
self.play(*[
CounterclockwiseTransform(vertex, Dot(point))
for vertex, point in zip(self.vertices, self.points)
]+[
@@ -195,7 +195,7 @@ class PlanarGraphDefinition(Scene):
self.add(quote, planar, end_quote)
self.dither()
self.animate(
self.play(
FadeOut(quote),
FadeOut(end_quote),
ApplyMethod(planar.shift, shift_val),
@@ -238,26 +238,26 @@ class TerminologyFromPolyhedra(GraphScene):
regions_to_faces = text_mobject("Regions $\\to$ Faces").to_corner()
self.clear()
# self.animate(TransformAnimations(
# self.play(TransformAnimations(
# Rotating(Dodecahedron(), **rot_kwargs),
# Rotating(cube, **rot_kwargs)
# ))
self.animate(Rotating(cube, **rot_kwargs))
self.play(Rotating(cube, **rot_kwargs))
self.clear()
self.animate(*[
self.play(*[
Transform(l1, l2)
for l1, l2 in zip(cube.split(), self.edges)
])
self.dither()
self.add(dots_to_vertices)
self.animate(*[
self.play(*[
ShowCreation(dot, run_time = 1.0)
for dot in self.vertices
])
self.dither(2)
self.remove(dots_to_vertices, *self.vertices)
self.add(lines_to_edges)
self.animate(ApplyMethod(
self.play(ApplyMethod(
CompoundMobject(*self.edges).highlight, "yellow"
))
self.dither(2)
@@ -295,7 +295,7 @@ class ThreePiecesOfTerminology(GraphScene):
self.remove(self.traced_cycle)
self.add(accent(spanning_trees))
self.animate(ShowCreation(self.spanning_tree), run_time = 1.0)
self.play(ShowCreation(self.spanning_tree), run_time = 1.0)
self.dither()
tone_down(spanning_trees)
self.remove(self.spanning_tree)
@@ -304,14 +304,14 @@ class ThreePiecesOfTerminology(GraphScene):
self.generate_dual_graph()
for mob in self.mobjects:
mob.fade
self.animate(*[
self.play(*[
ShowCreation(mob, run_time = 1.0)
for mob in self.dual_vertices + self.dual_edges
])
self.dither()
self.clear()
self.animate(ApplyMethod(
self.play(ApplyMethod(
CompoundMobject(*terms).center
))
self.dither()
@@ -335,7 +335,7 @@ class WalkingRandolph(GraphScene):
randy.scale(RANDOLPH_SCALE_VAL)
randy.move_to(point_path[0])
for next, last in zip(point_path[1:], point_path):
self.animate(
self.play(
WalkPiCreature(randy, next),
ShowCreation(Line(last, next).highlight("yellow")),
run_time = 2.0
@@ -378,13 +378,13 @@ class PathExamples(GraphScene):
self.remove(not_a_path)
self.add(valid_path)
self.animate(ShowCreation(path_lines, **kwargs))
self.play(ShowCreation(path_lines, **kwargs))
self.dither(2)
self.remove(path_lines)
self.remove(valid_path)
self.add(not_a_path)
self.animate(ShowCreation(non_path_lines, **kwargs))
self.play(ShowCreation(non_path_lines, **kwargs))
self.dither(2)
self.remove(non_path_lines)
@@ -414,7 +414,7 @@ class IntroduceRandolph(GraphScene):
GraphScene.construct(self)
randy = Randolph().move_to((-3, 0, 0))
name = text_mobject("Randolph")
self.animate(Transform(
self.play(Transform(
randy,
deepcopy(randy).scale(RANDOLPH_SCALE_VAL).move_to(self.points[0]),
))
@@ -454,19 +454,19 @@ class DefineSpanningTree(GraphScene):
self.dither(2)
self.remove(dollar_signs)
run_time_per_branch = 0.5
self.animate(
self.play(
ShowCreation(green_dot_at_index(0)),
run_time = run_time_per_branch
)
for pair in self.spanning_tree_index_pairs:
self.animate(ShowCreation(
self.play(ShowCreation(
Line(
self.points[pair[0]],
self.points[pair[1]]
).highlight("yellow"),
run_time = run_time_per_branch
))
self.animate(ShowCreation(
self.play(ShowCreation(
green_dot_at_index(pair[1]),
run_time = run_time_per_branch
))
@@ -476,7 +476,7 @@ class DefineSpanningTree(GraphScene):
for edge, limit in zip(unneeded_edges, range(5)):
line = Line(self.points[edge[0]], self.points[edge[1]])
line.highlight("red")
self.animate(ShowCreation(line, run_time = 1.0))
self.play(ShowCreation(line, run_time = 1.0))
self.add(unneeded.center().shift(line.get_center() + 0.2*UP))
self.dither()
self.remove(line, unneeded)
@@ -493,19 +493,19 @@ class NamingTree(GraphScene):
spanning_tree = text_mobject("``Spanning Tree''").to_edge(UP)
self.add(*branches)
self.animate(
self.play(
FadeOut(CompoundMobject(*self.edges + self.vertices)),
Animation(CompoundMobject(*branches)),
)
self.clear()
self.add(tree, *branches)
self.dither()
self.animate(*[
self.play(*[
Transform(b1, b2, run_time = 2)
for b1, b2 in zip(branches, treeified_branches)
])
self.dither()
self.animate(*[
self.play(*[
FadeIn(mob)
for mob in self.edges + self.vertices
] + [
@@ -522,7 +522,7 @@ class DualGraph(GraphScene):
GraphScene.construct(self)
self.generate_dual_graph()
self.add(text_mobject("Dual Graph").to_edge(UP).shift(2*LEFT))
self.animate(*[
self.play(*[
ShowCreation(mob)
for mob in self.dual_edges + self.dual_vertices
])
@@ -557,12 +557,12 @@ class FacebookGraph(GraphScene):
self.dither()
self.annotate_edges(friends)
self.dither()
self.animate(*[
self.play(*[
CounterclockwiseTransform(account, vertex)
for account, vertex in zip(accounts, self.vertices)
])
self.dither()
self.animate(*[
self.play(*[
Transform(ann, edge)
for ann, edge in zip(self.edge_annotations, self.edges)
])
@@ -607,7 +607,7 @@ class FacebookGraphAsAbstractSet(Scene):
self.add(accounts, friendships, lines)
self.dither()
for mob in names_mob, friends_mob:
self.animate(ShowCreation(
self.play(ShowCreation(
mob, run_time = 1.0
))
self.dither()
@@ -690,10 +690,10 @@ class ExamplesOfGraphs(GraphScene):
comp_words = CompoundMobject(*words)
comp_lines = CompoundMobject(*lines)
self.add(words1)
self.animate(ShowCreation(comp_words, run_time = 1.0))
self.play(ShowCreation(comp_words, run_time = 1.0))
self.dither()
self.add(words2)
self.animate(ShowCreation(comp_lines, run_time = 1.0))
self.play(ShowCreation(comp_lines, run_time = 1.0))
self.dither()
self.remove(comp_words, comp_lines)
@@ -708,7 +708,7 @@ class ExamplesOfGraphs(GraphScene):
for mob in connected, not_connected:
mob.shift(self.points[3] + UP)
self.animate(*[
self.play(*[
ShowCreation(mob, run_time = 1.0)
for mob in self.edges + self.vertices
])
@@ -745,7 +745,7 @@ class ExamplesOfGraphs(GraphScene):
tup = tuple(reversed(tup))
edge = deepcopy(self.edges[self.graph.edges.index(tup)])
edge.highlight("red")
self.animate(ShowCreation(edge), run_time = 1.0)
self.play(ShowCreation(edge), run_time = 1.0)
self.dither()
self.remove(edge)
else:
@@ -787,19 +787,19 @@ class DrawDualGraph(GraphScene):
self.dither()
self.reset_background()
self.highlight_region(outer_region, outer_region_mob.get_color())
self.animate(*[
self.play(*[
Transform(reg_mob, dot)
for reg_mob, dot in zip(region_mobs, self.dual_vertices)
])
self.dither()
self.reset_background()
self.animate(ApplyFunction(
self.play(ApplyFunction(
lambda p : (SPACE_WIDTH + SPACE_HEIGHT)*p/np.linalg.norm(p),
outer_region_mob
))
self.dither()
for edges in internal_edges, external_edges:
self.animate(*[
self.play(*[
ShowCreation(edge, run_time = 2.0)
for edge in edges
])
@@ -812,7 +812,7 @@ class EdgesAreTheSame(GraphScene):
self.remove(*self.vertices)
self.add(*self.dual_edges)
self.dither()
self.animate(*[
self.play(*[
Transform(*pair, run_time = 2.0)
for pair in zip(self.dual_edges, self.edges)
])
@@ -880,7 +880,7 @@ class CyclesCorrespondWithConnectedComponents(GraphScene):
for last, next in zip(cycle, cycle[1:]):
line = Line(self.points[last], self.points[next])
line.highlight("yellow")
self.animate(
self.play(
ShowCreation(line),
WalkPiCreature(randy, self.points[next]),
run_time = 1.0
@@ -896,8 +896,8 @@ class CyclesCorrespondWithConnectedComponents(GraphScene):
Line(self.dual_points[last], self.dual_points[next])
for last, next in zip(dual_cycle, dual_cycle[1:])
]).highlight("red")
self.animate(ShowCreation(lines))
self.animate(*[
self.play(ShowCreation(lines))
self.play(*[
Transform(v, Dot(
v.get_center(),
radius = 3*Dot.DEFAULT_RADIUS
@@ -937,7 +937,7 @@ class IntroduceMortimer(GraphScene):
small_morty = deepcopy(morty).scale(RANDOLPH_SCALE_VAL)
small_randy.move_to(self.points[randy_path[0]])
small_morty.move_to(self.dual_points[morty_path[0]])
self.animate(*[
self.play(*[
FadeIn(mob)
for mob in self.vertices + self.edges
] + [
@@ -949,19 +949,19 @@ class IntroduceMortimer(GraphScene):
self.highlight_region(self.regions[morty_path[0]])
for last, next in zip(morty_path, morty_path[1:]):
self.animate(WalkPiCreature(morty, self.dual_points[next]),**kwargs)
self.play(WalkPiCreature(morty, self.dual_points[next]),**kwargs)
self.highlight_region(self.regions[next])
self.dither()
for last, next in zip(randy_path, randy_path[1:]):
line = Line(self.points[last], self.points[next])
line.highlight("yellow")
self.animate(
self.play(
WalkPiCreature(randy, self.points[next]),
ShowCreation(line),
**kwargs
)
self.dither()
self.animate(*[
self.play(*[
ApplyMethod(
line.rotate_in_place,
np.pi/10,
@@ -988,9 +988,9 @@ class RandolphMortimerSpanningTreeGame(GraphScene):
time_per_dual_edge = 0.5
self.add(randy, morty)
self.animate(ShowCreation(self.spanning_tree))
self.play(ShowCreation(self.spanning_tree))
self.dither()
self.animate(WalkPiCreature(
self.play(WalkPiCreature(
morty, self.dual_points[attempted_dual_point_index],
alpha_func = lambda t : 0.3 * there_and_back(t),
run_time = 2.0,
@@ -1000,7 +1000,7 @@ class RandolphMortimerSpanningTreeGame(GraphScene):
# if index > 0:
# edge = self.edges[dual_edges[index-1]]
# midpoint = edge.get_center()
# self.animate(*[
# self.play(*[
# ShowCreation(Line(
# midpoint,
# tip
@@ -1015,7 +1015,7 @@ class RandolphMortimerSpanningTreeGame(GraphScene):
cycle_index = region_ordering[-1]
cycle = self.graph.region_cycles[cycle_index]
self.highlight_region(self.regions[cycle_index], "black")
self.animate(ShowCreation(CompoundMobject(*[
self.play(ShowCreation(CompoundMobject(*[
Line(self.points[last], self.points[next]).highlight("green")
for last, next in zip(cycle, list(cycle)[1:] + [cycle[0]])
])))
@@ -1043,7 +1043,7 @@ class MortimerCannotTraverseCycle(GraphScene):
for last, next in zip(dual_cycle, dual_cycle[1:]):
line = Line(self.dual_points[last], self.dual_points[next])
line.highlight("red")
self.animate(
self.play(
WalkPiCreature(morty, self.dual_points[next], **kwargs),
ShowCreation(line, **kwargs),
)
@@ -1056,7 +1056,7 @@ class MortimerCannotTraverseCycle(GraphScene):
matching_edges.append(
self.edges[distances.index(min(distances))]
)
self.animate(*[
self.play(*[
Transform(v, Dot(
v.get_center(),
radius = 3*Dot.DEFAULT_RADIUS,
@@ -1065,7 +1065,7 @@ class MortimerCannotTraverseCycle(GraphScene):
for v in np.array(self.vertices)[trapped_points]
])
self.add(text)
self.animate(*[
self.play(*[
Transform(line, deepcopy(edge).highlight(line.get_color()))
for line, edge in zip(all_lines, matching_edges)
])
@@ -1095,7 +1095,7 @@ class TwoPropertiesOfSpanningTree(Scene):
explanation.get_center() + vect,
tail = word.get_center() - vect,
))
self.animate(ApplyMethod(word.highlight, "yellow"))
self.play(ApplyMethod(word.highlight, "yellow"))
self.dither()
@@ -1116,7 +1116,7 @@ class DualSpanningTree(GraphScene):
""").to_edge(UP)
self.add(self.spanning_tree, randy, morty)
self.animate(ShowCreation(CompoundMobject(
self.play(ShowCreation(CompoundMobject(
*np.array(self.edges)[dual_edges]
).highlight("red")))
self.add(words)
@@ -1136,7 +1136,7 @@ class TreeCountFormula(Scene):
all_dots = [Dot(branches[0].points[0])]
self.add(text, all_dots[0])
for branch in branches:
self.animate(
self.play(
ShowCreation(branch),
run_time = time_per_branch
)
@@ -1145,7 +1145,7 @@ class TreeCountFormula(Scene):
all_dots.append(dot)
self.dither()
self.remove(*all_dots)
self.animate(
self.play(
FadeOut(text),
FadeIn(CompoundMobject(*gs.edges + gs.vertices)),
*[
@@ -1178,7 +1178,7 @@ class FinalSum(Scene):
copy.scale_in_place(lines[index].get_width()/mob.get_width())
anims.append(CounterclockwiseTransform(copy, mob))
self.clear()
self.animate(*anims, run_time = 2.0)
self.play(*anims, run_time = 2.0)
self.dither()

View File

@@ -52,7 +52,7 @@ class LogoGeneration(Scene):
name.highlight("grey")
name.shift(2*DOWN)
self.animate(Transform(
self.play(Transform(
circle, iris,
run_time = DEFAULT_ANIMATION_RUN_TIME
))

View File

@@ -15,7 +15,7 @@ from region import *
from scene import Scene, RearrangeEquation
from script_wrapper import command_line_create_scene
from inventing_math_images import *
# from inventing_math_images import *
MOVIE_PREFIX = "inventing_math/"
DIVERGENT_SUM_TEXT = [
@@ -191,7 +191,7 @@ class IntroduceDivergentSum(Scene):
**kwargs
)
self.add(ellipses)
self.animate(
self.play(
Transform(brace, end_brace, **kwargs),
flip_through,
)
@@ -220,17 +220,17 @@ class ClearlyNonsense(Scene):
this_way.highlight("yellow")
right_arrow.highlight("yellow")
self.animate(Transform(
self.play(Transform(
div_sum,
deepcopy(div_sum).scale(0.5).shift(3*UP)
))
self.animate(ShowCreation(number_line))
self.play(ShowCreation(number_line))
self.dither()
self.add(how_here)
self.animate(ShowCreation(neg_1_arrow))
self.play(ShowCreation(neg_1_arrow))
self.dither()
self.add(this_way)
self.animate(ShowCreation(right_arrow))
self.play(ShowCreation(right_arrow))
self.dither()
class OutlineOfVideo(Scene):
@@ -280,7 +280,7 @@ class OutlineOfVideo(Scene):
[texts[3]]
]
for group in groups:
self.animate(*[
self.play(*[
DelayByOrder(FadeIn(element))
for element in group
])
@@ -309,7 +309,7 @@ class OutlineOfVideo(Scene):
# # div_sum = divergent_sum().scale(0.5).shift(3*UP)
# # self.add(div_sum)
# # self.animate(
# # self.play(
# # ApplyMethod(div_sum.replace, equation),
# # FadeIn(line_one_first),
# # FadeIn(line_one_last)
@@ -333,9 +333,9 @@ class OutlineOfVideo(Scene):
# define_parts[1].highlight("skyblue")
# self.add(sum_mob)
# self.animate(FadeIn(discover))
# self.play(FadeIn(discover))
# self.dither()
# self.animate(FadeIn(CompoundMobject(*define_parts)))
# self.play(FadeIn(CompoundMobject(*define_parts)))
# self.dither()
class YouAsMathematician(Scene):
@@ -359,16 +359,16 @@ class YouAsMathematician(Scene):
for x in LEFT, RIGHT
]
self.add(you, explanation)
self.animate(
self.play(
ShowCreation(arrow),
BlinkPiCreature(you)
)
self.dither()
self.animate(ShowCreation(bubble))
self.play(ShowCreation(bubble))
for part in equation_parts:
self.animate(DelayByOrder(FadeIn(part)), run_time = 0.5)
self.play(DelayByOrder(FadeIn(part)), run_time = 0.5)
self.dither()
self.animate(
self.play(
BlinkPiCreature(you),
FadeOut(explanation),
FadeOut(arrow)
@@ -376,19 +376,19 @@ class YouAsMathematician(Scene):
self.remove(bubble, *equation_parts)
self.disapproving_friend()
self.add(bubble, equation)
self.animate(Transform(equation, CompoundMobject(*dot_pair)))
self.play(Transform(equation, CompoundMobject(*dot_pair)))
self.remove(equation)
self.add(*dot_pair)
two_arrows = [
Arrow(x, direction = x).shift(UP).nudge()
for x in LEFT, RIGHT
]
self.animate(*[ShowCreation(a) for a in two_arrows])
self.animate(BlinkPiCreature(you))
self.play(*[ShowCreation(a) for a in two_arrows])
self.play(BlinkPiCreature(you))
self.remove(*dot_pair+two_arrows)
everything = CompoundMobject(*self.mobjects)
self.clear()
self.animate(
self.play(
ApplyPointwiseFunction(
lambda p : 3*SPACE_WIDTH*p/np.linalg.norm(p),
everything
@@ -408,7 +408,7 @@ class YouAsMathematician(Scene):
bubble.content.sort_points(lambda p : np.dot(p, DOWN+RIGHT))
self.add(friend, bubble)
self.animate(DelayByOrder(FadeIn(bubble.content)))
self.play(DelayByOrder(FadeIn(bubble.content)))
self.dither()
self.remove(friend, bubble, bubble.content)
@@ -423,7 +423,7 @@ class DotsGettingCloser(Scene):
self.dither()
for x in range(10):
distance = min(dots[1].points[:,0])-max(dots[0].points[:,0])
self.animate(ApplyMethod(dots[0].shift, 0.5*distance*RIGHT))
self.play(ApplyMethod(dots[0].shift, 0.5*distance*RIGHT))
class ZoomInOnInterval(Scene):
@@ -441,10 +441,10 @@ class ZoomInOnInterval(Scene):
self.add(number_line)
self.dither()
self.animate(Transform(number_line, new_line))
self.play(Transform(number_line, new_line))
self.clear()
squish = lambda p : (p[0], 0, 0)
self.animate(
self.play(
ApplyMethod(new_line.apply_function, squish),
ApplyMethod(
interval[0].apply_function, squish,
@@ -476,7 +476,7 @@ class DanceDotOnInterval(Scene):
conv_sum = tex_mobject(sum_terms, size = "\\large").split()
self.add(interval)
self.animate(*[
self.play(*[
ApplyMethod(dot.shift, DOWN)
for dot in dots
])
@@ -486,7 +486,7 @@ class DanceDotOnInterval(Scene):
start = dots[0].get_center()
line = Line(start, start + shift_val*RIGHT)
line.highlight(color_range.next())
self.animate(
self.play(
ApplyMethod(dots[0].shift, shift_val),
ShowCreation(line)
)
@@ -500,7 +500,7 @@ class DanceDotOnInterval(Scene):
line.get_center()+2*DOWN,
tail = num.get_center()+0.5*num.get_height()*UP
)
self.animate(
self.play(
ApplyMethod(line.shift, 2*DOWN),
FadeIn(num),
FadeIn(arrow),
@@ -517,7 +517,7 @@ class DanceDotOnInterval(Scene):
for x in range(0, len(partial_sum_parts), 4):
partial_sum_parts[x+2].highlight("yellow")
self.animate(*[
self.play(*[
FadeIn(partial_sum_parts[y])
for y in range(x, x+4)
])
@@ -541,7 +541,7 @@ class OrganizePartialSums(Scene):
self.add(*partial_sum_parts)
self.dither()
self.animate(*[
self.play(*[
ClockwiseTransform(*pair)
for pair in zip(pure_sums, new_pure_sums)
]+[
@@ -557,9 +557,9 @@ class OrganizePartialSums(Scene):
infinite_sum.scale(1.5/1.25)
infinite_sum.to_corner(DOWN+LEFT).shift(2*RIGHT)
self.animate(ShowCreation(dots))
self.play(ShowCreation(dots))
self.dither()
self.animate(FadeIn(CompoundMobject(down_arrow, infinite_sum)))
self.play(FadeIn(CompoundMobject(down_arrow, infinite_sum)))
self.dither()
class SeeNumbersApproachOne(Scene):
@@ -580,7 +580,7 @@ class SeeNumbersApproachOne(Scene):
])
self.add(interval)
self.animate(
self.play(
ShowCreation(arrow),
ShowCreation(dots),
run_time = 2.0
@@ -598,7 +598,7 @@ class OneAndInfiniteSumAreTheSameThing(Scene):
self.dither()
self.add(inf_sum.shift(RIGHT))
self.dither()
self.animate(
self.play(
ApplyMethod(one.shift, RIGHT),
ApplyMethod(inf_sum.shift, LEFT),
CounterclockwiseTransform(point, equals)
@@ -623,7 +623,7 @@ class HowDoYouDefineInfiniteSums(Scene):
for mob in text[:-1]:
self.add(mob)
self.dither(0.1)
self.animate(BlinkPiCreature(you))
self.play(BlinkPiCreature(you))
self.dither()
self.add(text[-1])
self.dither()
@@ -650,8 +650,8 @@ class LessAboutNewThoughts(Scene):
kwargs = {"run_time" : 0.25}
self.add(*words)
self.dither()
self.animate(ShowCreation(gen_cross, **kwargs))
self.animate(ShowCreation(new_cross, **kwargs))
self.play(ShowCreation(gen_cross, **kwargs))
self.play(ShowCreation(new_cross, **kwargs))
self.dither()
self.add(disecting)
self.dither(0.5)
@@ -679,9 +679,9 @@ class ListOfPartialSums(Scene):
display_numbers = False,
run_time = 1.0
)
self.animate(ShowCreation(dots))
self.play(ShowCreation(dots))
self.dither()
self.animate(
self.play(
FadeIn(CompoundMobject(*equals)),
*[
Transform(deepcopy(number), finite_sum)
@@ -689,7 +689,7 @@ class ListOfPartialSums(Scene):
]
)
self.dither()
self.animate(*[
self.play(*[
ApplyMethod(s.highlight, "yellow", alpha_func = there_and_back)
for s in sums
])
@@ -720,7 +720,7 @@ class ShowDecreasingDistance(Scene):
self.add(dots.split()[0])
self.add(number_line, *lines)
self.dither()
self.animate(
self.play(
ApplyMethod(vert_line0.shift, RIGHT),
Transform(
horiz_line,
@@ -753,19 +753,19 @@ class CircleZoomInOnOne(Scene):
arrow = Arrow(2*RIGHT, direction = 1.5*(DOWN+RIGHT)).nudge()
self.add(number_line, dots)
self.animate(
self.play(
Transform(circle, Point(2*RIGHT).highlight("white")),
run_time = 5.0
)
self.animate(*[
self.play(*[
DelayByOrder(FadeIn(mob))
for mob in arrow, curr_num
])
self.dither()
for num in numbers[1:] + [text]:
curr_num.points = np.array(list(reversed(curr_num.points)))
self.animate(
self.play(
ShowCreation(
curr_num,
alpha_func = lambda t : smooth(1-t)
@@ -782,12 +782,12 @@ class ZoomInOnOne(Scene):
number_line = NumberLine(interval_size = 1, radius = SPACE_WIDTH+2)
number_line.filter_out(lambda (x, y, z):abs(y)>0.1)
nl_with_nums = deepcopy(number_line).add_numbers()
self.animate(ApplyMethod(nl_with_nums.shift, 2*LEFT))
self.play(ApplyMethod(nl_with_nums.shift, 2*LEFT))
zero, one, two = [
tex_mobject(str(n)).scale(0.5).shift(0.4*DOWN+2*(-1+n)*RIGHT)
for n in 0, 1, 2
]
self.animate(
self.play(
FadeOut(nl_with_nums),
*[Animation(mob) for mob in zero, one, two, number_line]
)
@@ -817,7 +817,7 @@ class ZoomInOnOne(Scene):
for x in range(num_levels)
]
kwargs = {"alpha_func" : None}
self.animate(*[
self.play(*[
ApplyMethod(number_lines[x].scale, scale_val, **kwargs)
for x in range(1, num_levels)
]+[
@@ -853,7 +853,7 @@ class DefineInfiniteSum(Scene):
self.add(expression)
self.dither()
self.animate(ApplyFunction(
self.play(ApplyFunction(
lambda mob : mob.scale(0.5).to_corner(UP+LEFT, buff = buff),
expression
))
@@ -863,7 +863,7 @@ class DefineInfiniteSum(Scene):
Line(SPACE_WIDTH*LEFT+bottom, side+bottom),
Line(SPACE_HEIGHT*UP+side, side+bottom)
]
self.animate(*[
self.play(*[
ShowCreation(line.highlight("white"))
for line in lines
])
@@ -893,7 +893,7 @@ class DefineInfiniteSum(Scene):
self.dither()
esses = np.array(terms)[range(0, len(terms), 3)]
other_terms = filter(lambda m : m not in esses, terms)
self.animate(*[
self.play(*[
ApplyMethod(ess.highlight, "yellow")
for ess in esses
])
@@ -903,7 +903,7 @@ class DefineInfiniteSum(Scene):
s.scale(1.0/(n+1))
s.shift(ex_point-RIGHT*2.0/2**n)
return s
self.animate(*[
self.play(*[
FadeOut(term)
for term in other_terms
]+[
@@ -920,7 +920,7 @@ class DefineInfiniteSum(Scene):
for y in [-1, -0.01, 1, 0.01]
for x in [ex_point+y*RIGHT]
]
self.animate(*[
self.play(*[
Transform(lines[x], lines[x+1], run_time = 3.0)
for x in 0, 2
])
@@ -944,8 +944,8 @@ class YouJustInventedSomeMath(Scene):
for mob in text:
self.add(mob)
self.dither(0.2)
self.animate(WaveArm(you))
self.animate(BlinkPiCreature(you))
self.play(WaveArm(you))
self.play(BlinkPiCreature(you))
@@ -968,7 +968,7 @@ class SeekMoreGeneralTruths(Scene):
for qsum in sums.split():
qsum.sort_points(lambda p : np.dot(p, DOWN+RIGHT))
self.animate(DelayByOrder(FadeIn(qsum)))
self.play(DelayByOrder(FadeIn(qsum)))
self.dither(0.5)
self.dither()
@@ -1036,7 +1036,7 @@ class ChopIntervalInProportions(Scene):
new_term_to_replace = deepcopy(term_to_replace)
new_term_to_replace.center().shift(last+UP+0.3*LEFT)
left_paren.center().shift(last+1.1*UP)
self.animate(
self.play(
FadeIn(lt[1]),
FadeIn(rt[0]),
Transform(
@@ -1049,7 +1049,7 @@ class ChopIntervalInProportions(Scene):
*additional_anims
)
self.dither()
self.animate(
self.play(
Transform(
term_to_replace,
CompoundMobject(lt[0], rt[1])
@@ -1059,7 +1059,7 @@ class ChopIntervalInProportions(Scene):
)
self.remove(left_paren, right_paren)
else:
self.animate(
self.play(
FadeIn(lt[1]),
FadeIn(rt[0]),
Transform(
@@ -1076,7 +1076,7 @@ class ChopIntervalInProportions(Scene):
lt, rt = CompoundMobject(*lt), CompoundMobject(*rt)
self.add(lt, rt)
else:
self.animate(
self.play(
Transform(
brace_to_replace.repeat(2),
CompoundMobject(*braces)
@@ -1090,7 +1090,7 @@ class ChopIntervalInProportions(Scene):
self.remove(brace_to_replace, term_to_replace)
self.add(lt, rt, *braces)
else:
self.animate(*[
self.play(*[
FadeIn(mob)
for mob in braces + [lt, rt]
] + additional_anims)
@@ -1104,7 +1104,7 @@ class ChopIntervalInProportions(Scene):
split_100.to_edge(RIGHT)
split_100.sort_points()
right_terms[-1].sort_points()
self.animate(Transform(
self.play(Transform(
right_terms[-1], split_100
))
self.dither()
@@ -1225,13 +1225,13 @@ class PlugNumbersIntoRightside(Scene):
self.add(lhs, *rhs)
self.dither()
self.animate(FadeIn(right_words))
self.play(FadeIn(right_words))
curr = rhs[1]
for num, count in zip(nums, it.count()):
self.animate(CounterclockwiseTransform(curr, num))
self.play(CounterclockwiseTransform(curr, num))
self.dither()
if count == 2:
self.animate(FadeIn(left_words))
self.play(FadeIn(left_words))
class PlugInNegativeOne(RearrangeEquation):
@@ -1327,10 +1327,10 @@ class ListPartialDivergentSums(Scene):
arrow = Arrow(3*DOWN+2*LEFT, direction = DOWN, length = 6)
for x in range(0, len(terms), 2):
self.animate(FadeIn(terms[x]), FadeIn(terms[x+1]))
self.animate(FadeIn(words), ShowCreation(arrow))
self.play(FadeIn(terms[x]), FadeIn(terms[x+1]))
self.play(FadeIn(words), ShowCreation(arrow))
for x in range(0, len(terms), 2):
self.animate(
self.play(
ApplyMethod(terms[x].highlight, "green"),
run_time = 0.1
)
@@ -1345,8 +1345,8 @@ class NotARobot(Scene):
low_words.shift(1.5*DOWN)
self.add(you)
self.animate(ShimmerIn(top_words))
self.animate(ShimmerIn(low_words))
self.play(ShimmerIn(top_words))
self.play(ShimmerIn(low_words))
class SumPowersOfTwoAnimation(Scene):
@@ -1412,7 +1412,7 @@ class SumPowersOfTwoAnimation(Scene):
new_top_sum_end = new_top_sum[-1]
self.dither()
self.animate(*[
self.play(*[
FadeIn(mob)
for mob in [
new_dots,
@@ -1423,7 +1423,7 @@ class SumPowersOfTwoAnimation(Scene):
]
])
self.dither()
self.animate(
self.play(
Transform(topbrace, new_topbrace),
Transform(alt_topbrace, new_topbrace),
Transform(bottombrace, new_bottombrace),
@@ -1463,11 +1463,11 @@ class PretendTheyDoApproachNegativeOne(RearrangeEquation):
for column in columns:
column.shift(shift_val)
shift_val = shift_val + (column.get_width()+0.2)*RIGHT
self.animate(ShimmerIn(columns[0]))
self.play(ShimmerIn(columns[0]))
self.dither()
self.add(columns[1])
self.dither()
self.animate(
self.play(
DelayByOrder(Transform(deepcopy(columns[0]), columns[-1])),
FadeIn(columns[2])
)
@@ -1488,16 +1488,16 @@ class DistanceBetweenRationalNumbers(Scene):
text = text_mobject("How we define distance between rational numbers")
text.to_edge(UP)
self.add(text, *nums)
self.animate(*[ShowCreation(arrow) for arrow in arrows])
self.animate(ShimmerIn(dist))
self.play(*[ShowCreation(arrow) for arrow in arrows])
self.play(ShimmerIn(dist))
self.dither()
class NotTheOnlyWayToOrganize(Scene):
def construct(self):
self.animate(ShowCreation(NumberLine().add_numbers()))
self.play(ShowCreation(NumberLine().add_numbers()))
self.dither()
words = "Is there any other reasonable way to organize numbers?"
self.animate(FadeIn(text_mobject(words).shift(2*UP)))
self.play(FadeIn(text_mobject(words).shift(2*UP)))
self.dither()
class DistanceIsAFunction(Scene):
@@ -1563,11 +1563,11 @@ class DistanceIsAFunction(Scene):
kwargs = {"run_time" : 0.5}
for mobs in example_mobs:
if previous:
self.animate(*[
self.play(*[
DelayByOrder(Transform(prev, mob, **kwargs))
for prev, mob in zip(previous, mobs)[:-1]
])
self.animate(DelayByOrder(Transform(
self.play(DelayByOrder(Transform(
previous[-1], mobs[-1], **kwargs
)))
self.remove(*previous)
@@ -1595,7 +1595,7 @@ class ShiftInvarianceNumberLine(Scene):
self.add(number_line, topbrace, dist0, footnote)
self.dither()
self.remove(dist0)
self.animate(
self.play(
ApplyMethod(topbrace.shift, 2*RIGHT),
*[
Transform(*pair)
@@ -1624,9 +1624,9 @@ class NameShiftInvarianceProperty(Scene):
mob.highlight("yellow")
self.add(prop)
self.animate(ShimmerIn(label), ShimmerIn(u_brace))
self.play(ShimmerIn(label), ShimmerIn(u_brace))
self.dither()
self.animate(ShimmerIn(name))
self.play(ShimmerIn(name))
self.dither()
@@ -1657,15 +1657,15 @@ class TriangleInequality(Scene):
]
for symbol, loc in zip(symbols, locations):
self.add(tex_mobject(symbol).shift(loc))
self.animate(ShowCreation(ac_line), FadeIn(ac_copy))
self.play(ShowCreation(ac_line), FadeIn(ac_copy))
self.dither()
self.animate(*[
self.play(*[
ShowCreation(line) for line in ab_line, bc_line
]+[
FadeIn(dist) for dist in ab_copy, bc_copy
])
self.dither()
self.animate(*[
self.play(*[
Transform(*pair)
for pair in zip(all_copies, all_dists)
]+[
@@ -1696,7 +1696,7 @@ class StruggleToFindFrameOfMind(Scene):
bubble.add_content(mob)
for first, second in [(curr, questions), (questions, mob)]:
copy = deepcopy(first)
self.animate(DelayByOrder(Transform(
self.play(DelayByOrder(Transform(
copy, second, **kwargs
)))
self.remove(copy)
@@ -1732,7 +1732,7 @@ class RoomsAndSubrooms(Scene):
for group in rectangle_groups:
mob = CompoundMobject(*group)
mob.sort_points(np.linalg.norm)
self.animate(ShowCreation(mob))
self.play(ShowCreation(mob))
self.dither()
@@ -1771,7 +1771,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
LEFT*0.05*n+\
(0.4*RIGHT if n == 0 else ORIGIN) #Stupid
)
self.animate(FadeIn(num, run_time = 0.5))
self.play(FadeIn(num, run_time = 0.5))
nums.append(num)
return zero, nums
@@ -1790,7 +1790,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
rect.highlight(colors[n])
rectangles.append(rect)
for rect in rectangles:
self.animate(ShowCreation(rect))
self.play(ShowCreation(rect))
self.dither()
return rectangles
@@ -1810,7 +1810,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
)
clusters.append(cluster)
for rect in cluster[1:]:
self.animate(FadeIn(rect, run_time = 0.6**(count-1)))
self.play(FadeIn(rect, run_time = 0.6**(count-1)))
return clusters
def adjust_power_mobs(self, zero, power_mobs, small_rects):
@@ -1822,7 +1822,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
new_power_mobs[-1].shift(DOWN)
dots = tex_mobject("\\vdots")
dots.scale(0.5).shift(new_zero.get_center()+0.5*DOWN)
self.animate(
self.play(
Transform(zero, new_zero),
FadeIn(dots),
*[
@@ -1847,7 +1847,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
self.center_in_closest_rect(mob, small_rects)
mob.shift(UP)
return mob
self.animate(*[
self.play(*[
ApplyFunction(transform, mob)
for mob in zero_copy, power_mob_copy
])
@@ -1855,7 +1855,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
for n in range(power+1, 2*power):
left_mob = num_mobs[n-power]
shift_val = left_mob.get_center()-last_left_mob.get_center()
self.animate(*[
self.play(*[
ApplyMethod(mob.shift, shift_val)
for mob in zero_copy, power_mob_copy
])
@@ -1867,7 +1867,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
num_mobs[n].shift(power_mob_copy.get_center()+DOWN)
self.center_in_closest_rect(num_mobs[n], small_rects)
point = Point(power_mob_copy.get_center())
self.animate(Transform(point, num_mobs[n]))
self.play(Transform(point, num_mobs[n]))
self.remove(point)
self.add(num_mobs[n])
last_left_mob = left_mob
@@ -1885,7 +1885,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
neg_one = tex_mobject("-1").scale(0.5)
shift_val = num_mobs[15].get_center()-neg_one.get_center()
neg_one.shift(UP)
self.animate(ApplyMethod(neg_one.shift, shift_val))
self.play(ApplyMethod(neg_one.shift, shift_val))
def show_distances(self, num_mobs, rect_clusters):
self.remove(*[r for c in rect_clusters for r in c])
@@ -1912,7 +1912,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
for pair in sample(pairs, min(10, len(pairs))):
for index in pair:
num_mobs[index].highlight("green")
self.animate(*[
self.play(*[
ApplyMethod(
num_mobs[index].rotate_in_place, np.pi/10,
alpha_func = wiggle
@@ -1967,7 +1967,7 @@ class DeduceWhereNegativeOneFalls(Scene):
for new_arg, old_arg in zip(new_args, last_args):
new_arg.shift(old_arg.get_center())
if last_args != [arg0, arg1]:
self.animate(*[
self.play(*[
DelayByOrder(Transform(*pair, run_time = 0.5*rest_time))
for pair in zip(last_args, new_args)
])
@@ -2003,7 +2003,7 @@ class OtherRationalNumbers(Scene):
]
for pair, locus in zip(pairs, locii):
fraction = tex_mobject("\\frac{%d}{%d}"%pair).shift(locus)
self.animate(ShimmerIn(fraction))
self.play(ShimmerIn(fraction))
self.dither()
class PAdicMetric(Scene):
@@ -2022,18 +2022,18 @@ class PAdicMetric(Scene):
for prime, count in zip(primes, it.count()):
prime.scale(1.0).highlight(colors.next())
prime.shift(center_of_mass([p_str.get_top(), p_str.get_center()]))
self.animate(DelayByOrder(Transform(curr, prime)))
self.play(DelayByOrder(Transform(curr, prime)))
self.dither()
if count == 2:
self.spill(CompoundMobject(curr, text), arrow, new_numbers)
self.remove(curr)
curr = prime
self.animate(DelayByOrder(Transform(curr, p_str)))
self.play(DelayByOrder(Transform(curr, p_str)))
self.dither()
def spill(self, start, arrow, end):
start.sort_points(lambda p : p[1])
self.animate(
self.play(
ShowCreation(
arrow,
alpha_func = squish_alpha_func(smooth, 0.5, 1.0)
@@ -2043,7 +2043,7 @@ class PAdicMetric(Scene):
Point(arrow.points[0]).highlight("white")
))
)
self.animate(ShimmerIn(end))
self.play(ShimmerIn(end))
class FuzzyDiscoveryToNewMath(Scene):
@@ -2098,12 +2098,12 @@ class FuzzyDiscoveryToNewMath(Scene):
midpoints.append(count*UP)
self.add(fuzzy, lines)
self.animate(*map(ShimmerIn, fuzzy_discoveries))
self.play(*map(ShimmerIn, fuzzy_discoveries))
self.dither()
self.animate(DelayByOrder(Transform(
self.play(DelayByOrder(Transform(
deepcopy(fuzzy), new_math
)))
self.animate(*[
self.play(*[
DelayByOrder(Transform(deepcopy(disc), math))
for disc, math in zip(fuzzy_discoveries, new_maths)
])
@@ -2129,7 +2129,7 @@ class DiscoveryAndInvention(Scene):
nrd.get_bottom(),
tail = discovery.get_top()
)
self.animate(
self.play(
FadeIn(nrd),
ShowCreation(arrow)
)
@@ -2139,14 +2139,14 @@ class DiscoveryAndInvention(Scene):
invention.get_top(),
tail = nrd.get_bottom()
)
self.animate(ShowCreation(arrow))
self.play(ShowCreation(arrow))
arrows.append(arrow)
self.dither()
arrow = Arrow(
rt.get_top(),
tail = invention.get_bottom()
)
self.animate(
self.play(
FadeIn(rt),
ShowCreation(arrow)
)
@@ -2156,12 +2156,12 @@ class DiscoveryAndInvention(Scene):
discovery.get_bottom(),
tail = rt.get_top()
)
self.animate(ShowCreation(arrow))
self.play(ShowCreation(arrow))
self.dither()
arrows.append(arrow)
for color in Color("yellow").range_to("red", 4):
for arrow in arrows:
self.animate(
self.play(
ShowCreation(deepcopy(arrow).highlight(color)),
run_time = 0.25
)

View File

@@ -133,7 +133,7 @@ class CountSections(CircleScene):
def __init__(self, *args, **kwargs):
CircleScene.__init__(self, *args, **kwargs)
self.remove(*self.lines)
self.animate(*[
self.play(*[
Transform(Dot(points[i]),Line(points[i], points[1-i]))
for points in it.combinations(self.points, 2)
for i in (0, 1)
@@ -219,13 +219,13 @@ class HardProblemsSimplerQuestions(Scene):
for c in [left_center, right_center]
]
self.add(fermat["n"])
self.animate(*[
self.play(*[
Transform(deepcopy(fermat["n"]), f_copy)
for f_copy in copies
])
self.remove(*self.mobjects)
self.add(fermat["n"])
self.animate(*[
self.play(*[
CounterclockwiseTransform(mobs[0], mobs[1])
for f_copy, sym in zip(copies, ["3", "2"])
for mobs in zip(f_copy.split(), fermat[sym].split())
@@ -257,7 +257,7 @@ class HardProblemsSimplerQuestions(Scene):
mob.scale(0.5).shift(left_center + (0, 2, 0))
self.add(circle_grid, other_grid)
self.animate(
self.play(
FadeIn(fermat2_jargon),
FadeIn(fermat3_jargon),
CounterclockwiseTransform(start_line, end_line),
@@ -266,7 +266,7 @@ class HardProblemsSimplerQuestions(Scene):
self.dither()
all_mobjects = CompoundMobject(*self.mobjects)
self.remove(*self.mobjects)
self.animate(
self.play(
Transform(
all_mobjects,
Point((SPACE_WIDTH, 0, 0))
@@ -301,7 +301,7 @@ class CountLines(CircleScene):
]
self.add(text)
self.dither()
self.animate(*[
self.play(*[
Transform(line1, line2, run_time = 2)
for line1, line2 in zip(self.lines, new_lines)
])
@@ -314,7 +314,7 @@ class CountLines(CircleScene):
anims.append(Transform(mob, answer))
else:
anims.append(FadeOut(mob))
self.animate(*anims, run_time = 1)
self.play(*anims, run_time = 1)
class CountIntersectionPoints(CircleScene):
def __init__(self, radians, *args, **kwargs):
@@ -347,7 +347,7 @@ class CountIntersectionPoints(CircleScene):
else:
anims.append(FadeOut(mob))
anims.append(Animation(formula))
self.animate(*anims, run_time = 1)
self.play(*anims, run_time = 1)
class NonGeneralPosition(CircleScene):
args_list = []
@@ -383,7 +383,7 @@ class NonGeneralPosition(CircleScene):
self.dither(2)
self.remove(text, arrow)
self.reset_background()
self.animate(*[
self.play(*[
Transform(mob1, mob2, run_time = DEFAULT_ANIMATION_RUN_TIME)
for mob1, mob2 in zip(self.mobjects, new_self.mobjects)
])
@@ -430,12 +430,12 @@ class GeneralPositionRule(Scene):
for i, j in pairs
for line in [Line(cs.points[i], cs.points[j])]
]
self.animate(*[
self.play(*[
ShowCreation(line, run_time = 1.0)
for line in intersecting_lines
])
if first_time:
self.animate(Transform(
self.play(Transform(
CompoundMobject(*intersecting_lines),
words_mob
))
@@ -465,18 +465,18 @@ class LineCorrespondsWithPair(CircleScene):
self.dots.remove(dot0)
self.dots.remove(dot1)
self.dither()
self.animate(*[
self.play(*[
ApplyMethod(mob.fade, 0.2)
for mob in self.lines + self.dots
])
self.animate(*[
self.play(*[
Transform(
dot, Dot(dot.get_center(), 3*dot.radius),
alpha_func = there_and_back
)
for dot in (dot0, dot1)
])
self.animate(Transform(line, dot0))
self.play(Transform(line, dot0))
class IllustrateNChooseK(Scene):
args_list = [
@@ -550,7 +550,7 @@ class IllustrateNChooseK(Scene):
self.remove(count_mob)
self.remove(tuple_copy)
self.add(count_mob)
self.animate(FadeIn(CompoundMobject(form1, form2, pronunciation)))
self.play(FadeIn(CompoundMobject(form1, form2, pronunciation)))
class IntersectionPointCorrespondances(CircleScene):
args_list = [
@@ -602,16 +602,16 @@ class IntersectionPointCorrespondances(CircleScene):
fade_outs.append(FadeOut(mob, alpha_func = not_quite_there))
self.add(intersection_dot_arrow)
self.animate(Highlight(intersection_dot))
self.play(Highlight(intersection_dot))
self.remove(intersection_dot_arrow)
self.animate(*fade_outs)
self.play(*fade_outs)
self.dither()
self.add(line_statement)
self.animate(*line_highlights)
self.play(*line_highlights)
self.remove(line_statement)
self.dither()
self.add(dots_statement, *dot_pointers)
self.animate(*dot_highlights)
self.play(*dot_highlights)
self.remove(dots_statement, *dot_pointers)
class LinesIntersectOutside(CircleScene):
@@ -637,11 +637,11 @@ class LinesIntersectOutside(CircleScene):
self.lines[pairs.index((indices[p0], indices[p1]))]
for p0, p1 in [(0, 1), (2, 3)]
]
self.animate(*[
self.play(*[
FadeOut(mob, alpha_func = not_quite_there)
for mob in self.mobjects if mob not in lines_to_save
])
self.animate(*[
self.play(*[
Transform(
Line(self.points[indices[p0]], self.points[indices[p1]]),
Line(self.points[indices[p0]], intersection_point))
@@ -665,7 +665,7 @@ class QuadrupletsToIntersections(CircleScene):
dot_quad.highlight()
self.add(dot_quad)
self.dither(frame_time / 3)
self.animate(Transform(
self.play(Transform(
dot_quad,
intersection_dot,
run_time = 3*frame_time/2
@@ -684,19 +684,19 @@ class GraphsAndEulersFormulaJoke(Scene):
)
graph.filter_out(lambda (x, y, z) : abs(y) > SPACE_HEIGHT)
self.add(axes)
self.animate(ShowCreation(graph), run_time = 1.0)
self.play(ShowCreation(graph), run_time = 1.0)
eulers = tex_mobject("e^{\pi i} = -1").shift((0, 3, 0))
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
deepcopy(graph), eulers
))
self.dither()
self.remove(*self.mobjects)
self.add(eulers)
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
CompoundMobject(axes, graph),
Point((-SPACE_WIDTH, SPACE_HEIGHT, 0))
))
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
eulers,
Point((SPACE_WIDTH, SPACE_HEIGHT, 0))
))
@@ -710,16 +710,16 @@ class DefiningGraph(GraphScene):
dots, lines = self.vertices, self.edges
self.remove(*dots + lines)
all_dots = CompoundMobject(*dots)
self.animate(ShowCreation(all_dots))
self.play(ShowCreation(all_dots))
self.remove(all_dots)
self.add(*dots)
self.animate(FadeIn(vertices_word))
self.play(FadeIn(vertices_word))
self.dither()
self.remove(vertices_word)
self.animate(*[
self.play(*[
ShowCreation(line) for line in lines
])
self.animate(FadeIn(edges_word))
self.play(FadeIn(edges_word))
#Move to new graph
# new_graph = deepcopy(self.graph)
@@ -728,7 +728,7 @@ class DefiningGraph(GraphScene):
# for v in new_graph.vertices
# ]
# new_graph_scene = GraphScene(new_graph)
# self.animate(*[
# self.play(*[
# Transform(m[0], m[1])
# for m in zip(self.mobjects, new_graph_scene.mobjects)
# ], run_time = 7.0)
@@ -741,7 +741,7 @@ class IntersectCubeGraphEdges(GraphScene):
def __init__(self, *args, **kwargs):
GraphScene.__init__(self, CubeGraph(), *args, **kwargs)
self.remove(self.edges[0], self.edges[4])
self.animate(*[
self.play(*[
Transform(
Line(self.points[i], self.points[j]),
CurvedLine(self.points[i], self.points[j]),
@@ -772,7 +772,7 @@ class DoubledEdges(GraphScene):
Transform(backwards, outward, **kwargs),
]
outward_curved_lines.append(outward)
self.animate(*anims)
self.play(*anims)
self.dither()
self.remove(*outward_curved_lines)
@@ -846,12 +846,12 @@ class CannotDirectlyApplyEulerToMoser(CircleScene):
yellow_lines = CompoundMobject(*[
l.highlight("yellow") for l in deepcopy(self.lines)
])
self.animate(*[
self.play(*[
ShowCreation(dot) for dot in yellow_dots
], run_time = 1.0)
self.dither()
self.remove(*yellow_dots)
self.animate(ShowCreation(yellow_lines))
self.play(ShowCreation(yellow_lines))
self.dither()
self.remove(yellow_lines)
cannot_intersect = text_mobject(r"""
@@ -868,7 +868,7 @@ class CannotDirectlyApplyEulerToMoser(CircleScene):
for mob in self.mobjects:
mob.fade(1/0.3)
self.generate_intersection_dots()
self.animate(FadeIn(intersection_count), *[
self.play(FadeIn(intersection_count), *[
ShowCreation(dot) for dot in self.intersection_dots
])
@@ -899,7 +899,7 @@ class ShowMoserGraphLines(CircleScene):
compound = CompoundMobject(*mobs)
if mobs in (self.dots, self.intersection_dots):
self.remove(*mobs)
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
compound,
deepcopy(compound).scale(1.05),
alpha_func = there_and_back,
@@ -907,12 +907,12 @@ class ShowMoserGraphLines(CircleScene):
))
else:
compound.highlight("yellow")
self.animate(ShowCreation(compound))
self.play(ShowCreation(compound))
self.remove(compound)
if mobs == self.intersection_dots:
self.remove(n, plus_n_choose_4)
self.animate(*[
self.play(*[
Transform(line, small_line, run_time = 3.0)
for line, small_line in zip(self.lines, small_lines)
])
@@ -920,16 +920,16 @@ class ShowMoserGraphLines(CircleScene):
line.highlight("yellow") for line in small_lines
])
self.add(plus_2_n_choose_4)
self.animate(ShowCreation(yellow_lines))
self.play(ShowCreation(yellow_lines))
self.dither()
self.remove(yellow_lines)
self.chop_circle_at_points()
self.animate(*[
self.play(*[
Transform(p, sp, run_time = 3.0)
for p, sp in zip(self.circle_pieces, self.smaller_circle_pieces)
])
self.add(plus_n)
self.animate(ShowCreation(CompoundMobject(*[
self.play(ShowCreation(CompoundMobject(*[
mob.highlight("yellow") for mob in self.circle_pieces
])))
@@ -961,7 +961,7 @@ class HowIntersectionChopsLine(CircleScene):
for p0, p1 in [(0, 2), (1, 3)]
])
self.add(*lines)
self.animate(*[
self.play(*[
FadeOut(mob)
for mob in self.mobjects
if mob not in lines
@@ -973,7 +973,7 @@ class HowIntersectionChopsLine(CircleScene):
Line(intersection_point, line.end)
for line in lines
]
self.animate(*[
self.play(*[
Transform(
line,
Line(
@@ -986,7 +986,7 @@ class HowIntersectionChopsLine(CircleScene):
for line, h in zip(lines, (-1, 1))
])
self.remove(*lines)
self.animate(*[
self.play(*[
Transform(
line,
deepcopy(line).scale(1.1).scale_in_place(1/1.1),
@@ -1054,7 +1054,7 @@ class ApplyEulerToMoser(CircleScene):
d[key].get_center() - main_center
)
self.animate(*[
self.play(*[
CounterclockwiseTransform(d[1], d[2], run_time = 2.0)
for d in [V, minus, E, plus, F, equals, two]
])
@@ -1069,7 +1069,7 @@ class ApplyEulerToMoser(CircleScene):
F[1].highlight("white")
E[1].highlight()
self.remove(*self.lines + self.circle_pieces)
self.animate(*[
self.play(*[
Transform(
deepcopy(line),
deepcopy(line).scale_in_place(0.5),
@@ -1088,7 +1088,7 @@ class ApplyEulerToMoser(CircleScene):
V[1].highlight()
self.add(*self.dots + self.intersection_dots)
self.remove(*self.lines + self.circle_pieces)
self.animate(*[
self.play(*[
Transform(
deepcopy(dot),
deepcopy(dot).scale_in_place(1.4).highlight("yellow")
@@ -1110,7 +1110,7 @@ class ApplyEulerToMoser(CircleScene):
self.dither()
self.add(*all_mobs)
self.remove(*[d[1] for d in [V, minus, E, plus, F, equals, two]])
self.animate(
self.play(
Transform(V[2].repeat(2), CompoundMobject(n[3], minus1[3], nc4[3])),
*[
Transform(d[2], d[3])
@@ -1119,7 +1119,7 @@ class ApplyEulerToMoser(CircleScene):
)
self.dither()
self.remove(*self.mobjects)
self.animate(
self.play(
Transform(E[3], CompoundMobject(
nc2[4], plus1[4], two1[4], nc41[4], plus2[4], n1[4]
)),
@@ -1140,7 +1140,7 @@ class ApplyEulerToMoser(CircleScene):
)
self.dither()
self.remove(*self.mobjects)
self.animate(
self.play(
Transform(
CompoundMobject(plus2[4], n1[4], minus[4], n[4]),
Point((SPACE_WIDTH, SPACE_HEIGHT, 0))
@@ -1153,7 +1153,7 @@ class ApplyEulerToMoser(CircleScene):
)
self.dither()
self.remove(*self.mobjects)
self.animate(
self.play(
Transform(nc41[5], nc4[6]),
Transform(two1[5], Point(nc4[6].get_center())),
*[
@@ -1163,7 +1163,7 @@ class ApplyEulerToMoser(CircleScene):
)
self.dither()
self.remove(*self.mobjects)
self.animate(
self.play(
CounterclockwiseTransform(two[6], two[7]),
CounterclockwiseTransform(plus[6], plus[7]),
*[
@@ -1184,7 +1184,7 @@ class ApplyEulerToMoser(CircleScene):
one = tex_mobject("1").shift(two.get_center())
two.highlight("red")
self.add(two)
self.animate(CounterclockwiseTransform(two, one))
self.play(CounterclockwiseTransform(two, one))
class FormulaRelatesToPowersOfTwo(Scene):
def __init__(self, *args, **kwargs):
@@ -1207,11 +1207,11 @@ class FormulaRelatesToPowersOfTwo(Scene):
sums = everything[1::3]
results = everything[2::3]
self.add(*forms)
self.animate(*[
self.play(*[
FadeIn(s) for s in sums
])
self.dither()
self.animate(*[
self.play(*[
Transform(deepcopy(s), result)
for s, result in zip(sums, results)
])
@@ -1225,7 +1225,7 @@ class FormulaRelatesToPowersOfTwo(Scene):
self.dither()
self.remove(*self.mobjects)
self.add(*forms + sums + results)
self.animate(*[
self.play(*[
CounterclockwiseTransform(result, pof2)
for result, pof2 in zip(results, powers_of_two)
])
@@ -1245,7 +1245,7 @@ class DrawPascalsTriangle(PascalsTriangleScene):
for k in range(1, n)
]
starts.append(deepcopy(self.coords_to_mobs[n-1][n-1]))
self.animate(*[
self.play(*[
Transform(starts[i], self.coords_to_mobs[n][i],
run_time = 1.5, black_out_extra_points = False)
for i in range(n+1)
@@ -1276,7 +1276,7 @@ class PascalsTriangleWithNChooseK(PascalsTriangleScene):
for i in [0, 1]:
self.dither()
self.remove(*self.mobjects)
self.animate(*[
self.play(*[
CounterclockwiseTransform(
deepcopy(mob_dicts[i][n][k]),
mob_dicts[1-i][n][k]
@@ -1305,7 +1305,7 @@ class PascalsTriangleNChooseKExample(PascalsTriangleScene):
self.remove(*triangle_terms)
self.add(*formula_terms)
self.dither()
self.animate(*
self.play(*
[
ShowCreation(mob) for mob in triangle_terms
]+[
@@ -1339,7 +1339,7 @@ class PascalsTriangleNChooseKExample(PascalsTriangleScene):
if b < k:
self.coords_to_mobs[n][b].highlight("green")
self.remove(b_mob)
self.animate(*[
self.play(*[
ApplyMethod(mob.fade, 0.2)
for mob in triangle_terms
if mob != self.coords_to_mobs[n][k]
@@ -1384,13 +1384,13 @@ class PascalsTriangleSumRows(PascalsTriangleScene):
powers_of_two.append(pof2)
equalses.append(new_equals)
powers_of_two_symbols.append(symbol)
self.animate(FadeIn(CompoundMobject(*pluses)))
self.play(FadeIn(CompoundMobject(*pluses)))
run_time = 0.5
to_remove = []
for n in range(self.nrows):
start = CompoundMobject(*[self.coords_to_mobs[n][k] for k in range(n+1)])
to_remove.append(start)
self.animate(
self.play(
Transform(start, powers_of_two[n]),
FadeIn(equalses[n]),
run_time = run_time
@@ -1399,7 +1399,7 @@ class PascalsTriangleSumRows(PascalsTriangleScene):
self.remove(*to_remove)
self.add(*powers_of_two)
for n in range(self.nrows):
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
powers_of_two[n], powers_of_two_symbols[n],
run_time = run_time
))
@@ -1438,7 +1438,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
target_terms.append(new_term)
self.add(*terms)
self.dither()
self.animate(*
self.play(*
[
FadeIn(self.coords_to_n_choose_k[n0][k0])
for n0, k0 in self.coords
@@ -1454,7 +1454,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
(k, deepcopy(self.coords_to_mobs[n][k]).highlight(term_color))
for k in term_range
])
self.animate(*
self.play(*
[
CounterclockwiseTransform(
self.coords_to_n_choose_k[n0][k0],
@@ -1479,7 +1479,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
self.coords_to_n_choose_k[n-1][k],
]
self.add(self.coords_to_mobs[n][k])
self.animate(Transform(
self.play(Transform(
terms[k],
CompoundMobject(*above_terms).highlight(term_color)
))
@@ -1488,7 +1488,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
terms_sum = tex_mobject(str(moser_function(n)))
terms_sum.shift((SPACE_WIDTH-1, terms[0].get_center()[1], 0))
terms_sum.highlight(term_color)
self.animate(Transform(CompoundMobject(*terms), terms_sum))
self.play(Transform(CompoundMobject(*terms), terms_sum))
class RotatingPolyhedra(Scene):
args_list = [
@@ -1511,13 +1511,13 @@ class RotatingPolyhedra(Scene):
]
curr_mob = polyhedra.pop()
for mob in polyhedra:
self.animate(TransformAnimations(
self.play(TransformAnimations(
Rotating(curr_mob, **rot_kwargs),
Rotating(mob, **rot_kwargs)
))
for m in polyhedra:
m.rotate(rot_kwargs["radians"], rot_kwargs["axis"])
self.animate(Rotating(curr_mob, **rot_kwargs))
self.play(Rotating(curr_mob, **rot_kwargs))
class ExplainNChoose2Formula(Scene):
args_list = [(7,2,6)]
@@ -1545,8 +1545,8 @@ class ExplainNChoose2Formula(Scene):
self.add(parens, n_mob)
up_unit = np.array((0, height, 0))
self.animate(ApplyMethod(nums_compound.shift, -(n-1)*up_unit))
self.animate(ApplyMethod(nums_compound.shift, (n-a)*up_unit))
self.play(ApplyMethod(nums_compound.shift, -(n-1)*up_unit))
self.play(ApplyMethod(nums_compound.shift, (n-a)*up_unit))
self.remove(nums_compound)
nums = nums_compound.split()
a_mob = nums.pop(a-1)
@@ -1555,23 +1555,23 @@ class ExplainNChoose2Formula(Scene):
self.dither()
right_shift = b_mob.get_center() - a_mob.get_center()
right_shift[1] = 0
self.animate(
self.play(
ApplyMethod(nums_compound.shift, right_shift),
FadeIn(n_minus_1)
)
self.animate(ApplyMethod(nums_compound.shift, (a-b)*up_unit))
self.play(ApplyMethod(nums_compound.shift, (a-b)*up_unit))
self.remove(nums_compound)
nums = nums_compound.split()
b_mob = nums.pop(b-2 if a < b else b-1)
self.add(b_mob)
self.animate(*[
self.play(*[
CounterclockwiseTransform(
mob,
Point(mob.get_center()).highlight("black")
)
for mob in nums
])
self.animate(*[
self.play(*[
ApplyMethod(mob.shift, (0, 1, 0))
for mob in parens, a_mob, b_mob
])
@@ -1581,7 +1581,7 @@ class ExplainNChoose2Formula(Scene):
a_copy = deepcopy(a_mob).center().shift(b_center - (0, 2, 0))
b_copy = deepcopy(b_mob).center().shift(a_center - (0, 2, 0))
self.add(over_2, deepcopy(a_mob), deepcopy(b_mob))
self.animate(
self.play(
CounterclockwiseTransform(a_mob, a_copy),
CounterclockwiseTransform(b_mob, b_copy),
FadeIn(parens_copy),
@@ -1619,7 +1619,7 @@ class ExplainNChoose4Formula(Scene):
up_unit = np.array((0, height, 0))
for i in range(4):
self.add(form_mobs[i])
self.animate(ApplyMethod(
self.play(ApplyMethod(
nums_compound.shift, (curr_num-quad[i])*up_unit))
self.remove(nums_compound)
nums = nums_compound.split()
@@ -1630,11 +1630,11 @@ class ExplainNChoose4Formula(Scene):
if i < 3:
right_shift = quad_mobs[i+1].get_center() - chosen.get_center()
right_shift[1] = 0
self.animate(
self.play(
ApplyMethod(nums_compound.shift, right_shift)
)
else:
self.animate(*[
self.play(*[
CounterclockwiseTransform(
mob,
Point(mob.get_center()).highlight("black")
@@ -1658,7 +1658,7 @@ class ExplainNChoose4Formula(Scene):
for i in range(4)
]
compound_quad = CompoundMobject(*quad_mobs)
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
compound_quad,
CompoundMobject(*new_quad_mobs)
))
@@ -1688,7 +1688,7 @@ class IntersectionChoppingExamples(Scene):
self.add(tex_mobject(exp).shift((0, SPACE_HEIGHT-1, 0)))
self.add(*lines)
self.dither()
self.animate(*[
self.play(*[
Transform(line, deepcopy(line).scale(1.2).scale_in_place(1/1.2))
for line in lines
])

View File

@@ -12,6 +12,7 @@ from constants import *
from region import *
from scene import Scene
from script_wrapper import command_line_create_scene
from inventing_math import underbrace
import random
@@ -47,6 +48,10 @@ def fraction_mobject(fraction):
n, d = fraction.numerator, fraction.denominator
return tex_mobject("\\frac{%d}{%d}"%(n, d))
def continued_fraction(int_list):
if len(int_list) == 1:
return int_list[0]
return int_list[0] + Fraction(1, continued_fraction(int_list[1:]))
def zero_to_one_interval():
interval = NumberLine(
@@ -69,6 +74,31 @@ class OpenInterval(Mobject):
self.stretch(0.5+0.5*scale_factor, 1)
self.shift(center)
class Piano(ImageMobject):
SHOULD_BUFF_POINTS = False
def __init__(self, **kwargs):
ImageMobject.__init__(self, "piano_keyboard", invert = False)
jump = self.get_width()/24
self.scale(0.5).center()
self.half_note_jump = self.get_width()/24
self.ivory_jump = self.get_width()/14
def split(self):
left = self.get_left()[0]
keys = []
for count in range(14):
key = Mobject(color = "white")
x0 = left + count*self.ivory_jump
x1 = x0 + self.ivory_jump
key.add_points(
self.points[
(self.points[:,0] > x0)*(self.points[:,0] < x1)
]
)
keys.append(key)
return keys
class VibratingString(Animation):
def __init__(self,
num_periods = 1,
@@ -84,7 +114,7 @@ class VibratingString(Animation):
self.center = center
def func(x, t):
return sum([
(amplitude/((k+1)**2))*np.sin(2*mult*t)*np.sin(k*mult*x)
(amplitude/((k+1)**2.5))*np.sin(2*mult*t)*np.sin(k*mult*x)
for k in range(overtones)
for mult in [(num_periods+k)*np.pi]
])
@@ -95,16 +125,18 @@ class VibratingString(Animation):
def update_mobject(self, alpha):
self.mobject.init_points()
epsilon = self.mobject.epsilon
self.mobject.add_points([
[x*self.radius, self.func(x, alpha*self.run_time), 0]
for x in np.arange(-1, 1, self.mobject.epsilon/self.radius)
[x*self.radius, self.func(x, alpha*self.run_time)+y, 0]
for x in np.arange(-1, 1, epsilon/self.radius)
for y in epsilon*np.arange(3)
])
self.mobject.shift(self.center)
class IntervalScene(Scene):
def construct(self):
self.interval = zero_to_one_interval()
self.interval = UnitInterval()
self.add(self.interval)
def show_all_fractions(self,
@@ -144,8 +176,8 @@ class IntervalScene(Scene):
)
def add_open_interval(self, num, width, color = None, run_time = 0):
width *= 2*self.interval.radius
center_point = self.num_to_point(num)
width *= self.interval.unit_length_to_spacial_width
center_point = self.interval.number_to_point(num)
open_interval = OpenInterval(center_point, width)
if color:
open_interval.highlight(color)
@@ -155,7 +187,7 @@ class IntervalScene(Scene):
interval_line.highlight("yellow")
if run_time > 0:
squished_interval = deepcopy(open_interval).stretch_to_fit_width(0)
self.animate(
self.play(
Transform(squished_interval, open_interval),
ShowCreation(interval_line),
run_time = run_time
@@ -164,11 +196,6 @@ class IntervalScene(Scene):
self.add(open_interval, interval_line)
return open_interval, interval_line
def num_to_point(self, num):
assert(num <= 1 and num >= 0)
radius = self.interval.radius
return (num*2*radius - radius)*RIGHT
class TwoChallenges(Scene):
def construct(self):
@@ -196,10 +223,10 @@ class TwoChallenges(Scene):
self.dither()
self.add(two, measure)
self.dither()
self.animate(ShowCreation(arrow_to_int))
self.play(ShowCreation(arrow_to_int))
self.add(integration)
self.dither()
self.animate(ShowCreation(arrow_to_prob))
self.play(ShowCreation(arrow_to_prob))
self.add(probability)
self.dither()
@@ -213,9 +240,9 @@ class MeasureTheoryToHarmony(IntervalScene):
self.clear()
radius = self.interval.radius
line = Line(radius*LEFT, radius*RIGHT).highlight("white")
self.animate(DelayByOrder(Transform(all_mobs, line)))
self.play(DelayByOrder(Transform(all_mobs, line)))
self.clear()
self.animate(VibratingString(alpha_func = smooth))
self.play(VibratingString(alpha_func = smooth))
self.clear()
self.add(line)
self.dither()
@@ -224,21 +251,440 @@ class MeasureTheoryToHarmony(IntervalScene):
class ChallengeOne(Scene):
def construct(self):
title = text_mobject("Challenge #1").to_edge(UP)
bottom_vibration = VibratingString(
num_periods = 1, run_time = 1.0,
start_color = Color("blue")
colors = start_color.range_to("white", 6)
self.bottom_vibration = VibratingString(
num_periods = 1, run_time = 3.0,
center = DOWN, color = start_color
)
top_vibrations = [
VibratingString(
num_periods = freq, run_time = 3.0,
center = 2*UP, color = colors.next()
)
for freq in [1, 2, 5.0/3, 4.0/3, 2]
]
freq_220 = text_mobject("220 Hz")
freq_r220 = text_mobject("$r\\times$220 Hz")
freq_330 = text_mobject("1.5$\\times$220 Hz")
freq_sqrt2 = text_mobject("$\\sqrt{2}\\times$220 Hz")
freq_220.shift(1.5*DOWN)
for freq in freq_r220, freq_330, freq_sqrt2:
freq.shift(1.5*UP)
r_constraint = tex_mobject("(1<r<2)", size = "\\large")
self.add(title)
self.dither()
self.vibrate(1)
self.add(freq_220)
self.vibrate(1)
self.add(r_constraint)
self.vibrate(1)
self.add(freq_r220)
self.vibrate(2, top_vibrations[1])
self.remove(freq_r220, r_constraint)
self.add(freq_330)
self.vibrate(2, top_vibrations[2])
self.remove(freq_330)
self.add(freq_sqrt2)
self.vibrate(1, top_vibrations[3])
self.remove(freq_sqrt2)
self.continuously_vary_frequency(top_vibrations[0], top_vibrations[4])
def vibrate(self, num_repeats, *top_vibrations):
anims = [self.bottom_vibration] + list(top_vibrations)
for count in range(num_repeats):
self.play(*anims)
self.remove(*[a.mobject for a in anims])
def continuously_vary_frequency(self, top_vib_1, top_vib_2):
number_line = NumberLine(interval_size = 1).add_numbers()
one, two = 2*number_line.interval_size*RIGHT, 4*number_line.interval_size*RIGHT
arrow1 = Arrow(one+UP, one)
arrow2 = Arrow(two+UP, two)
r1 = tex_mobject("r").next_to(arrow1, UP)
r2 = tex_mobject("r").next_to(arrow2, UP)
kwargs = {
"run_time" : 5.0,
"alpha_func" : there_and_back
}
run_time = 3.0
vibrations = [self.bottom_vibration, top_vib_1, top_vib_2]
self.add(number_line, r1, arrow1)
self.play(bottom_vibration, top_vib_1)
for vib in vibrations:
vib.set_run_time(kwargs["run_time"])
self.play(
self.bottom_vibration,
Transform(arrow1, arrow2, **kwargs),
Transform(r1, r2, **kwargs),
TransformAnimations(top_vib_1, top_vib_2, **kwargs)
)
for vib in vibrations:
vib.set_run_time(3.0)
self.play(bottom_vibration, top_vib_1)
class QuestionAndAnswer(Scene):
def construct(self):
Q = text_mobject("Q:").shift(UP).to_edge(LEFT)
A = text_mobject("A:").shift(DOWN).to_edge(LEFT)
string1 = VibratingString(center = 3*UP, color = "blue")
string2 = VibratingString(num_periods = 2, center = 3.5*UP, color = "green")
twotwenty = tex_mobject("220").scale(0.25).next_to(string1.mobject, LEFT)
r220 = tex_mobject("r\\times220").scale(0.25).next_to(string2.mobject, LEFT)
question = text_mobject(
"For what values of $r$ will the frequencies 220~Hz and \
$r\\times$220~Hz sound nice together?"
).next_to(Q)
answer = text_mobject([
"When $r$ is",
"sufficiently close to",
"a rational number"
], size = "\\small").scale(1.5)
answer.next_to(A)
correction1 = text_mobject(
"with sufficiently low denominator",
size = "\\small"
).scale(1.5)
correction1.highlight("yellow")
correction1.next_to(A).shift(2*answer.get_height()*DOWN)
answer = answer.split()
answer[1].highlight("green")
temp_answer_end = deepcopy(answer[-1]).next_to(answer[0], buff = 0.2)
self.add(Q, A, question, twotwenty, r220)
self.play(string1, string2)
self.add(answer[0], temp_answer_end)
self.play(string1, string2)
self.play(ShimmerIn(correction1), string1, string2)
self.play(string1, string2, run_time = 3.0)
self.play(
Transform(Point(answer[1].get_left()), answer[1]),
Transform(temp_answer_end, answer[2]),
string1, string2
)
self.play(string1, string2, run_time = 3.0)
class PlaySimpleRatio(Scene):
args_list = [
(Fraction(3, 2), "green"),
(Fraction(4, 3), "purple"),
(Fraction(8, 5), "skyblue"),
(Fraction(211, 198), "orange"),
(Fraction(1093, 826), "red"),
]
@staticmethod
def args_to_string(fraction, color):
return str(fraction).replace("/", "_to_")
def construct(self, fraction, color):
string1 = VibratingString(
num_periods = 1, run_time = 5.0,
center = DOWN, color = "blue"
)
top_vibration = VibratingString(
num_periods = 2, run_time = 1.0,
center = 2*UP, color = "lightgreen"
string2 = VibratingString(
num_periods = fraction, run_time = 5.0,
center = 2*UP, color = color
)
freq_num1 = text_mobject("220 Hz")
freq_num2 = text_mobject("$r\\times$220 Hz")
freq_num1.shift(1.5*DOWN)
freq_num2.shift(1.5*UP)
r_constraint = tex_mobject("1<r<2")
# self.add(title, freq_num1, freq_num2, r_constraint)
self.animate(top_vibration, bottom_vibration)
self.add(fraction_mobject(fraction).shift(0.5*UP))
self.play(string1, string2)
class FlashOnXProximity(Animation):
def __init__(self, mobject, x_val, *close_mobjects, **kwargs):
self.x_val = x_val
self.close_mobjects = close_mobjects
Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha):
for mob in self.close_mobjects:
if np.min(np.abs(mob.points[:,0] - self.x_val)) < 0.1:
self.mobject.highlight()
return
self.mobject.to_original_color()
class PatternInFrequencies(Scene):
args_list = [
(3, 2, "green"),
(4, 3, "purple"),
(8, 5, "skyblue"),
(35, 43, "red"),
]
@staticmethod
def args_to_string(num1, num2, color):
return "%d_to_%d"%(num1, num2)
def construct(self, num1, num2, color):
big_line = Line(SPACE_HEIGHT*UP, SPACE_HEIGHT*DOWN)
big_line.highlight("white").shift(2*LEFT)
line_template = Line(UP, DOWN)
line_template.shift(2*UP+2*LEFT)
setup_width = 2*SPACE_WIDTH
num_top_lines = int(setup_width)
num_bot_lines = int(setup_width*num1/num2)
top_lines = CompoundMobject(*[
deepcopy(line_template).shift(k*(float(num1)/num2)*RIGHT)
for k in range(num_top_lines)
])
line_template.shift(4*DOWN)
bottom_lines = CompoundMobject(*[
deepcopy(line_template).shift(k*RIGHT)
for k in range(num_bot_lines)
])
bottom_lines.highlight("blue")
top_lines.highlight(color)
kwargs = {
"run_time" : 10,
"alpha_func" : None
}
self.add(big_line)
self.add(tex_mobject("%d:%d"%(num1, num2)))
fracs = (
1.0/(num_top_lines-1),
1.0/(num_bot_lines-1)
)
anims = [
ApplyMethod(mob.shift, setup_width*LEFT, **kwargs)
for mob in top_lines, bottom_lines
]
anim_mobs = [anim.mobject for anim in anims]
self.play(
FlashOnXProximity(big_line, -2, *anim_mobs, **kwargs),
*anims
)
class CompareFractionComplexity(Scene):
def construct(self):
fractions = []
for num, den in [(4, 3), (1093,826)]:
top = tex_mobject("%d \\over"%num)
bottom = tex_mobject(str(den)).next_to(top, DOWN, buff = 0.3)
fractions.append(CompoundMobject(top, bottom))
frac0 = fractions[0].shift(3*LEFT).split()
frac1 = fractions[1].shift(3*RIGHT).split()
arrow1 = Arrow(UP, ORIGIN).next_to(frac0[0], UP)
arrow2 = Arrow(UP, ORIGIN).next_to(frac1[0], UP)
simple = text_mobject("Simple").next_to(arrow1, UP)
simple.highlight("green")
complicated = text_mobject("Complicated").next_to(arrow2, UP)
complicated.highlight("red")
indicates = text_mobject("Indicates complexity").shift(2*DOWN)
arrow3 = Arrow(indicates.get_top(), frac0[1])
arrow4 = Arrow(indicates.get_top(), frac1[1])
self.add(*frac0 + frac1)
self.dither()
self.add(simple, complicated)
self.play(*[
ShowCreation(arrow)
for arrow in arrow1, arrow2
])
self.dither()
self.play(*[
DelayByOrder(ApplyMethod(frac[1].highlight, "yellow"))
for frac in frac0, frac1
])
self.play(
FadeIn(indicates),
ShowCreation(arrow3),
ShowCreation(arrow4)
)
self.dither()
class IrrationalGang(Scene):
def construct(self):
randy = Randolph()
randy.mouth.highlight(randy.DEFAULT_COLOR)
randy.sync_parts()
sqrt13 = tex_mobject("\\sqrt{13}").shift(2*LEFT)
sqrt13.highlight("green")
zeta3 = tex_mobject("\\zeta(3)").shift(2*RIGHT)
zeta3.highlight("grey")
eyes = CompoundMobject(*randy.eyes)
eyes.scale(0.5)
sqrt13.add(eyes.next_to(sqrt13, UP, buff = 0).shift(0.25*RIGHT))
eyes.scale(0.5)
zeta3.add(eyes.next_to(zeta3, UP, buff = 0).shift(0.3*LEFT+0.08*DOWN))
speech_bubble = SpeechBubble()
speech_bubble.pin_to(randy)
speech_bubble.write("We want to play too!")
self.add(randy, sqrt13, zeta3, speech_bubble, speech_bubble.content)
self.play(BlinkPiCreature(randy))
class PianoTuning(Scene):
def construct(self):
piano = self.piano = Piano()
jump = piano.half_note_jump
semicircle = Circle().filter_out(lambda p : p[1] < 0)
semicircle.scale(jump/semicircle.get_width())
semicircles = CompoundMobject(*[
deepcopy(semicircle).shift(jump*k*RIGHT)
for k in range(23)
])
semicircles.highlight("white")
semicircles.next_to(piano, UP, buff = 0)
semicircles.shift(0.05*RIGHT)
semicircles.sort_points(lambda p : p[0])
first_jump = semicircles.split()[0]
twelfth_root = tex_mobject("2^{\\left(\\frac{1}{12}\\right)}")
twelfth_root.scale(0.75).next_to(first_jump, UP, buff = 1.5)
line = Line(twelfth_root, first_jump).highlight("grey")
self.keys = piano.split()
self.semicircles = semicircles.split()
self.add(piano)
self.dither()
self.play(ShowCreation(first_jump))
self.play(
ShowCreation(line),
FadeIn(twelfth_root)
)
self.dither()
self.play(ShowCreation(semicircles, alpha_func = None))
self.dither()
self.show_interval(5, 7)
self.show_interval(4, 5)
def show_interval(self, interval, half_steps):
whole_notes_to_base = 5
half_notes_to_base = 9
self.clear()
self.add(self.piano)
colors = list(Color("blue").range_to("yellow", 7))
low = self.keys[whole_notes_to_base]
high = self.keys[whole_notes_to_base + interval - 1]
u_brace = underbrace(low.get_bottom(), high.get_bottom())
u_brace.highlight("yellow")
ratio = tex_mobject("2^{\\left(\\frac{%d}{12}\\right)}"%half_steps)
ratio.next_to(u_brace, DOWN, buff = 0.2)
semicircles = self.semicircles[half_notes_to_base:half_notes_to_base+half_steps]
product = tex_mobject(
["\\left(2^{\\left(\\frac{1}{12}\\right)}\\right)"]*half_steps,
size = "\\small"
).next_to(self.piano, UP, buff = 1.0)
approximate_form = tex_mobject("\\approx"+str(2**(float(half_steps)/12)))
approximate_form.scale(0.75)
approximate_form.next_to(ratio)
self.play(ApplyMethod(low.highlight, colors[0]))
self.play(
ApplyMethod(high.highlight, colors[interval]),
Transform(Point(u_brace.get_left()), u_brace),
)
terms = product.split()
for term, semicircle in zip(terms, semicircles):
self.add(term, semicircle)
self.dither(0.25)
self.dither()
product.sort_points(lambda p : p[1])
self.play(DelayByOrder(Transform(product, ratio)))
self.dither()
self.play(ShimmerIn(approximate_form))
self.dither()
class PowersOfTwelfthRoot(Scene):
def construct(self):
max_height = SPACE_HEIGHT-0.5
min_height = -max_height
num_terms = 11
mob_list = []
fraction_map = {
1 : Fraction(16, 15),
2 : Fraction(9, 8),
3 : Fraction(6, 5),
4 : Fraction(5, 4),
5 : Fraction(4, 3),
7 : Fraction(3, 2),
8 : Fraction(8, 5),
9 : Fraction(5, 3),
10 : Fraction(16, 9),
}
approx = tex_mobject("\\approx").scale(0.5)
curr_height = max_height*UP
spacing = UP*(max_height-min_height)/(len(fraction_map)-1.0)
for i in range(1, num_terms+1):
if i not in fraction_map:
continue
term = tex_mobject("2^{\\left(\\frac{%d}{12}\\right)}"%i)
term.shift(curr_height)
curr_height -= spacing
term.shift(4*LEFT)
value = 2**(i/12.0)
approx_form = tex_mobject(str(value)[:10])
approx_copy = deepcopy(approx).next_to(term)
approx_form.scale(0.5).next_to(approx_copy)
words = text_mobject("is close to")
words.scale(approx_form.get_height()/words.get_height())
words.next_to(approx_form)
frac = fraction_map[i]
frac_mob = tex_mobject("%d/%d"%(frac.numerator, frac.denominator))
frac_mob.scale(0.5).next_to(words)
percent_error = abs(100*((value - frac) / frac))
error_string = text_mobject([
"with", str(percent_error)[:4] + "\\%", "error"
])
error_string = error_string.split()
error_string[1].highlight()
error_string = CompoundMobject(*error_string)
error_string.scale(approx_form.get_height()/error_string.get_height())
error_string.next_to(frac_mob)
mob_list.append(CompoundMobject(*[
term, approx_copy, approx_form, words, frac_mob, error_string
]))
self.play(ShimmerIn(CompoundMobject(*mob_list), run_time = 3.0))
class AllValuesBetween1And2(Scene):
def construct(self):
irrational = 1.2020569031595942
cont_frac = [1, 4, 1, 18, 1, 1, 1, 4, 1, 9, 9, 2, 1, 1, 1, 2]
number_line = NumberLine(interval_size = 1).add_numbers()
one, two = 2*RIGHT, 4*RIGHT
top_arrow = Arrow(one+UP, one)
bot_arrow = Arrow(2*irrational*RIGHT+DOWN, 2*irrational*RIGHT)
r = tex_mobject("r").next_to(top_arrow, UP)
irr_mob = tex_mobject(str(irrational)).next_to(bot_arrow, DOWN)
approximations = [
continued_fraction(cont_frac[:k])
for k in range(1, len(cont_frac))
]
approx_mobs = [fraction_mobject(a) for a in approximations]
self.add(number_line)
kwargs = {
"run_time" : 3.0,
"alpha_func" : there_and_back
}
self.play(*[
ApplyMethod(mob.shift, 2*RIGHT, **kwargs)
for mob in r, top_arrow
])
self.remove(r, top_arrow)
self.play(
ShimmerIn(irr_mob),
ShowCreation(bot_arrow)
)
frac_mob = Point(top_arrow.get_top())
for approx in approximations:
point = 2*float(approx)*RIGHT
new_arrow = Arrow(point+UP, point)
mob = fraction_mobject(approx).next_to(new_arrow, UP)
self.play(
Transform(top_arrow, new_arrow),
Transform(frac_mob, mob),
run_time = 0.2
)
self.dither(0.5)
@@ -252,7 +698,11 @@ class SampleIntervalScene(IntervalScene):
class ShowAllFractions(IntervalScene):
def construct(self):
IntervalScene.construct(self)
self.show_all_fractions(remove_as_you_go = False, pause_time = 0.3)
self.show_all_fractions(
num_fractions = 100,
remove_as_you_go = False,
pause_time = 0.3
)
if __name__ == "__main__":

View File

@@ -84,8 +84,8 @@ class HappyTauDayWords(Scene):
pi.highlight("red")
self.add(words, tau, pi)
self.dither()
self.animate(BlinkPiCreature(tau))
self.animate(BlinkPiCreature(pi))
self.play(BlinkPiCreature(tau))
self.play(BlinkPiCreature(pi))
class TauPoem(Scene):
args_list = map(lambda x : (x,), range(len(POEM_LINES)))
@@ -160,17 +160,17 @@ class TauPoem(Scene):
if self.line_num == 19:
shift_val = SPACE_HEIGHT*DOWN
self.new_digit.shift(shift_val)
self.animate(ApplyMethod(
self.play(ApplyMethod(
self.first_digits.shift, shift_val, run_time = 2.0
))
self.dither(2)
self.animate_over_time_range(0, 2,
self.play_over_time_range(0, 2,
Transform(
deepcopy(self.first_word), self.number_word,
alpha_func = squish_alpha_func(smooth)
)
)
self.animate_over_time_range(2, 4,
self.play_over_time_range(2, 4,
Transform(
self.number_word, self.new_digit,
alpha_func = squish_alpha_func(smooth)
@@ -181,7 +181,7 @@ class TauPoem(Scene):
two, pi = tex_mobject(["2", "\\pi"]).scale(2).split()
self.add(two, pi)
two_copy = deepcopy(two).rotate(np.pi/10).highlight("yellow")
self.animate(Transform(
self.play(Transform(
two, two_copy,
alpha_func = squish_alpha_func(
lambda t : wiggle(t),
@@ -203,12 +203,12 @@ class TauPoem(Scene):
)
self.add(two_pi)
self.dither()
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
two_pi, sphere,
alpha_func = lambda t : 2*smooth(t/2)
))
self.remove(two_pi)
self.animate(CounterclockwiseTransform(
self.play(CounterclockwiseTransform(
sphere, tau,
alpha_func = lambda t : 2*(smooth(t/2+0.5)-0.5)
))
@@ -227,11 +227,11 @@ class TauPoem(Scene):
for eye in blinked.eyes:
eye.highlight("black")
self.add(*set(tau.parts).difference(tau.white_parts))
self.animate(*[
self.play(*[
Transform(*eyes)
for eyes in zip(blinked.eyes, tau.eyes)
])
self.animate(ShowCreation(tau.mouth))
self.play(ShowCreation(tau.mouth))
self.dither(2)
def line3(self):
@@ -239,17 +239,17 @@ class TauPoem(Scene):
pi = PiCreature()
self.add(*tau.parts)
self.dither()
self.animate(
self.play(
Transform(tau.leg, pi.left_leg),
ShowCreation(pi.right_leg),
run_time = 1.0,
)
self.animate(*[
self.play(*[
Transform(*parts)
for parts in zip(tau.white_parts, pi.white_parts)
])
self.remove(*tau.parts + pi.parts)
self.animate(BlinkPiCreature(pi))
self.play(BlinkPiCreature(pi))
def pi_speaking(self, text):
pi = PiCreature()
@@ -263,7 +263,7 @@ class TauPoem(Scene):
pi, bubble = self.pi_speaking("Conventions matter \\\\ not!")
self.add(pi)
self.dither()
self.animate(Transform(
self.play(Transform(
Point(bubble.tip).highlight("black"),
bubble
))
@@ -280,11 +280,11 @@ class TauPoem(Scene):
formulae = tex_mobject(FORMULAE, size = "\\small")
formulae.scale(1.25)
formulae.to_corner([1, -1, 0])
self.animate(FadeIn(formulae))
self.play(FadeIn(formulae))
def line6(self):
bubble = ThoughtBubble()
self.animate(ApplyFunction(
self.play(ApplyFunction(
lambda p : 2 * p / np.linalg.norm(p),
bubble,
alpha_func = wiggle,
@@ -302,10 +302,10 @@ class TauPoem(Scene):
self.dither()
self.remove(bubble)
bubble_copy = deepcopy(bubble)
self.animate(CounterclockwiseTransform(bubble_copy, heart))
self.play(CounterclockwiseTransform(bubble_copy, heart))
self.dither()
self.remove(bubble_copy)
self.animate(CounterclockwiseTransform(heart, bubble))
self.play(CounterclockwiseTransform(heart, bubble))
self.dither()
@@ -316,7 +316,7 @@ class TauPoem(Scene):
self.add(two, *pi.parts)
self.dither()
self.animate(
self.play(
Transform(pi.left_leg, tau.leg),
Transform(
pi.right_leg,
@@ -343,10 +343,10 @@ class TauPoem(Scene):
self.add(tau)
self.dither()
self.animate(Transform(point, pi))
self.play(Transform(point, pi))
self.remove(point)
self.add(pi)
self.animate(WaveArm(tau),Transform(pi, new_pi))
self.play(WaveArm(tau),Transform(pi, new_pi))
def line10(self):
formulae = tex_mobject(FORMULAE, "\\small")
@@ -363,7 +363,7 @@ class TauPoem(Scene):
mob.to_edge(LEFT).shift(RIGHT*(SPACE_WIDTH-1))
else:
mob.shift(2*SPACE_WIDTH*RIGHT)
self.animate(*[
self.play(*[
Transform(*mobs, run_time = 2.0)
for mobs in zip(formulae, f_copy)
])
@@ -402,7 +402,7 @@ class TauPoem(Scene):
tau.shift(tau_line.get_center() + 0.5*UP)
self.add(axes, grid)
self.animate(
self.play(
TransformAnimations(
ShowCreation(sine),
ShowCreation(deepcopy(sine).shift(2*np.pi*interval_size*RIGHT)),
@@ -411,7 +411,7 @@ class TauPoem(Scene):
),
ShowCreation(circle)
)
self.animate(
self.play(
CounterclockwiseTransform(sine_period, tau_line),
CounterclockwiseTransform(circle, deepcopy(tau_line)),
FadeOut(axes),
@@ -435,9 +435,9 @@ class TauPoem(Scene):
self.add(*formula)
self.dither()
self.animate(CounterclockwiseTransform(two_pi, tau))
self.play(CounterclockwiseTransform(two_pi, tau))
self.remove(two_pi)
self.animate(BlinkPiCreature(tau))
self.play(BlinkPiCreature(tau))
self.dither()
def line14(self):
@@ -445,7 +445,7 @@ class TauPoem(Scene):
"Wait! Area \\\\ of circles"
)
self.add(pi)
self.animate(
self.play(
Transform(Point(bubble.tip).highlight("black"), bubble)
)
@@ -461,7 +461,7 @@ class TauPoem(Scene):
self.add(pi, bubble, *formula)
self.dither(2)
self.animate(ApplyMethod(half.highlight, "yellow"))
self.play(ApplyMethod(half.highlight, "yellow"))
def line16(self):
self.add(tex_mobject(
@@ -498,9 +498,9 @@ class TauPoem(Scene):
for line in lines:
line.highlight("red")
self.animate(ApplyFunction(trianglify, circle, run_time = 2.0))
self.play(ApplyFunction(trianglify, circle, run_time = 2.0))
self.add(tau_r, r)
self.animate(*[
self.play(*[
ShowCreation(line, run_time = 1.0)
for line in lines
])
@@ -521,7 +521,7 @@ class TauPoem(Scene):
self.add(*pi.parts + tau.parts)
self.dither(0.8)
self.animate(*[
self.play(*[
Transform(*eyes, run_time = 0.2, alpha_func = rush_into)
for eyes in [
(tau.left_eye, blinked_tau.left_eye),
@@ -529,7 +529,7 @@ class TauPoem(Scene):
]
])
self.remove(tau.left_eye, tau.right_eye)
self.animate(*[
self.play(*[
Transform(*eyes, run_time = 0.2, alpha_func = rush_from)
for eyes in [
(blinked_tau.left_eye, mad_tau.left_eye),
@@ -538,7 +538,7 @@ class TauPoem(Scene):
])
self.remove(blinked_tau.left_eye, blinked_tau.right_eye)
self.add(mad_tau.left_eye, mad_tau.right_eye)
self.animate(
self.play(
Transform(tau.arm, mad_tau.arm),
Transform(tau.mouth, mad_tau.mouth),
run_time = 0.5
@@ -546,7 +546,7 @@ class TauPoem(Scene):
self.remove(*tau.parts + blinked_tau.parts)
self.add(*mad_tau.parts)
self.animate(*[
self.play(*[
Transform(*eyes, run_time = 0.2, alpha_func = rush_into)
for eyes in [
(pi.left_eye, blinked_pi.left_eye),
@@ -554,7 +554,7 @@ class TauPoem(Scene):
]
])
self.remove(pi.left_eye, pi.right_eye)
self.animate(*[
self.play(*[
Transform(*eyes, run_time = 0.2, alpha_func = rush_from)
for eyes in [
(blinked_pi.left_eye, sad_pi.left_eye),
@@ -564,7 +564,7 @@ class TauPoem(Scene):
Transform(pi.mouth, sad_pi.mouth, run_time = 0.2)
])
self.remove(*blinked_pi.parts + pi.parts + sad_pi.parts)
self.animate(
self.play(
WalkPiCreature(sad_pi, DOWN+4*LEFT),
run_time = 1.0
)