mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 08:54:38 +08:00
Up to BuildToDADR in eoc chapter1
This commit is contained in:
652
eoc/chapter1.py
652
eoc/chapter1.py
@ -23,7 +23,7 @@ from camera import Camera
|
|||||||
from mobject.svg_mobject import *
|
from mobject.svg_mobject import *
|
||||||
from mobject.tex_mobject import *
|
from mobject.tex_mobject import *
|
||||||
|
|
||||||
class CircleScene(Scene):
|
class CircleScene(PiCreatureScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"radius" : 1.5,
|
"radius" : 1.5,
|
||||||
"stroke_color" : WHITE,
|
"stroke_color" : WHITE,
|
||||||
@ -32,7 +32,9 @@ class CircleScene(Scene):
|
|||||||
"radial_line_color" : MAROON_B,
|
"radial_line_color" : MAROON_B,
|
||||||
"outer_ring_color" : GREEN_E,
|
"outer_ring_color" : GREEN_E,
|
||||||
"dR" : 0.1,
|
"dR" : 0.1,
|
||||||
|
"dR_color" : YELLOW,
|
||||||
"unwrapped_tip" : ORIGIN,
|
"unwrapped_tip" : ORIGIN,
|
||||||
|
"include_pi_creature" : False,
|
||||||
}
|
}
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.circle = Circle(
|
self.circle = Circle(
|
||||||
@ -48,14 +50,21 @@ class CircleScene(Scene):
|
|||||||
color = self.radial_line_color
|
color = self.radial_line_color
|
||||||
)
|
)
|
||||||
self.radius_brace = Brace(self.radius_line, buff = SMALL_BUFF)
|
self.radius_brace = Brace(self.radius_line, buff = SMALL_BUFF)
|
||||||
self.radius_label = self.radius_brace.get_text("R", buff = SMALL_BUFF)
|
self.radius_label = self.radius_brace.get_text("$R$", buff = SMALL_BUFF)
|
||||||
|
|
||||||
self.add(
|
self.add(
|
||||||
self.circle, self.radius_line,
|
self.circle, self.radius_line,
|
||||||
self.radius_brace, self.radius_label
|
self.radius_brace, self.radius_label
|
||||||
)
|
)
|
||||||
|
|
||||||
def introduce_circle(self):
|
self.pi_creature = self.get_pi_creature()
|
||||||
|
if self.include_pi_creature:
|
||||||
|
self.add(self.pi_creature)
|
||||||
|
|
||||||
|
def get_pi_creature(self):
|
||||||
|
return Mortimer().to_corner(DOWN+RIGHT)
|
||||||
|
|
||||||
|
def introduce_circle(self, added_anims = []):
|
||||||
self.remove(self.circle)
|
self.remove(self.circle)
|
||||||
self.play(
|
self.play(
|
||||||
ShowCreation(self.radius_line),
|
ShowCreation(self.radius_line),
|
||||||
@ -70,6 +79,7 @@ class CircleScene(Scene):
|
|||||||
about_point = self.circle.get_center(),
|
about_point = self.circle.get_center(),
|
||||||
),
|
),
|
||||||
ShowCreation(self.circle),
|
ShowCreation(self.circle),
|
||||||
|
*added_anims,
|
||||||
run_time = 2
|
run_time = 2
|
||||||
)
|
)
|
||||||
self.play(
|
self.play(
|
||||||
@ -92,10 +102,11 @@ class CircleScene(Scene):
|
|||||||
nudge_line.get_center() + 0.5*RIGHT+DOWN,
|
nudge_line.get_center() + 0.5*RIGHT+DOWN,
|
||||||
nudge_line.get_center(),
|
nudge_line.get_center(),
|
||||||
color = YELLOW,
|
color = YELLOW,
|
||||||
buff = 0.025,
|
buff = SMALL_BUFF,
|
||||||
tip_length = 0.2,
|
tip_length = 0.2,
|
||||||
)
|
)
|
||||||
nudge_label = TexMobject("%.01f"%self.dR)
|
nudge_label = TexMobject("%.01f"%self.dR)
|
||||||
|
nudge_label.highlight(self.dR_color)
|
||||||
nudge_label.scale(0.75)
|
nudge_label.scale(0.75)
|
||||||
nudge_label.next_to(nudge_arrow.get_start(), DOWN)
|
nudge_label.next_to(nudge_arrow.get_start(), DOWN)
|
||||||
|
|
||||||
@ -103,19 +114,18 @@ class CircleScene(Scene):
|
|||||||
|
|
||||||
outer_ring = self.get_outer_ring()
|
outer_ring = self.get_outer_ring()
|
||||||
|
|
||||||
self.play(ShowCreation(nudge_line))
|
|
||||||
self.play(
|
self.play(
|
||||||
|
FadeIn(outer_ring),
|
||||||
|
ShowCreation(nudge_line),
|
||||||
ShowCreation(nudge_arrow),
|
ShowCreation(nudge_arrow),
|
||||||
Write(nudge_label)
|
Write(nudge_label),
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(
|
self.nudge_line = nudge_line
|
||||||
FadeIn(outer_ring),
|
self.nudge_arrow = nudge_arrow
|
||||||
*map(Animation, radius_mobs)
|
self.nudge_label = nudge_label
|
||||||
)
|
|
||||||
return outer_ring
|
return outer_ring
|
||||||
|
|
||||||
|
|
||||||
def get_ring(self, radius, dR, color = GREEN):
|
def get_ring(self, radius, dR, color = GREEN):
|
||||||
ring = Circle(radius = radius + dR).center()
|
ring = Circle(radius = radius + dR).center()
|
||||||
inner_ring = Circle(radius = radius)
|
inner_ring = Circle(radius = radius)
|
||||||
@ -134,10 +144,11 @@ class CircleScene(Scene):
|
|||||||
color = self.outer_ring_color
|
color = self.outer_ring_color
|
||||||
)
|
)
|
||||||
|
|
||||||
def unwrap_ring(self, ring):
|
def unwrap_ring(self, ring, **kwargs):
|
||||||
self.unwrap_rings(ring)
|
self.unwrap_rings(ring, **kwargs)
|
||||||
|
|
||||||
def unwrap_rings(self, *rings):
|
def unwrap_rings(self, *rings, **kwargs):
|
||||||
|
added_anims = kwargs.get("added_anims", [])
|
||||||
rings = VGroup(*rings)
|
rings = VGroup(*rings)
|
||||||
unwrapped = VGroup(*[
|
unwrapped = VGroup(*[
|
||||||
self.get_unwrapped(ring)
|
self.get_unwrapped(ring)
|
||||||
@ -149,10 +160,10 @@ class CircleScene(Scene):
|
|||||||
run_time = 2,
|
run_time = 2,
|
||||||
path_arc = np.pi/2
|
path_arc = np.pi/2
|
||||||
)
|
)
|
||||||
self.play(Transform(
|
self.play(
|
||||||
rings, unwrapped,
|
Transform(rings, unwrapped, run_time = 3),
|
||||||
run_time = 3,
|
*added_anims
|
||||||
))
|
)
|
||||||
|
|
||||||
def get_unwrapped(self, ring):
|
def get_unwrapped(self, ring):
|
||||||
R = ring.R
|
R = ring.R
|
||||||
@ -174,6 +185,7 @@ class CircleScene(Scene):
|
|||||||
)
|
)
|
||||||
result.move_to(self.unwrapped_tip, aligned_edge = DOWN)
|
result.move_to(self.unwrapped_tip, aligned_edge = DOWN)
|
||||||
result.shift(R_plus_dr*DOWN)
|
result.shift(R_plus_dr*DOWN)
|
||||||
|
result.to_edge(LEFT)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -442,22 +454,606 @@ class IntroduceCircle(Scene):
|
|||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
class IntroduceTinyChangeInArea(CircleScene):
|
class PragmatismToArt(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
new_area_form, minus area_form = expression = TexMobject(
|
morty = Mortimer()
|
||||||
|
morty.to_corner(DOWN+RIGHT)
|
||||||
|
morty.shift(LEFT)
|
||||||
|
pragmatism = TextMobject("Pragmatism")
|
||||||
|
art = TextMobject("Art")
|
||||||
|
pragmatism.move_to(morty.get_corner(UP+LEFT), aligned_edge = DOWN)
|
||||||
|
art.move_to(morty.get_corner(UP+RIGHT), aligned_edge = DOWN)
|
||||||
|
art.shift(0.2*(LEFT+UP))
|
||||||
|
|
||||||
|
circle1 = Circle(
|
||||||
|
radius = 2,
|
||||||
|
fill_opacity = 1,
|
||||||
|
fill_color = BLUE_E,
|
||||||
|
stroke_width = 0,
|
||||||
|
)
|
||||||
|
circle2 = Circle(
|
||||||
|
radius = 2,
|
||||||
|
stroke_color = YELLOW
|
||||||
|
)
|
||||||
|
arrow = DoubleArrow(LEFT, RIGHT, color = WHITE)
|
||||||
|
circle_group = VGroup(circle1, arrow, circle2)
|
||||||
|
circle_group.arrange_submobjects()
|
||||||
|
circle_group.to_corner(UP+LEFT)
|
||||||
|
circle2.save_state()
|
||||||
|
circle2.move_to(circle1)
|
||||||
|
q_marks = TextMobject("???").next_to(arrow, UP)
|
||||||
|
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "raise_right_hand",
|
||||||
|
morty.look_at, pragmatism,
|
||||||
|
Write(pragmatism, run_time = 1),
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "raise_left_hand",
|
||||||
|
morty.look_at, art,
|
||||||
|
Transform(
|
||||||
|
VectorizedPoint(morty.get_corner(UP+RIGHT)),
|
||||||
|
art
|
||||||
|
),
|
||||||
|
pragmatism.fade, 0.7,
|
||||||
|
pragmatism.rotate_in_place, np.pi/4,
|
||||||
|
pragmatism.shift, DOWN+LEFT
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(circle1),
|
||||||
|
morty.look_at, circle1
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(circle2))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(arrow),
|
||||||
|
Write(q_marks),
|
||||||
|
circle2.restore
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
|
||||||
|
class IntroduceTinyChangeInArea(CircleScene):
|
||||||
|
CONFIG = {
|
||||||
|
"include_pi_creature" : True,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
new_area_form, minus, area_form = expression = TexMobject(
|
||||||
"\\pi (R + 0.1)^2", "-", "\\pi R^2"
|
"\\pi (R + 0.1)^2", "-", "\\pi R^2"
|
||||||
)
|
)
|
||||||
expression.to_corner(UP+RIGHT, buff = 2*MED_BUFF)
|
VGroup(*new_area_form[4:7]).highlight(self.dR_color)
|
||||||
|
expression_brace = Brace(expression, UP)
|
||||||
|
change_in_area = expression_brace.get_text("Change in area")
|
||||||
|
change_in_area.highlight(self.outer_ring_color)
|
||||||
|
area_brace = Brace(area_form)
|
||||||
|
area_word = area_brace.get_text("Area")
|
||||||
|
area_word.highlight(BLUE)
|
||||||
|
new_area_brace = Brace(new_area_form)
|
||||||
|
new_area_word = new_area_brace.get_text("New area")
|
||||||
|
group = VGroup(
|
||||||
|
expression, expression_brace, change_in_area,
|
||||||
|
area_brace, area_word, new_area_brace, new_area_word
|
||||||
|
)
|
||||||
|
group.to_edge(UP).shift(RIGHT)
|
||||||
|
group.save_state()
|
||||||
|
area_group = VGroup(area_form, area_brace, area_word)
|
||||||
|
area_group.save_state()
|
||||||
|
area_group.next_to(self.circle, RIGHT, buff = LARGE_BUFF)
|
||||||
|
|
||||||
self.introduce_circle()
|
self.introduce_circle(
|
||||||
self.dither()
|
added_anims = [self.pi_creature.change_mode, "speaking"]
|
||||||
|
)
|
||||||
|
self.play(Write(area_group))
|
||||||
|
self.change_mode("happy")
|
||||||
outer_ring = self.increase_radius()
|
outer_ring = self.increase_radius()
|
||||||
self.dither()
|
self.dither()
|
||||||
# ring = self.get_outer_ring()
|
self.play(
|
||||||
|
area_group.restore,
|
||||||
|
GrowFromCenter(expression_brace),
|
||||||
|
Write(new_area_form),
|
||||||
|
Write(minus),
|
||||||
|
Write(change_in_area),
|
||||||
|
self.pi_creature.change_mode, "confused",
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Write(new_area_word),
|
||||||
|
GrowFromCenter(new_area_brace)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
group.fade, 0.7,
|
||||||
|
self.pi_creature.change_mode, "happy"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
outer_ring.highlight, YELLOW,
|
||||||
|
Animation(self.nudge_arrow),
|
||||||
|
Animation(self.nudge_line),
|
||||||
|
rate_func = there_and_back
|
||||||
|
)
|
||||||
|
self.show_unwrapping(outer_ring)
|
||||||
|
self.play(group.restore)
|
||||||
|
self.work_out_expression(group)
|
||||||
|
self.second_unwrapping(outer_ring)
|
||||||
|
insignificant = TextMobject("Insignificant")
|
||||||
|
insignificant.highlight(self.dR_color)
|
||||||
|
insignificant.move_to(self.error_words)
|
||||||
|
self.play(Transform(self.error_words, insignificant))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
big_rect = Rectangle(
|
||||||
|
width = 2*SPACE_WIDTH,
|
||||||
|
height = 2*SPACE_HEIGHT,
|
||||||
|
fill_color = BLACK,
|
||||||
|
fill_opacity = 0.85,
|
||||||
|
stroke_width = 0,
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
FadeIn(big_rect),
|
||||||
|
area_form.highlight, BLUE,
|
||||||
|
self.two_pi_R.highlight, GREEN,
|
||||||
|
self.pi_creature.change_mode, "happy"
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_unwrapping(self, outer_ring):
|
||||||
|
almost_rect = outer_ring.copy()
|
||||||
|
self.unwrap_ring(
|
||||||
|
almost_rect,
|
||||||
|
added_anims = [self.pi_creature.change_mode, "pondering"]
|
||||||
|
)
|
||||||
|
|
||||||
|
circum_brace = Brace(almost_rect, UP).scale_in_place(0.95)
|
||||||
|
dR_brace = TexMobject("\\}")
|
||||||
|
dR_brace.stretch(0.5, 1)
|
||||||
|
dR_brace.next_to(almost_rect, RIGHT)
|
||||||
|
two_pi_R = circum_brace.get_text("$2\\pi R$")
|
||||||
|
dR = TexMobject("$0.1$").scale(0.7).next_to(dR_brace, RIGHT)
|
||||||
|
dR.highlight(self.dR_color)
|
||||||
|
|
||||||
|
two_pi_R.generate_target()
|
||||||
|
dR.generate_target()
|
||||||
|
lp, rp = TexMobject("()")
|
||||||
|
change_in_area = TextMobject(
|
||||||
|
"Change in area $\\approx$"
|
||||||
|
)
|
||||||
|
final_area = VGroup(
|
||||||
|
change_in_area,
|
||||||
|
two_pi_R.target, lp, dR.target.scale(1./0.7), rp
|
||||||
|
)
|
||||||
|
final_area.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||||
|
final_area.next_to(almost_rect, DOWN, buff = 2*MED_BUFF)
|
||||||
|
final_area.highlight(GREEN_A)
|
||||||
|
final_area[3].highlight(self.dR_color)
|
||||||
|
change_in_area.shift(0.1*LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(circum_brace),
|
||||||
|
Write(two_pi_R)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(dR_brace),
|
||||||
|
Write(dR)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
MoveToTarget(two_pi_R.copy()),
|
||||||
|
MoveToTarget(dR.copy()),
|
||||||
|
Write(change_in_area, run_time = 1),
|
||||||
|
Write(lp),
|
||||||
|
Write(rp),
|
||||||
|
)
|
||||||
|
self.remove(*self.get_mobjects_from_last_animation())
|
||||||
|
self.add(final_area)
|
||||||
|
self.play(
|
||||||
|
self.pi_creature.change_mode, "happy",
|
||||||
|
self.pi_creature.look_at, final_area
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
group = VGroup(
|
||||||
|
almost_rect, final_area, two_pi_R, dR,
|
||||||
|
circum_brace, dR_brace
|
||||||
|
)
|
||||||
|
self.play(group.fade)
|
||||||
|
|
||||||
|
def work_out_expression(self, expression_group):
|
||||||
|
exp, exp_brace, title, area_brace, area_word, new_area_brace, new_area_word = expression_group
|
||||||
|
new_area_form, minus, area_form = exp
|
||||||
|
|
||||||
|
expanded = TexMobject(
|
||||||
|
"\\pi R^2", "+", "2\\pi R (0.1)",
|
||||||
|
"+", "\\pi (0.1)^2", "-", "\\pi R^2",
|
||||||
|
)
|
||||||
|
pi_R_squared, plus, two_pi_R_dR, plus2, pi_dR_squared, minus2, pi_R_squared2 = expanded
|
||||||
|
for subset in two_pi_R_dR[4:7], pi_dR_squared[2:5]:
|
||||||
|
VGroup(*subset).highlight(self.dR_color)
|
||||||
|
expanded.next_to(new_area_form, DOWN, aligned_edge = LEFT, buff = MED_BUFF)
|
||||||
|
expanded.shift(LEFT/2.)
|
||||||
|
|
||||||
|
faders = [area_brace, area_word, new_area_brace, new_area_word]
|
||||||
|
self.play(*map(FadeOut, faders))
|
||||||
|
trips = [
|
||||||
|
([0, 2, 8], pi_R_squared, plus),
|
||||||
|
([8, 0, 2, 1, 4, 5, 6, 7], two_pi_R_dR, plus2),
|
||||||
|
([0, 1, 4, 5, 6, 7, 8], pi_dR_squared, VGroup()),
|
||||||
|
]
|
||||||
|
to_remove = []
|
||||||
|
for subset, target, writer in trips:
|
||||||
|
starter = VGroup(
|
||||||
|
*np.array(list(new_area_form.copy()))[subset]
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Transform(starter, target, run_time = 2),
|
||||||
|
Write(writer)
|
||||||
|
)
|
||||||
|
to_remove += self.get_mobjects_from_last_animation()
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(minus.copy(), minus2),
|
||||||
|
Transform(area_form.copy(), pi_R_squared2),
|
||||||
|
)
|
||||||
|
to_remove += self.get_mobjects_from_last_animation()
|
||||||
|
self.remove(*to_remove)
|
||||||
|
self.add(self.pi_creature, *expanded)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(mob.highlight, RED)
|
||||||
|
for mob in pi_R_squared, pi_R_squared2
|
||||||
|
])
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(mob.fade, 0.7)
|
||||||
|
for mob in plus, pi_R_squared, pi_R_squared2, minus2
|
||||||
|
])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
approx_brace = Brace(two_pi_R_dR)
|
||||||
|
error_brace = Brace(pi_dR_squared, buff = SMALL_BUFF)
|
||||||
|
error_words = error_brace.get_text("Error", buff = SMALL_BUFF)
|
||||||
|
error_words.highlight(RED)
|
||||||
|
self.error_words = error_words
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(approx_brace),
|
||||||
|
self.pi_creature.change_mode, "hooray"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(error_brace),
|
||||||
|
Write(error_words),
|
||||||
|
self.pi_creature.change_mode, "confused"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.two_pi_R = VGroup(*two_pi_R_dR[:3])
|
||||||
|
|
||||||
|
def second_unwrapping(self, outer_ring):
|
||||||
|
almost_rect = outer_ring.copy()
|
||||||
|
rect = Rectangle(
|
||||||
|
width = 2*np.pi*self.radius,
|
||||||
|
height = self.dR,
|
||||||
|
fill_color = self.outer_ring_color,
|
||||||
|
fill_opacity = 1,
|
||||||
|
stroke_width = 0,
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
almost_rect.highlight, YELLOW,
|
||||||
|
self.pi_creature.change_mode, "pondering"
|
||||||
|
)
|
||||||
|
self.unwrap_ring(almost_rect)
|
||||||
|
self.dither()
|
||||||
|
rect.move_to(almost_rect)
|
||||||
|
self.play(FadeIn(rect))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def get_pi_creature(self):
|
||||||
|
morty = Mortimer()
|
||||||
|
morty.scale(0.7)
|
||||||
|
morty.to_corner(DOWN+RIGHT)
|
||||||
|
return morty
|
||||||
|
|
||||||
|
class BuildToDADR(CircleScene):
|
||||||
|
CONFIG = {
|
||||||
|
"include_pi_creature" : True,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.outer_ring = self.increase_radius()
|
||||||
|
self.write_initial_terms()
|
||||||
|
self.show_fractions()
|
||||||
|
self.transition_to_dR()
|
||||||
|
self.elaborate_on_d()
|
||||||
|
self.not_infinitely_small()
|
||||||
|
|
||||||
|
def get_pi_creature(self):
|
||||||
|
morty = Mortimer()
|
||||||
|
morty.flip()
|
||||||
|
morty.to_corner(DOWN+LEFT)
|
||||||
|
return morty
|
||||||
|
|
||||||
|
def write_initial_terms(self):
|
||||||
|
change = TextMobject("Change in area")
|
||||||
|
change.highlight(GREEN_B)
|
||||||
|
equals, two_pi_R, dR, plus, pi, dR2, squared = rhs = TexMobject(
|
||||||
|
"=", "2 \\pi R", "(0.1)", "+", "\\pi", "(0.1)", "^2"
|
||||||
|
)
|
||||||
|
VGroup(dR, dR2).highlight(self.dR_color)
|
||||||
|
change.next_to(self.circle, buff = LARGE_BUFF)
|
||||||
|
rhs.next_to(change)
|
||||||
|
|
||||||
|
circum_brace = Brace(two_pi_R, UP)
|
||||||
|
circum_text = circum_brace.get_text("Circumference")
|
||||||
|
error_brace = Brace(VGroup(pi, squared), UP)
|
||||||
|
error_text = error_brace.get_text("Error")
|
||||||
|
error_text.highlight(RED)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(change, run_time = 1),
|
||||||
|
self.pi_creature.change_mode, "pondering",
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(*it.chain(
|
||||||
|
map(Write, [equals, two_pi_R, dR]),
|
||||||
|
map(FadeIn, [circum_text, circum_brace])
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
self.play(*it.chain(
|
||||||
|
map(Write, [plus, pi, dR2, squared]),
|
||||||
|
map(FadeIn, [error_brace, error_text])
|
||||||
|
))
|
||||||
|
self.dither(2)
|
||||||
|
self.change = change
|
||||||
|
self.circum_term = VGroup(two_pi_R, dR)
|
||||||
|
self.circum_term.label = VGroup(circum_brace, circum_text)
|
||||||
|
self.error_term = VGroup(pi, dR2, squared)
|
||||||
|
self.error_term.label = VGroup(error_brace, error_text)
|
||||||
|
self.equals = equals
|
||||||
|
self.plus = plus
|
||||||
|
|
||||||
|
def show_fractions(self):
|
||||||
|
terms = [self.change, self.circum_term, self.error_term]
|
||||||
|
for term in terms:
|
||||||
|
term.frac_line = TexMobject("\\frac{\\quad}{\\quad}")
|
||||||
|
term.frac_line.stretch_to_fit_width(term.get_width())
|
||||||
|
term.frac_line.next_to(term, DOWN, buff = SMALL_BUFF)
|
||||||
|
term.denom = TexMobject("(0.1)")
|
||||||
|
term.denom.next_to(term.frac_line, DOWN, buff = SMALL_BUFF)
|
||||||
|
term.denom.highlight(self.dR_color)
|
||||||
|
term.denom.save_state()
|
||||||
|
term.denom.replace(self.nudge_label)
|
||||||
|
|
||||||
|
self.equals.generate_target()
|
||||||
|
self.equals.target.next_to(self.change.frac_line, RIGHT)
|
||||||
|
self.plus.generate_target()
|
||||||
|
self.plus.target.next_to(self.circum_term.frac_line, RIGHT)
|
||||||
|
|
||||||
|
self.play(*it.chain(
|
||||||
|
[Write(term.frac_line) for term in terms],
|
||||||
|
map(MoveToTarget, [self.equals, self.plus])
|
||||||
|
))
|
||||||
|
self.play(*[term.denom.restore for term in terms])
|
||||||
|
self.dither(2)
|
||||||
|
canceleres = VGroup(self.circum_term[1], self.circum_term.denom)
|
||||||
|
self.play(canceleres.highlight, RED)
|
||||||
|
self.play(FadeOut(canceleres))
|
||||||
|
self.remove(self.circum_term)
|
||||||
|
self.play(
|
||||||
|
self.circum_term[0].move_to, self.circum_term.frac_line, LEFT,
|
||||||
|
self.circum_term[0].shift, 0.1*UP,
|
||||||
|
FadeOut(self.circum_term.frac_line),
|
||||||
|
MaintainPositionRelativeTo(
|
||||||
|
self.circum_term.label,
|
||||||
|
self.circum_term[0]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.circum_term = self.circum_term[0]
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
FadeOut(self.error_term[-1]),
|
||||||
|
FadeOut(self.error_term.denom)
|
||||||
|
)
|
||||||
|
self.error_term.remove(self.error_term[-1])
|
||||||
|
self.play(
|
||||||
|
self.error_term.move_to, self.error_term.frac_line,
|
||||||
|
self.error_term.shift, 0.3*LEFT + 0.15*UP,
|
||||||
|
FadeOut(self.error_term.frac_line),
|
||||||
|
self.plus.shift, 0.7*LEFT + 0.1*UP,
|
||||||
|
MaintainPositionRelativeTo(
|
||||||
|
self.error_term.label,
|
||||||
|
self.error_term
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def transition_to_dR(self):
|
||||||
|
dRs = VGroup(
|
||||||
|
self.nudge_label,
|
||||||
|
self.change.denom,
|
||||||
|
self.error_term[1],
|
||||||
|
)
|
||||||
|
error_brace, error_text = self.error_term.label
|
||||||
|
for s, width in ("(0.01)", 0.05), ("(0.001)", 0.03), ("dR", 0.03):
|
||||||
|
new_dRs = VGroup(*[
|
||||||
|
TexMobject(s).move_to(mob, LEFT)
|
||||||
|
for mob in dRs
|
||||||
|
])
|
||||||
|
new_dRs.highlight(self.dR_color)
|
||||||
|
new_outer_ring = self.get_ring(self.radius, width)
|
||||||
|
new_nudge_line = self.nudge_line.copy()
|
||||||
|
new_nudge_line.scale_to_fit_width(width)
|
||||||
|
new_nudge_line.move_to(self.nudge_line, LEFT)
|
||||||
|
error_brace.target = error_brace.copy()
|
||||||
|
error_brace.target.stretch_to_fit_width(
|
||||||
|
VGroup(self.error_term[0], new_dRs[-1]).get_width()
|
||||||
|
)
|
||||||
|
error_brace.target.move_to(error_brace, LEFT)
|
||||||
|
self.play(
|
||||||
|
MoveToTarget(error_brace),
|
||||||
|
Transform(self.outer_ring, new_outer_ring),
|
||||||
|
Transform(self.nudge_line, new_nudge_line),
|
||||||
|
*[
|
||||||
|
Transform(*pair)
|
||||||
|
for pair in zip(dRs, new_dRs)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
if s == "(0.001)":
|
||||||
|
self.plus.generate_target()
|
||||||
|
self.plus.target.next_to(self.circum_term)
|
||||||
|
self.error_term.generate_target()
|
||||||
|
self.error_term.target.next_to(self.plus.target)
|
||||||
|
error_brace.target = Brace(self.error_term.target)
|
||||||
|
error_text.target = error_brace.target.get_text("Truly tiny")
|
||||||
|
error_text.target.highlight(error_text.get_color())
|
||||||
|
self.play(*map(MoveToTarget, [
|
||||||
|
error_brace, error_text, self.plus, self.error_term
|
||||||
|
]))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
difference_text = TextMobject(
|
||||||
|
"``Tiny " , "d", "ifference in ", "$R$", "''",
|
||||||
|
arg_separator = ""
|
||||||
|
|
||||||
|
)
|
||||||
|
difference_text.highlight_by_tex("d", self.dR_color)
|
||||||
|
difference_text.next_to(self.pi_creature, UP+RIGHT)
|
||||||
|
difference_arrow = Arrow(difference_text, self.change.denom)
|
||||||
|
self.play(
|
||||||
|
Write(difference_text, run_time = 2),
|
||||||
|
ShowCreation(difference_arrow),
|
||||||
|
self.pi_creature.change_mode, "speaking"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
dA = TexMobject("dA")
|
||||||
|
dA.highlight(self.change.get_color())
|
||||||
|
frac_line = self.change.frac_line
|
||||||
|
frac_line.generate_target()
|
||||||
|
frac_line.target.stretch_to_fit_width(dA.get_width())
|
||||||
|
frac_line.target.next_to(self.equals, LEFT)
|
||||||
|
dA.next_to(frac_line.target, UP, 2*SMALL_BUFF)
|
||||||
|
self.change.denom.generate_target()
|
||||||
|
self.change.denom.target.next_to(frac_line.target, DOWN, 2*SMALL_BUFF)
|
||||||
|
A = TexMobject("A").replace(difference_text[3])
|
||||||
|
difference_arrow.target = Arrow(difference_text, dA.get_left())
|
||||||
|
self.play(
|
||||||
|
Transform(self.change, dA),
|
||||||
|
MoveToTarget(frac_line),
|
||||||
|
MoveToTarget(self.change.denom),
|
||||||
|
Transform(difference_text[3], A),
|
||||||
|
difference_text[1].highlight, dA.get_color(),
|
||||||
|
MoveToTarget(difference_arrow),
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(*map(FadeOut, [difference_text, difference_arrow]))
|
||||||
|
|
||||||
|
def elaborate_on_d(self):
|
||||||
|
arc = Arc(-np.pi, start_angle = -np.pi/2)
|
||||||
|
arc.scale_to_fit_height(
|
||||||
|
self.change.get_center()[1]-self.change.denom.get_center()[1]
|
||||||
|
)
|
||||||
|
arc.next_to(self.change.frac_line, LEFT)
|
||||||
|
arc.add_tip()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ShowCreation(arc),
|
||||||
|
self.pi_creature.change_mode, "sassy"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(self.pi_creature.shrug)
|
||||||
|
self.play(FadeOut(arc))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
d = TextMobject("``$d$''")
|
||||||
|
arrow = TexMobject("\\Rightarrow")
|
||||||
|
arrow.next_to(d)
|
||||||
|
ignore_error = TextMobject("Ignore error")
|
||||||
|
d_group = VGroup(d, arrow, ignore_error)
|
||||||
|
d_group.arrange_submobjects()
|
||||||
|
d_group.next_to(
|
||||||
|
self.pi_creature.get_corner(UP+RIGHT),
|
||||||
|
buff = LARGE_BUFF
|
||||||
|
)
|
||||||
|
error_group = VGroup(
|
||||||
|
self.error_term, self.error_term.label
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(d),
|
||||||
|
self.pi_creature.change_mode, "speaking"
|
||||||
|
)
|
||||||
|
self.play(*map(Write, [arrow, ignore_error]))
|
||||||
|
self.play(error_group.fade, 0.8)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
less_wrong_philosophy = TextMobject("``Less wrong'' philosophy")
|
||||||
|
less_wrong_philosophy.move_to(ignore_error, LEFT)
|
||||||
|
self.play(Transform(ignore_error, less_wrong_philosophy))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
big_dR = 0.3
|
||||||
|
big_outer_ring = self.get_ring(self.radius, big_dR)
|
||||||
|
big_nudge_line = self.nudge_line.copy()
|
||||||
|
big_nudge_line.stretch_to_fit_width(big_dR)
|
||||||
|
big_nudge_line.move_to(self.nudge_line, LEFT)
|
||||||
|
new_nudge_arrow = Arrow(self.nudge_label, big_nudge_line, buff = SMALL_BUFF)
|
||||||
|
self.outer_ring.save_state()
|
||||||
|
self.nudge_line.save_state()
|
||||||
|
self.nudge_arrow.save_state()
|
||||||
|
self.play(
|
||||||
|
Transform(self.outer_ring, big_outer_ring),
|
||||||
|
Transform(self.nudge_line, big_nudge_line),
|
||||||
|
Transform(self.nudge_arrow, new_nudge_arrow),
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
*[
|
||||||
|
mob.restore
|
||||||
|
for mob in [
|
||||||
|
self.outer_ring,
|
||||||
|
self.nudge_line,
|
||||||
|
self.nudge_arrow,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
rate_func = None,
|
||||||
|
run_time = 7
|
||||||
|
)
|
||||||
|
self.play(self.pi_creature.change_mode, "hooray")
|
||||||
|
self.less_wrong_philosophy = VGroup(
|
||||||
|
d, arrow, ignore_error
|
||||||
|
)
|
||||||
|
|
||||||
|
def not_infinitely_small(self):
|
||||||
|
randy = Randolph().flip()
|
||||||
|
randy.scale(0.7)
|
||||||
|
randy.to_corner(DOWN+RIGHT)
|
||||||
|
bubble = SpeechBubble()
|
||||||
|
bubble.write("$dR$ is infinitely small")
|
||||||
|
bubble.resize_to_content()
|
||||||
|
bubble.stretch(0.7, 1)
|
||||||
|
bubble.pin_to(randy)
|
||||||
|
bubble.set_fill(BLACK, opacity = 1)
|
||||||
|
bubble.add_content(bubble.content)
|
||||||
|
self.play(FadeIn(randy))
|
||||||
|
self.play(
|
||||||
|
randy.change_mode, "speaking",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content),
|
||||||
|
self.pi_creature.change_mode, "confused"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
to_infs = [self.change, self.change.denom, self.nudge_label]
|
||||||
|
for mob in to_infs:
|
||||||
|
mob.save_state()
|
||||||
|
mob.inf = TexMobject("1/\\infty")
|
||||||
|
mob.inf.highlight(mob.get_color())
|
||||||
|
mob.inf.move_to(mob)
|
||||||
|
self.play(*[
|
||||||
|
Transform(mob, mob.inf)
|
||||||
|
for mob in to_infs
|
||||||
|
])
|
||||||
|
self.dither()
|
||||||
|
self.play(self.pi_creature.change_mode, "pleading")
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,6 +162,16 @@ class PiCreature(SVGMobject):
|
|||||||
pi_creature.look_at(self.eyes)
|
pi_creature.look_at(self.eyes)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def shrug(self):
|
||||||
|
self.change_mode("shruggie")
|
||||||
|
top_mouth_point, bottom_mouth_point = [
|
||||||
|
self.mouth.points[np.argmax(self.mouth.points[:,1])],
|
||||||
|
self.mouth.points[np.argmin(self.mouth.points[:,1])]
|
||||||
|
]
|
||||||
|
self.look(top_mouth_point - bottom_mouth_point)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Randolph(PiCreature):
|
class Randolph(PiCreature):
|
||||||
pass #Nothing more than an alternative name
|
pass #Nothing more than an alternative name
|
||||||
@ -209,27 +219,54 @@ class Blink(ApplyMethod):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RandolphScene(Scene):
|
class PiCreatureScene(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"randy_kwargs" : {},
|
"total_dither_time" : 0
|
||||||
"randy_corner" : DOWN+LEFT
|
|
||||||
}
|
}
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.randy = Randolph(**self.randy_kwargs)
|
self.pi_creature = self.get_pi_creature()
|
||||||
self.randy.to_corner(self.randy_corner)
|
self.add(self.pi_creature)
|
||||||
if self.randy_corner[0] > 0:
|
|
||||||
self.randy.flip()
|
def get_pi_creature(self):
|
||||||
self.add(self.randy)
|
return Randolph().to_corner()
|
||||||
|
|
||||||
|
def play(self, *args, **kwargs):
|
||||||
|
if self.pi_creature not in self.get_mobjects():
|
||||||
|
Scene.play(self, *args, **kwargs)
|
||||||
|
return
|
||||||
|
|
||||||
|
if inspect.ismethod(args[0]):
|
||||||
|
mobject_of_interest = args[0].im_self
|
||||||
|
elif isinstance(args[0], Transform):
|
||||||
|
if args[0].mobject is self.pi_creature:
|
||||||
|
mobject_of_interest = self.pi_creature
|
||||||
|
else:
|
||||||
|
mobject_of_interest = args[0].ending_mobject
|
||||||
|
elif isinstance(args[0], Animation):
|
||||||
|
mobject_of_interest = args[0].mobject
|
||||||
|
else:
|
||||||
|
raise Exception("Invalid play args")
|
||||||
|
|
||||||
|
if mobject_of_interest is self.pi_creature:
|
||||||
|
new_anims = []
|
||||||
|
else:
|
||||||
|
new_anims = [self.pi_creature.look_at, mobject_of_interest]
|
||||||
|
Scene.play(self, *list(args) + new_anims, **kwargs)
|
||||||
|
|
||||||
def dither(self, time = 1, blink = True):
|
def dither(self, time = 1, blink = True):
|
||||||
while time > 0:
|
while time > 0:
|
||||||
if blink and time%2 == 1:
|
if blink and self.total_dither_time%2 == 1:
|
||||||
self.play(Blink(self.randy))
|
self.play(Blink(self.pi_creature))
|
||||||
else:
|
else:
|
||||||
Scene.dither(self, time)
|
Scene.dither(self, time)
|
||||||
time -= 1
|
time -= 1
|
||||||
|
self.total_dither_time += 1
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def change_mode(self, mode):
|
||||||
|
self.play(self.pi_creature.change_mode, mode)
|
||||||
|
|
||||||
|
|
||||||
class TeacherStudentsScene(Scene):
|
class TeacherStudentsScene(Scene):
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.teacher = Mortimer()
|
self.teacher = Mortimer()
|
||||||
|
Reference in New Issue
Block a user