Preliminary end to eoc/chapter1 animations

This commit is contained in:
Grant Sanderson 2016-11-13 11:35:06 -08:00
parent f7f2384eca
commit 4d60a245f6
2 changed files with 344 additions and 39 deletions

View file

@ -38,6 +38,7 @@ class CircleScene(PiCreatureScene):
"dR_color" : YELLOW,
"unwrapped_tip" : ORIGIN,
"include_pi_creature" : False,
"circle_corner" : UP+LEFT
}
def setup(self):
self.circle = Circle(
@ -46,7 +47,7 @@ class CircleScene(PiCreatureScene):
fill_color = self.fill_color,
fill_opacity = self.fill_opacity,
)
self.circle.to_corner(UP+LEFT, buff = 2*MED_BUFF)
self.circle.to_corner(self.circle_corner, buff = 2*MED_BUFF)
self.radius_line = Line(
self.circle.get_center(),
self.circle.get_right(),
@ -94,7 +95,7 @@ class CircleScene(PiCreatureScene):
Animation(self.radius_label),
)
def increase_radius(self, run_time = 2):
def increase_radius(self, numerical_dr = True, run_time = 2):
radius_mobs = VGroup(
self.radius_line, self.radius_brace, self.radius_label
)
@ -110,7 +111,10 @@ class CircleScene(PiCreatureScene):
buff = SMALL_BUFF,
tip_length = 0.2,
)
nudge_label = TexMobject("%.01f"%self.dR)
if numerical_dr:
nudge_label = TexMobject("%.01f"%self.dR)
else:
nudge_label = TexMobject("dr")
nudge_label.highlight(self.dR_color)
nudge_label.scale(0.75)
nudge_label.next_to(nudge_arrow.get_start(), DOWN)
@ -237,6 +241,7 @@ class OpeningQuote(Scene):
class Introduction(TeacherStudentsScene):
def construct(self):
self.show_series()
self.look_to_center()
self.go_through_students()
self.zoom_in_on_first()
@ -302,6 +307,20 @@ class Introduction(TeacherStudentsScene):
]
)
def look_to_center(self):
anims = []
for pi in self.get_everyone():
anims += [
pi.change_mode, "pondering",
pi.look_at, 2*UP
]
self.play(*anims)
self.random_blink(6)
self.play(*[
ApplyMethod(pi.change_mode, "happy")
for pi in self.get_everyone()
])
def go_through_students(self):
pi1, pi2, pi3 = self.get_students()
for pi in pi1, pi2, pi3:
@ -312,7 +331,7 @@ class Introduction(TeacherStudentsScene):
TexMobject("\\int_0^1 \\frac{1}{1-x^2}\\,dx").shift(UP+LEFT),
TexMobject("\\frac{d}{dx} e^x = e^x").shift(DOWN+RIGHT),
)
cant_wait = TextMobject("I litterally \\\\ can't wait")
cant_wait = TextMobject("I literally \\\\ can't wait")
big_derivative = TexMobject("""
\\frac{d}{dx} \\left( \\sin(x^2)2^{\\sqrt{x}} \\right)
""")
@ -461,6 +480,38 @@ class IntroduceCircle(Scene):
)
self.dither()
class HeartOfCalculus(GraphScene):
CONFIG = {
"x_labeled_nums" : [],
"y_labeled_nums" : [],
}
def construct(self):
self.setup_axes()
self.graph_function(lambda x : 3*np.sin(x/2) + x)
rect_sets = [
self.get_riemann_rectangles(
0, self.x_max, 1./(2**n), stroke_width = 1./(n+1)
)
for n in range(6)
]
rects = rect_sets.pop(0)
rects.save_state()
rects.stretch_to_fit_height(0)
rects.shift(
(self.graph_origin[1] - rects.get_center()[1])*UP
)
self.play(
rects.restore,
submobject_mode = "lagged_start",
run_time = 3
)
while rect_sets:
self.play(
Transform(rects, rect_sets.pop(0)),
run_time = 2
)
class PragmatismToArt(Scene):
def construct(self):
morty = Mortimer()
@ -759,6 +810,14 @@ class IntroduceTinyChangeInArea(CircleScene):
morty.to_corner(DOWN+RIGHT)
return morty
class CleanUpABit(TeacherStudentsScene):
def construct(self):
self.teacher_says("""
Let's clean that
up a bit
""")
self.random_blink(2)
class BuildToDADR(CircleScene):
CONFIG = {
"include_pi_creature" : True,
@ -839,6 +898,15 @@ class BuildToDADR(CircleScene):
))
self.play(*[term.denom.restore for term in terms])
self.dither(2)
self.play(
self.outer_ring.highlight, YELLOW,
rate_func = there_and_back
)
self.play(
self.nudge_label.scale_in_place, 2,
rate_func = there_and_back
)
self.dither(2)
canceleres = VGroup(self.circum_term[1], self.circum_term.denom)
self.play(canceleres.highlight, RED)
self.play(FadeOut(canceleres))
@ -991,6 +1059,15 @@ class BuildToDADR(CircleScene):
self.play(*map(Write, [arrow, ignore_error]))
self.play(error_group.fade, 0.8)
self.dither(2)
equality_brace = Brace(VGroup(self.change.denom, self.circum_term))
equal_word = equality_brace.get_text("Equality")
VGroup(equality_brace, equal_word).highlight(BLUE)
self.play(
GrowFromCenter(equality_brace),
Write(equal_word, run_time = 1)
)
self.dither(2)
self.play(*map(FadeOut, [equality_brace, equal_word]))
less_wrong_philosophy = TextMobject("``Less wrong'' philosophy")
less_wrong_philosophy.move_to(ignore_error, LEFT)
@ -1093,24 +1170,20 @@ class BuildToDADR(CircleScene):
self.play(self.pi_creature.change_mode, "guilty")
self.dither()
d_something = TextMobject("$d$(something)")
VGroup(*d_something[1:]).highlight(BLUE)
brace = Brace(d_something)
text = brace.get_text("""
Tiny change to
that something
""")
VGroup(*text[16:]).highlight(BLUE)
d_understanding = VGroup(d_something, brace, text)
d_understanding.move_to(self.less_wrong_philosophy, UP+LEFT)
new_bubble = self.pi_creature.get_bubble("speech", height = 6)
new_bubble.set_fill(BLACK, opacity = 0.8)
new_bubble.resize_to_content()
new_bubble.pin_to(self.pi_creature)
new_bubble.write("But it gets \\\\ less wrong!")
self.play(
FadeOut(bubble),
FadeOut(bubble.content),
Transform(self.less_wrong_philosophy, d_understanding),
randy.change_mode, "pondering",
ShowCreation(new_bubble),
Write(new_bubble.content),
randy.change_mode, "erm",
randy.highlight, BLUE_E,
self.pi_creature.change_mode, "speaking"
self.pi_creature.change_mode, "shruggie"
)
self.dither(2)
@ -1999,24 +2072,228 @@ class GraphIntegral(GraphScene):
self.dither()
def get_rectangles(self, dr, stroke_width = 1):
rectangles = VGroup()
for r in np.arange(0, self.R, dr):
points = VGroup(
VectorizedPoint(self.coords_to_point(r, 0)),
VectorizedPoint(self.coords_to_point(r+dr, 2*np.pi*r)),
)
rect = Rectangle()
rect.replace(points, stretch = True)
rect.set_fill(opacity = 1)
rectangles.add(rect)
rectangles.gradient_highlight(BLUE, GREEN)
rectangles.set_stroke(BLACK, width = stroke_width)
return rectangles
return self.get_riemann_rectangles(
0, self.R, dr, stroke_width = stroke_width
)
class FundamentalTheorem(CircleScene):
CONFIG = {
"circle_corner" : ORIGIN,
"radius" : 1.5,
"area_color" : BLUE,
"circum_color" : WHITE,
"unwrapped_tip" : 2.5*UP,
"include_pi_creature" : False
}
def setup(self):
CircleScene.setup(self)
group = VGroup(
self.circle, self.radius_line,
self.radius_brace, self.radius_label
)
self.remove(*group)
group.shift(DOWN)
self.foreground_group = VGroup(
self.radius_line,
self.radius_brace,
self.radius_label,
)
def get_pi_creature(self):
morty = Mortimer()
morty.scale(0.7)
morty.to_corner(DOWN+RIGHT)
return morty
def construct(self):
self.add_derivative_terms()
self.add_integral_terms()
self.think_about_it()
self.bring_in_circle()
self.show_outer_ring()
self.show_all_rings()
self.emphasize_oposites()
def add_derivative_terms(self):
symbolic = TexMobject(
"\\frac{d(\\pi R^2)}{dR} =", "2\\pi R"
)
VGroup(*symbolic[0][2:5]).highlight(self.area_color)
VGroup(*symbolic[0][7:9]).highlight(self.dR_color)
symbolic[1].highlight(self.circum_color)
geometric = TexMobject("\\frac{d \\quad}{dR}=")
VGroup(*geometric[2:4]).highlight(self.dR_color)
radius = geometric[0].get_height()
area_circle = Circle(
stroke_width = 0,
fill_color = self.area_color,
fill_opacity = 0.5,
radius = radius
)
area_circle.next_to(geometric[0], buff = SMALL_BUFF)
circum_circle = Circle(
color = self.circum_color,
radius = radius
)
circum_circle.next_to(geometric, RIGHT)
geometric.add(area_circle, circum_circle)
self.derivative_terms = VGroup(symbolic, geometric)
self.derivative_terms.arrange_submobjects(
DOWN, buff = LARGE_BUFF, aligned_edge = LEFT
)
self.derivative_terms.next_to(ORIGIN, LEFT, buff = LARGE_BUFF)
self.play(
Write(self.derivative_terms),
self.pi_creature.change_mode, "hooray"
)
self.dither()
def add_integral_terms(self):
symbolic = TexMobject(
"\\int_0^R", "2\\pi r", "\\cdot", "dr", "=", "\\pi R^2"
)
symbolic.highlight_by_tex("2\\pi r", self.circum_color)
symbolic.highlight_by_tex("dr", self.dR_color)
symbolic.highlight_by_tex("\\pi R^2", self.area_color)
geometric = symbolic.copy()
area_circle = Circle(
radius = geometric[-1].get_width()/2,
stroke_width = 0,
fill_color = self.area_color,
fill_opacity = 0.5
)
area_circle.move_to(geometric[-1])
circum_circle = Circle(
radius = geometric[1].get_width()/2,
color = self.circum_color
)
circum_circle.move_to(geometric[1])
geometric.submobjects[1] = circum_circle
geometric.submobjects[-1] = area_circle
self.integral_terms = VGroup(symbolic, geometric)
self.integral_terms.arrange_submobjects(
DOWN,
buff = LARGE_BUFF,
aligned_edge = LEFT
)
self.integral_terms.next_to(ORIGIN, RIGHT, buff = LARGE_BUFF)
self.play(Write(self.integral_terms))
self.dither()
def think_about_it(self):
for mode in "confused", "pondering", "surprised":
self.change_mode(mode)
self.dither()
def bring_in_circle(self):
self.play(
FadeOut(self.derivative_terms[0]),
FadeOut(self.integral_terms[0]),
self.derivative_terms[1].to_corner, UP+LEFT, 2*MED_BUFF,
self.integral_terms[1].to_corner, UP+RIGHT, 2*MED_BUFF,
self.pi_creature.change_mode, "speaking"
)
self.introduce_circle()
def show_outer_ring(self):
self.increase_radius(numerical_dr = False)
self.foreground_group.add(self.nudge_line, self.nudge_arrow)
self.dither()
ring_copy = self.outer_ring.copy()
ring_copy.save_state()
self.unwrap_ring(ring_copy, to_edge = LEFT)
brace = Brace(ring_copy, UP)
brace.stretch_in_place(0.95, 0)
deriv = brace.get_text("$\\dfrac{dA}{dR}$")
VGroup(*deriv[:2]).highlight(self.outer_ring.get_color())
VGroup(*deriv[-2:]).highlight(self.dR_color)
self.play(
GrowFromCenter(brace),
Write(deriv),
self.pi_creature.change_mode, "happy"
)
self.to_fade = VGroup(deriv, brace)
self.to_restore = ring_copy
def show_all_rings(self):
rings = VGroup(*[
self.get_ring(radius = r, dR = self.dR)
for r in np.arange(0, self.radius, self.dR)
])
rings.gradient_highlight(BLUE_E, GREEN_E)
rings.save_state()
integrand = self.integral_terms[1][1]
for ring in rings:
Transform(ring, integrand).update(1)
self.play(
ApplyMethod(
rings.restore,
submobject_mode = "lagged_start",
run_time = 5
),
Animation(self.foreground_group),
)
def emphasize_oposites(self):
self.play(
FadeOut(self.to_fade),
self.to_restore.restore,
Animation(self.foreground_group),
run_time = 2
)
arrow = DoubleArrow(
self.derivative_terms[1],
self.integral_terms[1],
)
opposites = TextMobject("Opposites")
opposites.next_to(arrow, DOWN)
self.play(
ShowCreation(arrow),
Write(opposites)
)
self.dither()
class NameTheFundamentalTheorem(TeacherStudentsScene):
def construct(self):
symbols = TexMobject(
"\\frac{d}{dx} \\int_0^x f(t)dt = f(x)",
)
symbols.to_corner(UP+LEFT)
brace = Brace(symbols)
abstract = brace.get_text("Abstract version")
self.add(symbols)
self.play(
GrowFromCenter(brace),
Write(abstract),
*[
ApplyMethod(pi.look_at, symbols)
for pi in self.get_everyone()
]
)
self.change_student_modes("pondering", "confused", "erm")
self.random_blink()
self.teacher_says("""
This is known as
the ``fundamental
theorem of calculus''
""", width = 5, height = 5, target_mode = "hooray")
self.random_blink(3)
self.teacher_says("""
We'll get here
in due time.
""")
self.change_student_modes(*["happy"]*3)
self.dither(2)

View file

@ -3,10 +3,11 @@ from helpers import *
from scene import Scene
# from topics.geometry import
from mobject.tex_mobject import TexMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VGroup, VectorizedPoint
from animation.simple_animations import Write, ShowCreation
from topics.number_line import NumberLine
from topics.functions import ParametricFunction
from topics.geometry import Rectangle
class GraphScene(Scene):
CONFIG = {
@ -40,7 +41,8 @@ class GraphScene(Scene):
color = self.axes_color
)
x_axis.shift(self.graph_origin - x_axis.number_to_point(0))
x_axis.add_numbers(*self.x_labeled_nums)
if self.x_labeled_nums:
x_axis.add_numbers(*self.x_labeled_nums)
x_label = TexMobject(self.x_axis_label)
x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF)
@ -56,8 +58,9 @@ class GraphScene(Scene):
)
y_axis.shift(self.graph_origin-y_axis.number_to_point(0))
y_axis.rotate(np.pi/2, about_point = y_axis.number_to_point(0))
y_axis.add_numbers(*self.y_labeled_nums)
y_axis.numbers.shift(self.y_axis_numbers_nudge)
if self.y_labeled_nums:
y_axis.add_numbers(*self.y_labeled_nums)
y_axis.numbers.shift(self.y_axis_numbers_nudge)
y_label = TexMobject(self.y_axis_label)
y_label.next_to(y_axis.get_top(), RIGHT, buff = 2*MED_BUFF)
@ -87,6 +90,7 @@ class GraphScene(Scene):
if is_main_graph:
self.graph = graph
self.func = func
if animate:
self.play(ShowCreation(graph))
self.add(graph)
@ -120,6 +124,30 @@ class GraphScene(Scene):
self.add(label)
return label
def get_riemann_rectangles(self,
x_min = None,
x_max = None,
dx = 0.1,
stroke_width = 1,
start_color = BLUE,
end_color = GREEN):
assert(hasattr(self, "func"))
x_min = x_min if x_min is not None else self.x_min
x_max = x_max if x_max is not None else self.x_max
rectangles = VGroup()
for x in np.arange(x_min, x_max, dx):
points = VGroup(*map(VectorizedPoint, [
self.coords_to_point(x, 0),
self.coords_to_point(x+dx, self.func(x+dx)),
]))
rect = Rectangle()
rect.replace(points, stretch = True)
rect.set_fill(opacity = 1)
rectangles.add(rect)
rectangles.gradient_highlight(start_color, end_color)
rectangles.set_stroke(BLACK, width = stroke_width)
return rectangles