3b1b-manim/old_projects/eoc/chapter3.py

2827 lines
87 KiB
Python
Raw Normal View History

from big_ol_pile_of_manim_imports import *
from old_projects.eoc.chapter2 import DISTANCE_COLOR, TIME_COLOR, \
2017-01-30 20:28:01 -08:00
VELOCITY_COLOR, Car, MoveCar
2017-01-25 13:00:01 -08:00
OUTPUT_COLOR = DISTANCE_COLOR
INPUT_COLOR = TIME_COLOR
DERIVATIVE_COLOR = VELOCITY_COLOR
class Chapter3OpeningQuote(OpeningQuote):
CONFIG = {
"quote" : [
"You know, for a mathematician, he did not have \\\\ enough",
"imagination.",
"But he has become a poet and \\\\ now he is fine.",
],
"highlighted_quote_terms" : {
"imagination." : BLUE,
},
"author" : "David Hilbert"
}
2017-01-30 20:28:01 -08:00
class PoseAbstractDerivative(TeacherStudentsScene):
def construct(self):
self.teacher_says("""
Given $f(x) = x^2 \\sin(x)$, \\\\
compute $\\frac{df}{dx}(x)$
""")
content_copy = self.teacher.bubble.content.copy()
self.change_student_modes("sad", "confused", "erm")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 20:28:01 -08:00
self.student_says(
"Why?", target_mode = "sassy",
added_anims = [
content_copy.scale, 0.8,
content_copy.to_corner, UP+LEFT
]
)
self.play(self.teacher.change_mode, "pondering")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-30 20:28:01 -08:00
class ContrastAbstractAndConcrete(Scene):
def construct(self):
v_line = Line(UP, DOWN).scale(FRAME_Y_RADIUS)
2017-01-30 20:28:01 -08:00
l_title = TextMobject("Abstract functions")
l_title.shift(FRAME_X_RADIUS*LEFT/2)
2017-01-30 20:28:01 -08:00
l_title.to_edge(UP)
r_title = TextMobject("Applications")
r_title.shift(FRAME_X_RADIUS*RIGHT/2)
2017-01-30 20:28:01 -08:00
r_title.to_edge(UP)
h_line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS)
2017-01-30 20:28:01 -08:00
h_line.shift((r_title.get_bottom()[1]-MED_SMALL_BUFF)*UP)
functions = VGroup(*map(TexMobject, [
"f(x) = 2x^2 - x^3",
"f(x) = \\sin(x)",
"f(x) = e^x",
"\\v_dots"
]))
functions.arrange_submobjects(
DOWN,
aligned_edge = LEFT,
buff = LARGE_BUFF
)
functions.shift(FRAME_X_RADIUS*LEFT/2)
2017-01-30 20:28:01 -08:00
functions[-1].shift(MED_LARGE_BUFF*RIGHT)
2017-01-25 13:00:01 -08:00
2017-01-30 20:28:01 -08:00
self.add(l_title, r_title)
self.play(*map(ShowCreation, [h_line, v_line]))
self.play(Write(functions))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 20:28:01 -08:00
anims = [
method(func_mob)
for func_mob, method in zip(functions, [
self.get_car_anim,
self.get_spring_anim,
self.get_population_anim,
])
]
for anim in anims:
self.play(FadeIn(anim.mobject))
self.play(anim)
self.play(FadeOut(anim.mobject))
def get_car_anim(self, alignement_mob):
car = Car()
point = 2*RIGHT + alignement_mob.get_bottom()[1]*UP
target_point = point + 5*RIGHT
car.move_to(point)
return MoveCar(
car, target_point,
run_time = 5,
)
def get_spring_anim(self, alignement_mob):
2017-01-31 22:17:16 -08:00
compact_spring, extended_spring = [
ParametricFunction(
lambda t : (t/denom)*RIGHT+np.sin(t)*UP+np.cos(t)*OUT,
t_max = 12*np.pi,
num_anchor_points = 100,
)
2018-07-11 11:38:59 -07:00
for denom in (12.0, 4.0)
2017-01-31 22:17:16 -08:00
]
for spring in compact_spring, extended_spring:
spring.scale(0.5)
spring.rotate(np.pi/6, UP)
2018-03-30 11:51:31 -07:00
spring.set_color(GREY)
2017-01-31 22:17:16 -08:00
spring.next_to(ORIGIN, RIGHT)
spring.shift(
alignement_mob.get_center()[1]*UP + SMALL_BUFF*RIGHT \
-spring.points[0]
)
weight = Square(
side_length = 0.5,
stroke_width = 0,
fill_color = LIGHT_GREY,
fill_opacity = 1,
)
weight.move_to(spring.points[-1])
spring.add(weight)
return Transform(
compact_spring, extended_spring,
2017-01-30 20:28:01 -08:00
rate_func = lambda t : 1+np.sin(6*np.pi*t),
run_time = 5
)
def get_population_anim(self, alignement_mob):
colors = color_gradient([BLUE_B, BLUE_E], 12)
pis = VGroup(*[
Randolph(
mode = "happy",
color = random.choice(colors)
).shift(
4*x*RIGHT + 4*y*UP + \
2*random.random()*RIGHT + \
2*random.random()*UP
)
for x in range(20)
for y in range(10)
])
pis.scale_to_fit_height(3)
pis.center()
pis.to_edge(DOWN, buff = SMALL_BUFF)
pis.shift(FRAME_X_RADIUS*RIGHT/2.)
2017-01-25 13:00:01 -08:00
2017-01-30 20:28:01 -08:00
anims = []
for index, pi in enumerate(pis):
if index < 2:
anims.append(FadeIn(pi))
continue
mom_index, dad_index = random.choice(
list(it.combinations(range(index), 2))
)
pi.parents = VGroup(pis[mom_index], pis[dad_index]).copy()
pi.parents.set_fill(opacity = 0)
exp = 1
while 2**exp < len(pis):
low_index = 2**exp
high_index = min(2**(exp+1), len(pis))
these_pis = pis[low_index:high_index]
anims.append(Transform(
VGroup(*[pi.parents for pi in these_pis]),
VGroup(*[VGroup(pi, pi.copy()) for pi in these_pis]),
submobject_mode = "lagged_start",
run_time = 2,
))
exp += 1
2017-01-25 13:00:01 -08:00
2017-01-30 20:28:01 -08:00
return Succession(*anims, rate_func = None)
2017-01-25 13:00:01 -08:00
2017-01-31 22:17:16 -08:00
class ApplicationNames(Scene):
def construct(self):
for name in "Velocity", "Oscillation", "Population growth":
mob = TextMobject(name)
mob.scale(2)
self.play(Write(mob))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-31 22:17:16 -08:00
self.play(FadeOut(mob))
2017-01-30 20:28:01 -08:00
class ListOfRules(PiCreatureScene):
CONFIG = {
"use_morty" : False,
}
def construct(self):
rules = VGroup(*map(TexMobject, [
"\\frac{d}{dx} x^n = nx^{n-1}",
"\\frac{d}{dx} \\sin(x) = \\cos(x)",
"\\frac{d}{dx} \\cos(x) = -\\sin(x)",
"\\frac{d}{dx} a^x = \\ln(a) a^x",
"\\vdots"
]))
rules.arrange_submobjects(
DOWN, buff = MED_LARGE_BUFF,
aligned_edge = LEFT,
)
rules[-1].shift(MED_LARGE_BUFF*RIGHT)
rules.scale_to_fit_height(FRAME_HEIGHT-1)
2017-01-30 20:28:01 -08:00
rules.next_to(self.pi_creature, RIGHT)
rules.to_edge(DOWN)
2017-01-25 13:00:01 -08:00
2017-01-30 20:28:01 -08:00
self.play(
Write(rules),
self.pi_creature.change_mode, "pleading",
)
self.change_mode("tired")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
class DerivativeOfXSquaredAsGraph(GraphScene, ZoomedScene, PiCreatureScene):
CONFIG = {
"start_x" : 2,
"big_x" : 3,
"dx" : 0.1,
2017-01-25 16:40:59 -08:00
"x_min" : -9,
"x_labeled_nums" : range(-8, 0, 2) + range(2, 10, 2),
2017-01-25 13:00:01 -08:00
"y_labeled_nums" : range(2, 12, 2),
2017-01-25 16:40:59 -08:00
"little_rect_nudge" : 0.5*(1.5*UP+RIGHT),
"graph_origin" : 2.5*DOWN + LEFT,
2017-01-25 13:00:01 -08:00
"zoomed_canvas_corner" : UP+LEFT,
"zoomed_canvas_frame_shape" : (4, 4),
2017-01-25 13:00:01 -08:00
}
def construct(self):
self.draw_graph()
self.ask_about_df_dx()
self.show_differing_slopes()
self.mention_alternate_view()
def draw_graph(self):
2017-01-31 22:17:16 -08:00
self.setup_axes(animate = True)
2017-01-25 13:00:01 -08:00
graph = self.get_graph(lambda x : x**2)
label = self.get_graph_label(
graph, "f(x) = x^2",
)
self.play(ShowCreation(graph))
self.play(Write(label))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.graph = graph
def ask_about_df_dx(self):
ss_group = self.get_secant_slope_group(
self.start_x, self.graph,
dx = self.dx,
dx_label = "dx",
df_label = "df",
)
secant_line = ss_group.secant_line
ss_group.remove(secant_line)
v_line, nudged_v_line = [
self.get_vertical_line_to_graph(
x, self.graph,
line_class = DashedLine,
color = RED,
dashed_segment_length = 0.025
)
2018-07-11 11:38:59 -07:00
for x in (self.start_x, self.start_x+self.dx)
2017-01-25 13:00:01 -08:00
]
df_dx = TexMobject("\\frac{df}{dx} ?")
2018-03-30 11:51:31 -07:00
VGroup(*df_dx[:2]).set_color(ss_group.df_line.get_color())
VGroup(*df_dx[3:5]).set_color(ss_group.dx_line.get_color())
2017-01-25 13:00:01 -08:00
df_dx.next_to(
self.input_to_graph_point(self.start_x, self.graph),
DOWN+RIGHT,
2017-01-25 16:40:59 -08:00
buff = MED_SMALL_BUFF
2017-01-25 13:00:01 -08:00
)
2017-01-31 22:17:16 -08:00
derivative_q = TextMobject("Derivative?")
derivative_q.next_to(self.pi_creature.get_corner(UP+LEFT), UP)
self.play(
Write(derivative_q, run_time = 1),
self.pi_creature.change_mode, "speaking"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
self.play(
FadeOut(derivative_q),
self.pi_creature.change_mode, "plain"
)
2017-01-25 13:00:01 -08:00
self.play(ShowCreation(v_line))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.play(Transform(v_line.copy(), nudged_v_line))
self.remove(self.get_mobjects_from_last_animation()[0])
self.add(nudged_v_line)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.activate_zooming()
2017-01-25 16:40:59 -08:00
self.little_rectangle.replace(self.big_rectangle)
2017-01-25 13:00:01 -08:00
self.play(
FadeIn(self.little_rectangle),
FadeIn(self.big_rectangle),
)
self.play(
2017-01-25 16:40:59 -08:00
ApplyFunction(
lambda r : self.position_little_rectangle(r, ss_group),
self.little_rectangle
),
2017-01-25 13:00:01 -08:00
self.pi_creature.change_mode, "pondering",
self.pi_creature.look_at, ss_group
)
self.play(
ShowCreation(ss_group.dx_line),
Write(ss_group.dx_label),
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.play(
ShowCreation(ss_group.df_line),
Write(ss_group.df_label),
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.play(Write(df_dx))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.play(*map(FadeOut, [
v_line, nudged_v_line,
]))
self.ss_group = ss_group
2017-01-25 16:40:59 -08:00
def position_little_rectangle(self, rect, ss_group):
rect.scale_to_fit_width(3*self.dx)
rect.move_to(
ss_group.dx_line.get_left()
)
rect.shift(
self.dx*self.little_rect_nudge
)
return rect
2017-01-25 13:00:01 -08:00
def show_differing_slopes(self):
ss_group = self.ss_group
def rect_update(rect):
2017-01-25 16:40:59 -08:00
self.position_little_rectangle(rect, ss_group)
2017-01-25 13:00:01 -08:00
self.play(
ShowCreation(ss_group.secant_line),
self.pi_creature.change_mode, "thinking"
)
ss_group.add(ss_group.secant_line)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
for target_x in self.big_x, -self.dx/2, 1, 2:
self.animate_secant_slope_group_change(
ss_group, target_x = target_x,
added_anims = [
UpdateFromFunc(self.little_rectangle, rect_update)
]
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
def mention_alternate_view(self):
2017-01-25 16:40:59 -08:00
self.remove(self.pi_creature)
everything = VGroup(*self.get_mobjects())
self.add(self.pi_creature)
self.disactivate_zooming()
self.play(
ApplyMethod(
everything.shift, FRAME_WIDTH*LEFT,
2017-01-25 16:40:59 -08:00
rate_func = lambda t : running_start(t, -0.1)
),
self.pi_creature.change_mode, "happy"
)
2017-01-25 13:00:01 -08:00
self.say("Let's try \\\\ another view.", target_mode = "speaking")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-25 13:00:01 -08:00
2017-01-25 16:40:59 -08:00
class NudgeSideLengthOfSquare(PiCreatureScene):
CONFIG = {
"square_width" : 3,
2017-01-26 19:59:55 -08:00
"alt_square_width" : 5,
"dx" : 0.25,
"alt_dx" : 0.01,
"square_color" : GREEN,
"square_fill_opacity" : 0.75,
"three_color" : GREEN,
"dx_color" : BLUE_B,
"is_recursing_on_dx" : False,
"is_recursing_on_square_width" : False,
2017-01-25 16:40:59 -08:00
}
def construct(self):
ApplyMethod(self.pi_creature.change_mode, "speaking").update(1)
self.add_function_label()
self.introduce_square()
self.increase_area()
2017-01-26 19:59:55 -08:00
self.write_df_equation()
2018-03-30 11:51:31 -07:00
self.set_color_shapes()
2017-01-25 16:40:59 -08:00
self.examine_thin_rectangles()
self.examine_tiny_square()
2017-01-26 19:59:55 -08:00
self.show_smaller_dx()
self.rule_of_thumb()
2017-01-25 16:40:59 -08:00
self.write_out_derivative()
def add_function_label(self):
label = TexMobject("f(x) = x^2")
2017-01-26 19:59:55 -08:00
label.next_to(ORIGIN, RIGHT, buff = (self.square_width-3)/2.)
2017-01-25 16:40:59 -08:00
label.to_edge(UP)
self.add(label)
2017-01-26 19:59:55 -08:00
self.function_label = label
2017-01-25 16:40:59 -08:00
def introduce_square(self):
square = Square(
side_length = self.square_width,
stroke_width = 0,
2017-01-26 19:59:55 -08:00
fill_opacity = self.square_fill_opacity,
fill_color = self.square_color,
2017-01-25 16:40:59 -08:00
)
square.to_corner(UP+LEFT, buff = LARGE_BUFF)
x_squared = TexMobject("x^2")
x_squared.move_to(square)
braces = VGroup()
2017-01-26 19:59:55 -08:00
for vect in RIGHT, DOWN:
2017-01-25 16:40:59 -08:00
brace = Brace(square, vect)
2017-01-26 19:59:55 -08:00
text = brace.get_text("$x$")
brace.add(text)
2017-01-25 16:40:59 -08:00
braces.add(brace)
2017-01-26 19:59:55 -08:00
self.play(
DrawBorderThenFill(square),
self.pi_creature.change_mode, "plain"
)
self.play(*map(GrowFromCenter, braces))
self.play(Write(x_squared))
self.change_mode("pondering")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 16:40:59 -08:00
2017-01-26 19:59:55 -08:00
self.square = square
self.side_braces = braces
2017-01-25 16:40:59 -08:00
def increase_area(self):
2017-01-26 19:59:55 -08:00
color_kwargs = {
"fill_color" : YELLOW,
"fill_opacity" : self.square_fill_opacity,
"stroke_width" : 0,
}
right_rect = Rectangle(
width = self.dx,
height = self.square_width,
**color_kwargs
)
bottom_rect = right_rect.copy().rotate(-np.pi/2)
right_rect.next_to(self.square, RIGHT, buff = 0)
bottom_rect.next_to(self.square, DOWN, buff = 0)
corner_square = Square(
side_length = self.dx,
**color_kwargs
)
corner_square.next_to(self.square, DOWN+RIGHT, buff = 0)
right_line = Line(
self.square.get_corner(UP+RIGHT),
self.square.get_corner(DOWN+RIGHT),
stroke_width = 0
)
bottom_line = Line(
self.square.get_corner(DOWN+RIGHT),
self.square.get_corner(DOWN+LEFT),
stroke_width = 0
)
corner_point = VectorizedPoint(
self.square.get_corner(DOWN+RIGHT)
)
little_braces = VGroup()
for vect in RIGHT, DOWN:
brace = Brace(
corner_square, vect,
buff = SMALL_BUFF,
)
text = brace.get_text("$dx$", buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
text.set_color(self.dx_color)
2017-01-26 19:59:55 -08:00
brace.add(text)
little_braces.add(brace)
right_brace, bottom_brace = self.side_braces
self.play(
Transform(right_line, right_rect),
Transform(bottom_line, bottom_rect),
Transform(corner_point, corner_square),
right_brace.next_to, right_rect, RIGHT, SMALL_BUFF,
bottom_brace.next_to, bottom_rect, DOWN, SMALL_BUFF,
)
self.remove(corner_point, bottom_line, right_line)
self.add(corner_square, bottom_rect, right_rect)
self.play(*map(GrowFromCenter, little_braces))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(*it.chain(*[
[mob.shift, vect*SMALL_BUFF]
for mob, vect in [
(right_rect, RIGHT),
(bottom_rect, DOWN),
(corner_square, DOWN+RIGHT),
(right_brace, RIGHT),
(bottom_brace, DOWN),
(little_braces, DOWN+RIGHT)
]
]))
self.change_mode("thinking")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.right_rect = right_rect
self.bottom_rect = bottom_rect
self.corner_square = corner_square
self.little_braces = little_braces
def write_df_equation(self):
right_rect = self.right_rect
bottom_rect = self.bottom_rect
corner_square = self.corner_square
df_equation = VGroup(
2018-03-30 11:51:31 -07:00
TexMobject("df").set_color(right_rect.get_color()),
2017-01-26 19:59:55 -08:00
TexMobject("="),
right_rect.copy(),
TextMobject("+"),
right_rect.copy(),
TexMobject("+"),
corner_square.copy()
)
df_equation.arrange_submobjects()
df_equation.next_to(
self.function_label, DOWN,
aligned_edge = LEFT,
buff = SMALL_BUFF
)
df, equals, r1, plus1, r2, plus2, s = df_equation
pairs = [
(df, self.function_label[0]),
(r1, right_rect),
(r2, bottom_rect),
(s, corner_square),
]
for mover, origin in pairs:
mover.save_state()
Transform(mover, origin).update(1)
self.play(df.restore)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(
*[
mob.restore
2018-07-11 11:38:59 -07:00
for mob in (r1, r2, s)
2017-01-26 19:59:55 -08:00
]+[
Write(symbol)
2018-07-11 11:38:59 -07:00
for symbol in (equals, plus1, plus2)
2017-01-26 19:59:55 -08:00
],
run_time = 2
)
self.change_mode("happy")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.df_equation = df_equation
2018-03-30 11:51:31 -07:00
def set_color_shapes(self):
2017-01-26 19:59:55 -08:00
df, equals, r1, plus1, r2, plus2, s = self.df_equation
tups = [
(self.right_rect, self.bottom_rect, r1, r2),
(self.corner_square, s)
]
for tup in tups:
self.play(
*it.chain(*[
2018-03-30 11:51:31 -07:00
[m.scale_in_place, 1.2, m.set_color, RED]
2017-01-26 19:59:55 -08:00
for m in tup
]),
rate_func = there_and_back
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 16:40:59 -08:00
def examine_thin_rectangles(self):
2017-01-26 19:59:55 -08:00
df, equals, r1, plus1, r2, plus2, s = self.df_equation
rects = VGroup(r1, r2)
thin_rect_brace = Brace(rects, DOWN)
text = thin_rect_brace.get_text("$2x \\, dx$")
2018-03-30 11:51:31 -07:00
VGroup(*text[-2:]).set_color(self.dx_color)
2017-01-26 19:59:55 -08:00
text.save_state()
alt_text = thin_rect_brace.get_text("$2(3)(0.01)$")
2018-03-30 11:51:31 -07:00
alt_text[2].set_color(self.three_color)
VGroup(*alt_text[-5:-1]).set_color(self.dx_color)
2017-01-26 19:59:55 -08:00
example_value = TexMobject("=0.06")
example_value.next_to(alt_text, DOWN)
self.play(GrowFromCenter(thin_rect_brace))
self.play(
Write(text),
self.pi_creature.change_mode, "pondering"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
xs = VGroup(*[
brace[-1]
for brace in self.side_braces
])
dxs = VGroup(*[
brace[-1]
for brace in self.little_braces
])
for group, tex, color in (xs, "3", self.three_color), (dxs, "0.01", self.dx_color):
group.save_state()
group.generate_target()
for submob in group.target:
number = TexMobject(tex)
2018-03-30 11:51:31 -07:00
number.set_color(color)
2017-01-26 19:59:55 -08:00
number.move_to(submob, LEFT)
Transform(submob, number).update(1)
self.play(MoveToTarget(xs))
self.play(MoveToTarget(dxs))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(Transform(text, alt_text))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(Write(example_value))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(
FadeOut(example_value),
*[
mob.restore
2018-07-11 11:38:59 -07:00
for mob in (xs, dxs, text)
2017-01-26 19:59:55 -08:00
]
)
self.remove(text)
text.restore()
self.add(text)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.dxs = dxs
self.thin_rect_brace = thin_rect_brace
self.thin_rect_area = text
2017-01-25 16:40:59 -08:00
def examine_tiny_square(self):
2017-01-26 19:59:55 -08:00
text = TexMobject("dx^2")
2018-03-30 11:51:31 -07:00
VGroup(*text[:2]).set_color(self.dx_color)
2017-01-26 19:59:55 -08:00
text.next_to(self.df_equation[-1], UP)
text.save_state()
alt_text = TextMobject("0.0001")
alt_text.move_to(text)
self.play(Write(text))
self.change_mode("surprised")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(
MoveToTarget(self.dxs),
self.pi_creature.change_mode, "plain"
)
for submob in self.dxs.target:
number = TexMobject("0.01")
2018-03-30 11:51:31 -07:00
number.set_color(self.dx_color)
2017-01-26 19:59:55 -08:00
number.move_to(submob, LEFT)
Transform(submob, number).update(1)
self.play(MoveToTarget(self.dxs))
self.play(
Transform(text, alt_text),
self.pi_creature.change_mode, "raise_right_hand"
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-26 19:59:55 -08:00
self.play(*[
mob.restore
2018-07-11 11:38:59 -07:00
for mob in (self.dxs, text)
2017-01-26 19:59:55 -08:00
] + [
self.pi_creature.change_mode, "erm"
])
self.dx_squared = text
def show_smaller_dx(self):
self.mobjects_at_start_of_show_smaller_dx = [
mob.copy() for mob in self.get_mobjects()
]
if self.is_recursing_on_dx:
return
alt_scene = self.__class__(
skip_animations = True,
dx = self.alt_dx,
is_recursing_on_dx = True
)
for mob in self.get_mobjects():
mob.save_state()
self.play(*[
Transform(*pair)
for pair in zip(
self.get_mobjects(),
alt_scene.mobjects_at_start_of_show_smaller_dx,
)
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(*[
mob.restore
for mob in self.get_mobjects()
])
self.change_mode("happy")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
def rule_of_thumb(self):
circle = Circle(color = RED)
dx_squared_group = VGroup(self.dx_squared, self.df_equation[-1])
circle.replace(dx_squared_group, stretch = True)
dx_squared_group.add(self.df_equation[-2])
circle.scale_in_place(1.5)
safe_to_ignore = TextMobject("Safe to ignore")
safe_to_ignore.next_to(circle, DOWN, aligned_edge = LEFT)
2018-03-30 11:51:31 -07:00
safe_to_ignore.set_color(circle.get_color())
2017-01-26 19:59:55 -08:00
self.play(ShowCreation(circle))
self.play(
Write(safe_to_ignore, run_time = 2),
self.pi_creature.change_mode, "raise_right_hand"
)
self.play(
FadeOut(circle),
FadeOut(safe_to_ignore),
dx_squared_group.fade, 0.5,
dx_squared_group.to_corner, UP+RIGHT,
self.pi_creature.change_mode, "plain"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 16:40:59 -08:00
def write_out_derivative(self):
2017-01-26 19:59:55 -08:00
df, equals, r1, plus1, r2, plus2, s = self.df_equation
frac_line = TexMobject("-")
frac_line.stretch_to_fit_width(df.get_width())
frac_line.move_to(df)
dx = VGroup(*self.thin_rect_area[-2:])
x = self.thin_rect_area[1]
self.play(
Transform(r1, self.right_rect),
Transform(r2, self.bottom_rect),
FadeOut(plus1),
FadeOut(self.thin_rect_brace)
)
self.play(
self.thin_rect_area.next_to, VGroup(df, equals),
RIGHT, MED_SMALL_BUFF, UP,
self.pi_creature.change_mode, "thinking"
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-26 19:59:55 -08:00
self.play(
ApplyMethod(df.next_to, frac_line, UP, SMALL_BUFF),
ApplyMethod(dx.next_to, frac_line, DOWN, SMALL_BUFF),
Write(frac_line),
path_arc = -np.pi
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
brace_xs = [
brace[-1]
for brace in self.side_braces
]
xs = list(brace_xs) + [x]
for x_mob in xs:
number = TexMobject("(%d)"%self.square_width)
number.move_to(x_mob, LEFT)
number.shift(
(x_mob.get_bottom()[1] - number[1].get_bottom()[1])*UP
)
x_mob.save_state()
x_mob.target = number
self.play(*map(MoveToTarget, xs))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-26 19:59:55 -08:00
#Recursively transform to what would have happened
#with a wider square width
self.mobjects_at_end_of_write_out_derivative = self.get_mobjects()
if self.is_recursing_on_square_width or self.is_recursing_on_dx:
return
alt_scene = self.__class__(
skip_animations = True,
square_width = self.alt_square_width,
is_recursing_on_square_width = True,
)
self.play(*[
Transform(*pair)
for pair in zip(
self.mobjects_at_end_of_write_out_derivative,
alt_scene.mobjects_at_end_of_write_out_derivative
)
])
self.change_mode("happy")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-26 19:59:55 -08:00
2017-01-31 22:17:16 -08:00
class ChangeInAreaOverChangeInX(Scene):
def construct(self):
fractions = []
for pair in ("Change in area", "Change in $x$"), ("$d(x^2)$", "$dx$"):
top, bottom = map(TextMobject, pair)
2018-03-30 11:51:31 -07:00
top.set_color(YELLOW)
bottom.set_color(BLUE_B)
2017-01-31 22:17:16 -08:00
frac_line = TexMobject("-")
frac_line.stretch_to_fit_width(top.get_width())
top.next_to(frac_line, UP, SMALL_BUFF)
bottom.next_to(frac_line, DOWN, SMALL_BUFF)
fractions.append(VGroup(
top, frac_line, bottom
))
words, symbols = fractions
self.play(Write(words[0], run_time = 1))
self.play(*map(Write, words[1:]), run_time = 1)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
self.play(Transform(words, symbols))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
2017-01-26 19:59:55 -08:00
class NudgeSideLengthOfCube(Scene):
CONFIG = {
"x_color" : BLUE,
"dx_color" : GREEN,
"df_color" : YELLOW,
"use_morty" : False,
"x" : 3,
"dx" : 0.2,
"alt_dx" : 0.02,
"offset_vect" : OUT,
"pose_angle" : np.pi/12,
"pose_axis" : UP+RIGHT,
"small_piece_scaling_factor" : 0.7,
"allow_recursion" : True,
2017-01-26 19:59:55 -08:00
}
def construct(self):
self.states = dict()
if self.allow_recursion:
self.alt_scene = self.__class__(
skip_animations = True,
allow_recursion = False,
dx = self.alt_dx,
)
2017-01-26 19:59:55 -08:00
self.add_title()
self.introduce_cube()
self.write_df_equation()
self.write_derivative()
2017-01-26 19:59:55 -08:00
def add_title(self):
title = TexMobject("f(x) = x^3")
title.shift(FRAME_X_RADIUS*LEFT/2)
2017-01-26 19:59:55 -08:00
title.to_edge(UP)
self.play(Write(title))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
def introduce_cube(self):
cube = self.get_cube()
cube.to_edge(LEFT, buff = 2*LARGE_BUFF)
cube.shift(DOWN)
dv_pieces = self.get_dv_pices(cube)
original_dx = self.dx
self.dx = 0
alt_dv_pieces = self.get_dv_pices(cube)
self.dx = original_dx
alt_dv_pieces.set_fill(opacity = 0)
x_brace = Brace(cube, LEFT, buff = SMALL_BUFF)
dx_brace = Brace(
dv_pieces[1], LEFT, buff = SMALL_BUFF,
)
dx_brace.stretch_in_place(1.5, 1)
for brace, tex in (x_brace, "x"), (dx_brace, "dx"):
brace.scale_in_place(0.95)
brace.rotate_in_place(-np.pi/96)
brace.shift(0.3*(UP+LEFT))
brace.add(brace.get_text("$%s$"%tex))
cube_group = VGroup(cube, dv_pieces, alt_dv_pieces)
self.pose_3d_mobject(cube_group)
self.play(DrawBorderThenFill(cube))
self.play(GrowFromCenter(x_brace))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(Transform(alt_dv_pieces, dv_pieces))
self.remove(alt_dv_pieces)
self.add(dv_pieces)
self.play(GrowFromCenter(dx_brace))
2018-01-15 19:15:05 -08:00
self.wait()
for piece in dv_pieces:
piece.on_cube_state = piece.copy()
2017-01-26 19:59:55 -08:00
self.play(*[
ApplyMethod(
piece.shift,
0.5*(piece.get_center()-cube.get_center())
)
for piece in dv_pieces
]+[
ApplyMethod(dx_brace.shift, 0.7*UP)
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.cube = cube
self.dx_brace = dx_brace
2017-01-26 19:59:55 -08:00
self.faces, self.bars, self.corner_cube = [
VGroup(*[
piece
for piece in dv_pieces
if piece.type == target_type
])
2018-07-11 11:38:59 -07:00
for target_type in ("face", "bar", "corner_cube")
2017-01-26 19:59:55 -08:00
]
def write_df_equation(self):
df_equation = VGroup(
TexMobject("df"),
TexMobject("="),
self.organize_faces(self.faces.copy()),
TexMobject("+"),
self.organize_bars(self.bars.copy()),
TexMobject("+"),
self.corner_cube.copy()
)
df, equals, faces, plus1, bars, plus2, corner_cube = df_equation
2018-03-30 11:51:31 -07:00
df.set_color(self.df_color)
2017-01-26 19:59:55 -08:00
for three_d_mob in faces, bars, corner_cube:
three_d_mob.scale(self.small_piece_scaling_factor)
# self.pose_3d_mobject(three_d_mob)
faces.set_fill(opacity = 0.3)
df_equation.arrange_submobjects(RIGHT)
df_equation.next_to(ORIGIN, RIGHT)
df_equation.to_edge(UP)
faces_brace = Brace(faces, DOWN)
2018-05-15 19:49:10 -07:00
derivative = faces_brace.get_tex("3x^2", "\\, dx")
2017-01-26 19:59:55 -08:00
extras_brace = Brace(VGroup(bars, corner_cube), DOWN)
ignore_text = extras_brace.get_text(
"Multiple \\\\ of $dx^2$"
)
ignore_text.scale_in_place(0.7)
x_squared_dx = TexMobject("x^2", "\\, dx")
self.play(*map(Write, [df, equals]))
self.grab_pieces(self.faces, faces)
2018-01-15 19:15:05 -08:00
self.wait()
self.shrink_dx("Faces are introduced")
2017-01-26 19:59:55 -08:00
face = self.faces[0]
face.save_state()
self.play(face.shift, FRAME_X_RADIUS*RIGHT)
x_squared_dx.next_to(face, LEFT)
2017-01-26 19:59:55 -08:00
self.play(Write(x_squared_dx, run_time = 1))
2018-01-15 19:15:05 -08:00
self.wait()
for submob, sides in zip(x_squared_dx, [face[0], VGroup(*face[1:])]):
self.play(
2018-03-30 11:51:31 -07:00
submob.set_color, RED,
sides.set_color, RED,
rate_func = there_and_back
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(
face.restore,
Transform(
x_squared_dx, derivative,
replace_mobject_with_target_in_scene = True
),
2017-01-26 19:59:55 -08:00
GrowFromCenter(faces_brace)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.grab_pieces(self.bars, bars, plus1)
self.grab_pieces(self.corner_cube, corner_cube, plus2)
self.play(
GrowFromCenter(extras_brace),
Write(ignore_text)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.play(*[
ApplyMethod(mob.fade, 0.7)
for mob in [
plus1, bars, plus2, corner_cube,
extras_brace, ignore_text
]
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
self.df_equation = df_equation
self.derivative = derivative
def write_derivative(self):
df, equals, faces, plus1, bars, plus2, corner_cube = self.df_equation
df = df.copy()
equals = equals.copy()
df_equals = VGroup(df, equals)
derivative = self.derivative.copy()
dx = derivative[1]
extra_stuff = TexMobject("+(\\dots)", "dx^2")
dx_squared = extra_stuff[1]
derivative.generate_target()
derivative.target.shift(2*DOWN)
extra_stuff.next_to(derivative.target)
self.play(
MoveToTarget(derivative),
df_equals.next_to, derivative.target[0], LEFT,
df_equals.shift, 0.07*DOWN
)
self.play(Write(extra_stuff))
2018-01-15 19:15:05 -08:00
self.wait()
frac_line = TexMobject("-")
frac_line.replace(df)
extra_stuff.generate_target()
extra_stuff.target.next_to(derivative[0])
frac_line2 = TexMobject("-")
frac_line2.stretch_to_fit_width(
extra_stuff.target[1].get_width()
)
frac_line2.move_to(extra_stuff.target[1])
extra_stuff.target[1].next_to(frac_line2, UP, buff = SMALL_BUFF)
dx_below_dx_squared = TexMobject("dx")
dx_below_dx_squared.next_to(frac_line2, DOWN, buff = SMALL_BUFF)
self.play(
FadeIn(frac_line),
FadeIn(frac_line2),
df.next_to, frac_line, UP, SMALL_BUFF,
dx.next_to, frac_line, DOWN, SMALL_BUFF,
MoveToTarget(extra_stuff),
Write(dx_below_dx_squared),
path_arc = -np.pi
)
2018-01-15 19:15:05 -08:00
self.wait()
inner_dx = VGroup(*dx_squared[:-1])
self.play(
FadeOut(frac_line2),
FadeOut(dx_below_dx_squared),
2018-03-30 11:51:31 -07:00
dx_squared[-1].set_color, BLACK,
inner_dx.next_to, extra_stuff[0], RIGHT, SMALL_BUFF
)
2018-01-15 19:15:05 -08:00
self.wait()
self.shrink_dx("Derivative is written", restore = False)
self.play(*[
ApplyMethod(mob.fade, 0.7)
2018-07-11 11:38:59 -07:00
for mob in (extra_stuff, inner_dx)
])
2018-01-15 19:15:05 -08:00
self.wait(2)
anims = []
for mob in list(self.faces)+list(self.bars)+list(self.corner_cube):
vect = mob.get_center()-self.cube.get_center()
anims += [
mob.shift, -(1./3)*vect
]
anims += self.dx_brace.shift, 0.7*DOWN
self.play(*anims)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
def grab_pieces(self, start_pieces, end_pices, to_write = None):
for piece in start_pieces:
piece.generate_target()
piece.target.rotate_in_place(
np.pi/12, piece.get_center()-self.cube.get_center()
)
2018-03-30 11:51:31 -07:00
piece.target.set_color(RED)
2017-01-26 19:59:55 -08:00
self.play(*map(MoveToTarget, start_pieces), rate_func = wiggle)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-26 19:59:55 -08:00
added_anims = []
if to_write is not None:
added_anims.append(Write(to_write))
self.play(
Transform(start_pieces.copy(), end_pices),
*added_anims
)
2017-01-25 16:40:59 -08:00
def shrink_dx(self, state_name, restore = True):
mobjects = self.get_mobjects()
mobjects_with_points = [
m for m in mobjects
if m.get_num_points() > 0
]
#Alt_scene will reach this point, and save copy of self
#in states dict
self.states[state_name] = [
mob.copy() for mob in mobjects_with_points
]
if not self.allow_recursion:
2017-01-26 19:59:55 -08:00
return
if restore:
movers = self.states[state_name]
for mob in movers:
mob.save_state()
self.remove(*mobjects)
else:
movers = mobjects_with_points
2017-01-26 19:59:55 -08:00
self.play(*[
Transform(*pair)
for pair in zip(
movers,
self.alt_scene.states[state_name]
2017-01-26 19:59:55 -08:00
)
])
2018-01-15 19:15:05 -08:00
self.wait()
if restore:
self.play(*[m.restore for m in movers])
self.remove(*movers)
self.mobjects = mobjects
2017-01-26 19:59:55 -08:00
def get_cube(self):
cube = self.get_prism(self.x, self.x, self.x)
cube.set_fill(color = BLUE, opacity = 0.3)
cube.set_stroke(color = WHITE, width = 1)
return cube
def get_dv_pices(self, cube):
pieces = VGroup()
for vect in it.product([0, 1], [0, 1], [0, 1]):
if np.all(vect == ORIGIN):
continue
args = [
self.x if bit is 0 else self.dx
for bit in vect
]
piece = self.get_prism(*args)
piece.next_to(cube, np.array(vect), buff = 0)
pieces.add(piece)
if sum(vect) == 1:
piece.type = "face"
elif sum(vect) == 2:
piece.type = "bar"
else:
piece.type = "corner_cube"
return pieces
def organize_faces(self, faces):
self.unpose_3d_mobject(faces)
for face in faces:
dimensions = [
face.length_over_dim(dim)
for dim in range(3)
]
thin_dim = np.argmin(dimensions)
if thin_dim == 0:
face.rotate(np.pi/2, DOWN)
elif thin_dim == 1:
face.rotate(np.pi/2, RIGHT)
faces.arrange_submobjects(OUT, buff = LARGE_BUFF)
self.pose_3d_mobject(faces)
return faces
def organize_bars(self, bars):
self.unpose_3d_mobject(bars)
for bar in bars:
dimensions = [
bar.length_over_dim(dim)
for dim in range(3)
]
thick_dim = np.argmax(dimensions)
if thick_dim == 0:
bar.rotate(np.pi/2, OUT)
elif thick_dim == 2:
bar.rotate(np.pi/2, LEFT)
bars.arrange_submobjects(OUT, buff = LARGE_BUFF)
self.pose_3d_mobject(bars)
return bars
def get_corner_cube(self):
return self.get_prism(self.dx, self.dx, self.dx)
def get_prism(self, width, height, depth):
color_kwargs = {
"fill_color" : YELLOW,
"fill_opacity" : 0.4,
"stroke_color" : WHITE,
"stroke_width" : 0.1,
}
front = Rectangle(
width = width,
height = height,
**color_kwargs
)
face = VGroup(front)
for vect in LEFT, RIGHT, UP, DOWN:
if vect is LEFT or vect is RIGHT:
side = Rectangle(
height = height,
width = depth,
**color_kwargs
)
else:
side = Rectangle(
height = depth,
width = width,
**color_kwargs
)
side.next_to(front, vect, buff = 0)
side.rotate(
np.pi/2, rotate_vector(vect, -np.pi/2),
about_point = front.get_edge_center(vect)
)
face.add(side)
return face
2017-01-25 13:00:01 -08:00
2017-01-26 19:59:55 -08:00
def pose_3d_mobject(self, mobject):
mobject.rotate_in_place(self.pose_angle, self.pose_axis)
return mobject
2017-01-25 13:00:01 -08:00
2017-01-26 19:59:55 -08:00
def unpose_3d_mobject(self, mobject):
mobject.rotate_in_place(-self.pose_angle, self.pose_axis)
return mobject
2017-01-25 13:00:01 -08:00
2017-01-26 19:59:55 -08:00
class ShowCubeDVIn3D(Scene):
def construct(self):
raise Exception("This scene is only here for the stage_scenes script.")
2017-01-25 13:00:01 -08:00
2017-01-27 19:31:20 -08:00
class GraphOfXCubed(GraphScene):
CONFIG = {
"x_min" : -6,
"x_max" : 6,
"x_axis_width" : FRAME_WIDTH,
2017-01-27 19:31:20 -08:00
"x_labeled_nums" : range(-6, 7),
"y_min" : -35,
"y_max" : 35,
"y_axis_height" : FRAME_HEIGHT,
2017-01-27 19:31:20 -08:00
"y_tick_frequency" : 5,
"y_labeled_nums" : range(-30, 40, 10),
"graph_origin" : ORIGIN,
"dx" : 0.2,
"deriv_x_min" : -3,
"deriv_x_max" : 3,
}
def construct(self):
self.setup_axes(animate = False)
graph = self.get_graph(lambda x : x**3)
label = self.get_graph_label(
graph, "f(x) = x^3",
direction = LEFT,
)
deriv_graph, full_deriv_graph = [
self.get_derivative_graph(
graph,
color = DERIVATIVE_COLOR,
x_min = low_x,
x_max = high_x,
)
for low_x, high_x in [
(self.deriv_x_min, self.deriv_x_max),
(self.x_min, self.x_max),
]
]
deriv_label = self.get_graph_label(
deriv_graph,
"\\frac{df}{dx}(x) = 3x^2",
x_val = -3,
direction = LEFT
)
deriv_label.shift(0.5*DOWN)
ss_group = self.get_secant_slope_group(
self.deriv_x_min, graph,
dx = self.dx,
dx_line_color = WHITE,
df_line_color = WHITE,
secant_line_color = YELLOW,
)
self.play(ShowCreation(graph))
self.play(Write(label, run_time = 1))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
self.play(Write(deriv_label, run_time = 1))
self.play(ShowCreation(ss_group, submobject_mode = "all_at_once"))
self.animate_secant_slope_group_change(
ss_group,
target_x = self.deriv_x_max,
run_time = 10,
added_anims = [
ShowCreation(deriv_graph, run_time = 10)
]
)
self.play(FadeIn(full_deriv_graph))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
for x_val in -2, -self.dx/2, 2:
self.animate_secant_slope_group_change(
ss_group,
target_x = x_val,
run_time = 2
)
if x_val != -self.dx/2:
v_line = self.get_vertical_line_to_graph(
x_val, deriv_graph,
line_class = DashedLine
)
self.play(ShowCreation(v_line))
self.play(FadeOut(v_line))
class PatternForPowerRule(PiCreatureScene):
CONFIG = {
"num_exponents" : 5,
}
def construct(self):
self.introduce_pattern()
self.generalize_pattern()
self.show_hopping()
def introduce_pattern(self):
exp_range = range(1, 1+self.num_exponents)
colors = color_gradient([BLUE_D, YELLOW], self.num_exponents)
derivatives = VGroup()
for exponent, color in zip(exp_range, colors):
derivative = TexMobject(
"\\frac{d(x^%d)}{dx} = "%exponent,
"%d x^{%d}"%(exponent, exponent-1)
)
2018-03-30 11:51:31 -07:00
VGroup(*derivative[0][2:4]).set_color(color)
2017-01-27 19:31:20 -08:00
derivatives.add(derivative)
derivatives.arrange_submobjects(
DOWN, aligned_edge = LEFT,
buff = MED_LARGE_BUFF
)
derivatives.scale_to_fit_height(FRAME_HEIGHT-1)
2017-01-27 19:31:20 -08:00
derivatives.to_edge(LEFT)
self.play(FadeIn(derivatives[0]))
for d1, d2 in zip(derivatives, derivatives[1:]):
self.play(Transform(
d1.copy(), d2,
replace_mobject_with_target_in_scene = True
))
self.change_mode("thinking")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
for derivative in derivatives[-2:]:
derivative.save_state()
self.play(
derivative.scale, 2,
derivative.next_to, derivative,
RIGHT, SMALL_BUFF, DOWN,
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-27 19:31:20 -08:00
self.play(derivative.restore)
self.remove(derivative)
derivative.restore()
self.add(derivative)
2017-01-25 13:00:01 -08:00
2017-01-27 19:31:20 -08:00
self.derivatives = derivatives
self.colors = colors
2017-01-25 13:00:01 -08:00
2017-01-27 19:31:20 -08:00
def generalize_pattern(self):
derivatives = self.derivatives
2017-01-25 13:00:01 -08:00
2017-01-27 19:31:20 -08:00
power_rule = TexMobject(
"\\frac{d (x^n)}{dx} = ",
"nx^{n-1}"
)
title = TextMobject("``Power rule''")
title.next_to(power_rule, UP, MED_LARGE_BUFF)
lines = VGroup(*[
Line(
deriv.get_right(), power_rule.get_left(),
buff = MED_SMALL_BUFF,
color = deriv[0][2].get_color()
)
for deriv in derivatives
])
self.play(
Transform(
VGroup(*[d[0].copy() for d in derivatives]),
VGroup(power_rule[0]),
replace_mobject_with_target_in_scene = True
),
ShowCreation(lines),
submobject_mode = "lagged_start",
run_time = 2,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
self.play(Write(power_rule[1]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
self.play(
Write(title),
self.pi_creature.change_mode, "speaking"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
def show_hopping(self):
exp_range = range(2, 2+self.num_exponents-1)
self.change_mode("tired")
for exp, color in zip(exp_range, self.colors[1:]):
form = TexMobject(
"x^",
str(exp),
"\\rightarrow",
str(exp),
"x^",
str(exp-1)
)
2018-03-30 11:51:31 -07:00
form.set_color(color)
2017-01-27 19:31:20 -08:00
form.to_corner(UP+RIGHT, buff = LARGE_BUFF)
lhs = VGroup(*form[:2])
lhs_copy = lhs.copy()
rhs = VGroup(*form[-2:])
arrow = form[2]
self.play(Write(lhs))
self.play(
lhs_copy.move_to, rhs, DOWN+LEFT,
Write(arrow)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
self.play(
ApplyMethod(
lhs_copy[1].replace, form[3],
path_arc = np.pi,
rate_func = running_start,
),
FadeIn(
form[5],
rate_func = squish_rate_func(smooth, 0.5, 1)
)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-27 19:31:20 -08:00
self.play(
self.pi_creature.change_mode, "hesitant",
self.pi_creature.look_at, lhs_copy
)
self.play(*map(FadeOut, [form, lhs_copy]))
2017-01-28 15:49:22 -08:00
class PowerRuleAlgebra(Scene):
CONFIG = {
"dx_color" : YELLOW,
"x_color" : BLUE,
}
def construct(self):
x_to_n = TexMobject("x^n")
down_arrow = Arrow(UP, DOWN, buff = MED_LARGE_BUFF)
paren_strings = ["(", "x", "+", "dx", ")"]
x_dx_to_n = TexMobject(*paren_strings +["^n"])
equals = TexMobject("=")
equals2 = TexMobject("=")
full_product = TexMobject(
*paren_strings*3+["\\cdots"]+paren_strings
)
2017-01-27 19:31:20 -08:00
2018-03-30 11:51:31 -07:00
x_to_n.set_color(self.x_color)
2017-01-28 15:49:22 -08:00
for mob in x_dx_to_n, full_product:
2018-03-30 11:51:31 -07:00
mob.set_color_by_tex("dx", self.dx_color)
mob.set_color_by_tex("x", self.x_color)
2017-01-28 15:49:22 -08:00
nudge_group = VGroup(x_to_n, down_arrow, x_dx_to_n)
nudge_group.arrange_submobjects(DOWN)
nudge_group.to_corner(UP+LEFT)
down_arrow.next_to(x_to_n[0], DOWN)
equals.next_to(x_dx_to_n)
full_product.next_to(equals)
equals2.next_to(equals, DOWN, 1.5*LARGE_BUFF)
nudge_brace = Brace(x_dx_to_n, DOWN)
nudged_output = nudge_brace.get_text("Nudged \\\\ output")
product_brace = Brace(full_product, UP)
product_brace.add(product_brace.get_text("$n$ times"))
self.add(x_to_n)
self.play(ShowCreation(down_arrow))
self.play(
FadeIn(x_dx_to_n),
GrowFromCenter(nudge_brace),
GrowFromCenter(nudged_output)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
self.play(
Write(VGroup(equals, full_product)),
GrowFromCenter(
product_brace,
rate_func = squish_rate_func(smooth, 0.6, 1)
),
run_time = 3
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
self.workout_product(equals2, full_product)
2017-01-27 19:31:20 -08:00
2017-01-28 15:49:22 -08:00
def workout_product(self, equals, full_product):
product_part_tex_pairs = zip(full_product, full_product.expression_parts)
xs, dxs = [
VGroup(*[
submob
for submob, tex in product_part_tex_pairs
if tex == target_tex
])
2018-07-11 11:38:59 -07:00
for target_tex in ("x", "dx")
2017-01-28 15:49:22 -08:00
]
x_to_n = TexMobject("x^n")
extra_stuff = TexMobject("+(\\text{Multiple of }\\, dx^2)")
# extra_stuff.scale(0.8)
2018-03-30 11:51:31 -07:00
VGroup(*extra_stuff[-4:-2]).set_color(self.dx_color)
2017-01-27 19:31:20 -08:00
2017-01-28 15:49:22 -08:00
x_to_n.next_to(equals, RIGHT, align_using_submobjects = True)
2018-03-30 11:51:31 -07:00
x_to_n.set_color(self.x_color)
2017-01-25 13:00:01 -08:00
2017-01-28 15:49:22 -08:00
xs_copy = xs.copy()
full_product.save_state()
2018-03-30 11:51:31 -07:00
self.play(full_product.set_color, WHITE)
self.play(xs_copy.set_color, self.x_color)
2017-01-28 15:49:22 -08:00
self.play(
Write(equals),
Transform(xs_copy, x_to_n)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
brace, derivative_term = self.pull_out_linear_terms(
x_to_n, product_part_tex_pairs, xs, dxs
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
2017-01-28 15:49:22 -08:00
circle = Circle(color = DERIVATIVE_COLOR)
circle.replace(derivative_term, stretch = True)
circle.scale_in_place(1.4)
circle.rotate_in_place(
Line(
derivative_term.get_corner(DOWN+LEFT),
derivative_term.get_corner(UP+RIGHT),
).get_angle()
)
2017-01-25 13:00:01 -08:00
2017-01-28 15:49:22 -08:00
extra_stuff.next_to(brace, aligned_edge = UP)
2017-01-25 13:00:01 -08:00
2017-01-28 15:49:22 -08:00
self.play(Write(extra_stuff), full_product.restore)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
self.play(ShowCreation(circle))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
def pull_out_linear_terms(self, x_to_n, product_part_tex_pairs, xs, dxs):
last_group = None
all_linear_terms = VGroup()
for dx_index, dx in enumerate(dxs):
if dx is dxs[-1]:
v_dots = TexMobject("\\vdots")
v_dots.next_to(last_group[0], DOWN)
h_dots_list = [
submob
for submob, tex in product_part_tex_pairs
if tex == "\\cdots"
]
h_dots_copy = h_dots_list[0].copy()
self.play(ReplacementTransform(
h_dots_copy, v_dots,
))
last_group.add(v_dots)
all_linear_terms.add(v_dots)
dx_copy = dx.copy()
xs_copy = xs.copy()
xs_copy.remove(xs_copy[dx_index])
self.play(
2018-03-30 11:51:31 -07:00
dx_copy.set_color, self.dx_color,
xs_copy.set_color, self.x_color,
2017-01-28 15:49:22 -08:00
rate_func = squish_rate_func(smooth, 0, 0.5)
)
dx_copy.generate_target()
xs_copy.generate_target()
target_list = [dx_copy.target] + list(xs_copy.target)
target_list.sort(
lambda m1, m2 : cmp(m1.get_center()[0], m2.get_center()[0])
)
dots = TexMobject("+", ".", ".", "\\dots")
for dot_index, dot in enumerate(dots):
target_list.insert(2*dot_index, dot)
group = VGroup(*target_list)
group.arrange_submobjects(RIGHT, SMALL_BUFF)
if last_group is None:
group.next_to(x_to_n, RIGHT)
else:
group.next_to(last_group, DOWN, aligned_edge = LEFT)
last_group = group
self.play(
MoveToTarget(dx_copy),
MoveToTarget(xs_copy),
Write(dots)
)
all_linear_terms.add(dx_copy, xs_copy, dots)
all_linear_terms.generate_target()
all_linear_terms.target.scale(0.7)
brace = Brace(all_linear_terms.target, UP)
compact = TexMobject("+\\,", "n", "x^{n-1}", "\\,dx")
2018-03-30 11:51:31 -07:00
compact.set_color_by_tex("x^{n-1}", self.x_color)
compact.set_color_by_tex("\\,dx", self.dx_color)
2017-01-28 15:49:22 -08:00
compact.next_to(brace, UP)
brace.add(compact)
derivative_term = VGroup(*compact[1:3])
VGroup(brace, all_linear_terms.target).shift(
x_to_n[0].get_right()+MED_LARGE_BUFF*RIGHT - \
compact[0].get_left()
)
self.play(MoveToTarget(all_linear_terms))
self.play(Write(brace, run_time = 1))
return brace, derivative_term
2017-01-31 22:17:16 -08:00
class ReactToFullExpansion(Scene):
def construct(self):
randy = Randolph()
self.add(randy)
self.play(randy.change_mode, "pleading")
self.play(Blink(randy))
self.play(randy.change_mode, "angry")
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
self.play(randy.change_mode, "thinking")
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
2017-01-28 18:18:32 -08:00
class OneOverX(PiCreatureScene, GraphScene):
2017-01-28 15:49:22 -08:00
CONFIG = {
2017-01-28 18:18:32 -08:00
"unit_length" : 3.0,
"graph_origin" : (FRAME_X_RADIUS - LARGE_BUFF)*LEFT + 2*DOWN,
2017-01-28 15:49:22 -08:00
"rectangle_color_kwargs" : {
"fill_color" : BLUE,
"fill_opacity" : 0.5,
2017-01-28 15:49:22 -08:00
"stroke_width" : 1,
"stroke_color" : WHITE,
},
2017-01-28 18:18:32 -08:00
"x_axis_label" : "",
"y_axis_label" : "",
"x_min" : 0,
"y_min" : 0,
"x_tick_frequency" : 0.5,
"y_tick_frequency" : 0.5,
"x_labeled_nums" : range(0, 4),
"y_labeled_nums" : [1],
"y_axis_height" : 10,
"morty_scale_val" : 0.8,
"area_label_scale_factor" : 0.75,
"dx" : 0.1,
"start_x_value" : 1.3,
"dx_color" : GREEN,
"df_color" : RED,
2017-01-28 15:49:22 -08:00
}
2017-01-28 18:18:32 -08:00
def setup(self):
for c in self.__class__.__bases__:
c.setup(self)
self.x_max = self.x_axis_width/self.unit_length
self.y_max = self.y_axis_height/self.unit_length
2017-01-28 15:49:22 -08:00
def construct(self):
2017-04-17 10:19:30 -07:00
self.force_skipping()
2017-01-28 18:18:32 -08:00
self.introduce_function()
self.introduce_puddle()
self.introduce_graph()
self.perform_nudge()
def introduce_function(self):
func = TexMobject("f(x) = ", "\\frac{1}{x}")
func.to_edge(UP)
recip_copy = func[1].copy()
x_to_neg_one = TexMobject("x^{-1}")
x_to_neg_one.submobjects.reverse()
neg_one = VGroup(*x_to_neg_one[:2])
neg_two = TexMobject("-2")
self.play(
Write(func),
self.pi_creature.change_mode, "pondering"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 18:18:32 -08:00
self.play(
recip_copy.next_to, self.pi_creature, UP+LEFT,
self.pi_creature.change_mode, "raise_right_hand"
)
x_to_neg_one.move_to(recip_copy)
neg_two.replace(neg_one)
self.play(ReplacementTransform(recip_copy, x_to_neg_one))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 18:18:32 -08:00
self.play(
neg_one.scale, 1.5,
neg_one.next_to, x_to_neg_one, LEFT, SMALL_BUFF, DOWN,
rate_func = running_start,
path_arc = np.pi
)
self.play(FadeIn(neg_two))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 18:18:32 -08:00
self.say(
"More geometry!",
target_mode = "hooray",
added_anims = [
FadeOut(x_to_neg_one),
FadeOut(neg_two),
],
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-17 10:19:30 -07:00
self.play(RemovePiCreatureBubble(self.pi_creature))
2017-01-28 18:18:32 -08:00
def introduce_puddle(self):
rect_group = self.get_rectangle_group(self.start_x_value)
self.play(
DrawBorderThenFill(rect_group.rectangle),
Write(rect_group.area_label),
self.pi_creature.change_mode, "thinking"
)
self.play(
GrowFromCenter(rect_group.x_brace),
Write(rect_group.x_label),
)
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
GrowFromCenter(rect_group.recip_brace),
Write(rect_group.recip_label),
)
self.setup_axes(animate = True)
2018-01-15 19:15:05 -08:00
self.wait()
for d in 2, 3:
self.change_rectangle_group(
rect_group, d,
target_group_kwargs = {
"x_label" : str(d),
"one_over_x_label" : "\\frac{1}{%d}"%d,
},
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
self.change_rectangle_group(rect_group, 3)
2018-01-15 19:15:05 -08:00
self.wait()
self.rect_group = rect_group
2017-01-28 18:18:32 -08:00
def introduce_graph(self):
rect_group = self.rect_group
graph = self.get_graph(lambda x : 1./x)
graph.points = np.array(list(reversed(graph.points)))
self.change_rectangle_group(
rect_group, 0.01,
added_anims = [
ShowCreation(graph)
],
run_time = 5,
)
self.change_mode("happy")
self.change_rectangle_group(rect_group, self.start_x_value)
2018-01-15 19:15:05 -08:00
self.wait()
self.graph = graph
2017-01-28 18:18:32 -08:00
def perform_nudge(self):
rect_group = self.rect_group
graph = self.graph
rect_copy = rect_group.rectangle.copy()
rect_copy.set_fill(opacity = 0)
new_rect = self.get_rectangle(
self.start_x_value + self.dx
)
recip_brace = rect_group.recip_brace
recip_brace.generate_target()
recip_brace.target.next_to(
new_rect, RIGHT,
buff = SMALL_BUFF,
aligned_edge = DOWN,
)
recip_label = rect_group.recip_label
recip_label.generate_target()
recip_label.target.next_to(recip_brace.target, RIGHT)
h_lines = VGroup(*[
DashedLine(
ORIGIN, (rect_copy.get_width()+LARGE_BUFF)*RIGHT,
color = self.df_color,
stroke_width = 2
).move_to(rect.get_corner(UP+LEFT), LEFT)
2018-07-11 11:38:59 -07:00
for rect in (rect_group.rectangle, new_rect)
])
v_lines = VGroup(*[
DashedLine(
ORIGIN, (rect_copy.get_height()+MED_LARGE_BUFF)*UP,
color = self.dx_color,
stroke_width = 2
).move_to(rect.get_corner(DOWN+RIGHT), DOWN)
2018-07-11 11:38:59 -07:00
for rect in (rect_group.rectangle, new_rect)
])
dx_brace = Brace(v_lines, UP, buff = 0)
dx_label = dx_brace.get_text("$dx$")
dx_brace.add(dx_label)
df_brace = Brace(h_lines, RIGHT, buff = 0)
df_label = df_brace.get_text("$d\\left(\\frac{1}{x}\\right)$")
df_brace.add(df_label)
2017-04-17 10:19:30 -07:00
negative = TextMobject("Negative")
2018-03-30 11:51:31 -07:00
negative.set_color(RED)
2017-04-17 10:19:30 -07:00
negative.next_to(df_label, UP+RIGHT)
negative.shift(RIGHT)
negative_arrow = Arrow(
negative.get_left(),
df_label.get_corner(UP+RIGHT),
color = RED
)
area_changes = VGroup()
point_pairs = [
(new_rect.get_corner(UP+RIGHT), rect_copy.get_corner(DOWN+RIGHT)),
(new_rect.get_corner(UP+LEFT), rect_copy.get_corner(UP+RIGHT))
]
for color, point_pair in zip([self.dx_color, self.df_color], point_pairs):
area_change_rect = Rectangle(
fill_opacity = 1,
fill_color = color,
stroke_width = 0
)
area_change_rect.replace(
VGroup(*map(VectorizedPoint, point_pair)),
stretch = True
)
area_changes.add(area_change_rect)
area_gained, area_lost = area_changes
area_gained_label = TextMobject("Area gained")
area_gained_label.scale(0.75)
area_gained_label.next_to(
rect_copy.get_corner(DOWN+RIGHT),
UP+LEFT, buff = SMALL_BUFF
)
area_gained_arrow = Arrow(
area_gained_label.get_top(),
area_gained.get_center(),
buff = 0,
color = WHITE
)
area_lost_label = TextMobject("Area lost")
area_lost_label.scale(0.75)
area_lost_label.next_to(rect_copy.get_left(), RIGHT)
area_lost_arrow = Arrow(
area_lost_label.get_top(),
area_lost.get_center(),
buff = 0,
color = WHITE
)
question = TexMobject(
"\\frac{d(1/x)}{dx} = ???"
)
question.next_to(
self.pi_creature.get_corner(UP+LEFT),
UP, buff = MED_SMALL_BUFF,
)
self.play(
FadeOut(rect_group.area_label),
ReplacementTransform(rect_copy, new_rect),
MoveToTarget(recip_brace),
MoveToTarget(recip_label),
self.pi_creature.change_mode, "pondering"
)
self.play(
GrowFromCenter(dx_brace),
*map(ShowCreation, v_lines)
)
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
GrowFromCenter(df_brace),
*map(ShowCreation, h_lines)
)
self.change_mode("confused")
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
FadeIn(area_gained),
Write(area_gained_label, run_time = 2),
ShowCreation(area_gained_arrow)
)
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
FadeIn(area_lost),
Write(area_lost_label, run_time = 2),
ShowCreation(area_lost_arrow)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-17 10:19:30 -07:00
self.revert_to_original_skipping_status()###
self.play(
2017-04-17 10:19:30 -07:00
Write(negative),
ShowCreation(negative_arrow)
)
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
Write(question),
self.pi_creature.change_mode, "raise_right_hand"
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-01-28 18:18:32 -08:00
########
def create_pi_creature(self):
morty = PiCreatureScene.create_pi_creature(self)
2017-01-28 18:18:32 -08:00
morty.scale(
self.morty_scale_val,
about_point = morty.get_corner(DOWN+RIGHT)
)
return morty
def draw_graph(self):
self.setup_axes()
graph = self.get_graph(lambda x : 1./x)
rect_group = self.get_rectangle_group(0.5)
2017-01-28 15:49:22 -08:00
self.add(rect_group)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 18:18:32 -08:00
self.change_rectangle_group(
rect_group, 2,
target_group_kwargs = {
"x_label" : "2",
"one_over_x_label" : "\\frac{1}{2}",
},
added_anims = [ShowCreation(graph)]
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-28 15:49:22 -08:00
def get_rectangle_group(
self, x,
x_label = "x",
one_over_x_label = "\\frac{1}{x}"
):
2017-01-28 18:18:32 -08:00
result = VGroup()
result.x_val = x
2017-01-28 15:49:22 -08:00
result.rectangle = self.get_rectangle(x)
result.x_brace, result.recip_brace = braces = [
2017-01-28 18:18:32 -08:00
Brace(result.rectangle, vect)
2018-07-11 11:38:59 -07:00
for vect in (UP, RIGHT)
2017-01-28 18:18:32 -08:00
]
result.labels = VGroup()
for brace, label in zip(braces, [x_label, one_over_x_label]):
brace.get_text("$%s$"%label)
result.labels.add(brace.get_text("$%s$"%label))
result.x_label, result.recip_label = result.labels
2017-01-28 18:18:32 -08:00
area_label = TextMobject("Area = 1")
area_label.scale(self.area_label_scale_factor)
max_width = max(result.rectangle.get_width()-2*SMALL_BUFF, 0)
if area_label.get_width() > max_width:
area_label.scale_to_fit_width(max_width)
area_label.move_to(result.rectangle)
result.area_label = area_label
result.add(
result.rectangle,
result.x_brace,
result.recip_brace,
2017-01-28 18:18:32 -08:00
result.labels,
result.area_label,
)
2017-01-28 15:49:22 -08:00
return result
def get_rectangle(self, x):
try:
y = 1./x
except ZeroDivisionError:
y = 100
2017-01-28 15:49:22 -08:00
rectangle = Rectangle(
width = x*self.unit_length,
height = y*self.unit_length,
2017-01-28 15:49:22 -08:00
**self.rectangle_color_kwargs
)
2017-01-28 18:18:32 -08:00
rectangle.move_to(self.graph_origin, DOWN+LEFT)
2017-01-28 15:49:22 -08:00
return rectangle
def change_rectangle_group(
self,
rect_group, target_x,
target_group_kwargs = None,
added_anims = [],
**anim_kwargs
):
target_group_kwargs = target_group_kwargs or {}
if "run_time" not in anim_kwargs:
anim_kwargs["run_time"] = 3
target_group = self.get_rectangle_group(target_x, **target_group_kwargs)
2017-01-28 18:18:32 -08:00
target_labels = target_group.labels
labels_transform = Transform(
rect_group.labels,
target_group.labels
)
start_x = float(rect_group.x_val)
def update_rect_group(group, alpha):
x = interpolate(start_x, target_x, alpha)
new_group = self.get_rectangle_group(x, **target_group_kwargs)
Transform(group, new_group).update(1)
labels_transform.update(alpha)
for l1, l2 in zip(rect_group.labels, new_group.labels):
l1.move_to(l2)
return rect_group
2017-01-28 15:49:22 -08:00
self.play(
2017-01-28 18:18:32 -08:00
UpdateFromAlphaFunc(rect_group, update_rect_group),
2017-01-28 15:49:22 -08:00
*added_anims,
**anim_kwargs
)
rect_group.x_val = target_x
2017-01-25 13:00:01 -08:00
2017-01-31 22:17:16 -08:00
class AskRecipriocalQuestion(Scene):
def construct(self):
tex = TexMobject(
"(\\text{What number?})",
"\\cdot x = 1"
)
arrow = Arrow(DOWN+LEFT, UP+RIGHT)
arrow.move_to(tex[0].get_top(), DOWN+LEFT)
self.play(Write(tex))
self.play(ShowCreation(arrow))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
class SquareRootOfX(Scene):
CONFIG = {
"square_color_kwargs" : {
"stroke_color" : WHITE,
"stroke_width" : 1,
"fill_color" : BLUE_E,
"fill_opacity" : 1,
},
"bigger_square_color_kwargs" : {
"stroke_color" : WHITE,
"stroke_width" : 1,
"fill_color" : YELLOW,
"fill_opacity" : 0.7,
},
"square_corner" : 6*LEFT+3*UP,
"square_width" : 3,
"d_sqrt_x" : 0.3,
}
def construct(self):
self.add_title()
self.introduce_square()
self.nudge_square()
2017-01-25 13:00:01 -08:00
def add_title(self):
title = TexMobject("f(x) = \\sqrt{x}")
title.next_to(ORIGIN, RIGHT)
title.to_edge(UP)
self.add(title)
2017-01-25 13:00:01 -08:00
def introduce_square(self):
square = Square(
side_length = self.square_width,
**self.square_color_kwargs
)
square.move_to(self.square_corner, UP+LEFT)
area_label = TextMobject("Area $ = x$")
area_label.move_to(square)
2017-01-25 13:00:01 -08:00
bottom_brace, right_brace = braces = VGroup(*[
Brace(square, vect)
2018-07-11 11:38:59 -07:00
for vect in (DOWN, RIGHT)
])
for brace in braces:
brace.add(brace.get_text("$\\sqrt{x}$"))
2017-01-25 13:00:01 -08:00
self.play(
DrawBorderThenFill(square),
Write(area_label)
)
self.play(*map(FadeIn, braces))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
self.square = square
self.area_label = area_label
self.braces = braces
2017-01-25 13:00:01 -08:00
def nudge_square(self):
square = self.square
area_label = self.area_label
bottom_brace, right_brace = self.braces
2017-01-25 13:00:01 -08:00
bigger_square = Square(
side_length = self.square_width + self.d_sqrt_x,
**self.bigger_square_color_kwargs
)
bigger_square.move_to(self.square_corner, UP+LEFT)
2017-01-25 13:00:01 -08:00
square_copy = square.copy()
2017-01-25 13:00:01 -08:00
lines = VGroup(*[
DashedLine(
ORIGIN,
(self.square_width + MED_LARGE_BUFF)*vect,
color = WHITE,
stroke_width = 3
).shift(s.get_corner(corner))
for corner, vect in [(DOWN+LEFT, RIGHT), (UP+RIGHT, DOWN)]
for s in square, bigger_square
])
little_braces = VGroup(*[
Brace(VGroup(*line_pair), vect, buff = 0)
for line_pair, vect in (lines[:2], RIGHT), (lines[2:], DOWN)
])
for brace in little_braces:
tex = brace.get_text("$d\\sqrt{x}$", buff = SMALL_BUFF)
tex.scale_in_place(0.8)
brace.add(tex)
area_increase = TextMobject("$dx$ = New area")
2018-03-30 11:51:31 -07:00
area_increase.set_color(bigger_square.get_color())
area_increase.next_to(square, RIGHT, 4)
question = TexMobject("\\frac{d\\sqrt{x}}{dx} = ???")
2018-03-30 11:51:31 -07:00
VGroup(*question[5:7]).set_color(bigger_square.get_color())
question.next_to(
area_increase, DOWN,
aligned_edge = LEFT,
buff = LARGE_BUFF
)
self.play(
Transform(square_copy, bigger_square),
Animation(square),
Animation(area_label),
bottom_brace.next_to, bigger_square, DOWN, SMALL_BUFF, LEFT,
right_brace.next_to, bigger_square, RIGHT, SMALL_BUFF, UP,
)
self.play(Write(area_increase))
self.play(*it.chain(
map(ShowCreation, lines),
map(FadeIn, little_braces)
))
self.play(Write(question))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-25 13:00:01 -08:00
class MentionSine(TeacherStudentsScene):
def construct(self):
self.teacher_says("Let's tackle $\\sin(\\theta)$")
self.change_student_modes("pondering", "hooray", "erm")
2018-01-15 19:15:05 -08:00
self.wait(2)
self.student_thinks("")
self.zoom_in_on_thought_bubble()
2017-01-25 13:00:01 -08:00
2017-01-31 22:17:16 -08:00
class NameUnitCircle(Scene):
def construct(self):
words = TextMobject("Unit circle")
words.scale(2)
2018-03-30 11:51:31 -07:00
words.set_color(BLUE)
2017-01-31 22:17:16 -08:00
self.play(Write(words))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
class DerivativeOfSineIsSlope(Scene):
def construct(self):
tex = TexMobject(
"\\frac{d(\\sin(\\theta))}{d\\theta} = ",
"\\text{Slope of this graph}"
)
tex.scale_to_fit_width(FRAME_WIDTH-1)
2017-01-31 22:17:16 -08:00
tex.to_edge(DOWN)
2018-03-30 11:51:31 -07:00
VGroup(*tex[0][2:8]).set_color(BLUE)
VGroup(*tex[1][-9:]).set_color(BLUE)
2017-01-31 22:17:16 -08:00
self.play(Write(tex, run_time = 2))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
class IntroduceUnitCircleWithSine(GraphScene):
CONFIG = {
"unit_length" : 2.5,
"graph_origin" : ORIGIN,
"x_axis_width" : 15,
"y_axis_height" : 10,
"x_min" : -3,
"x_max" : 3,
"y_min" : -2,
"y_max" : 2,
"x_labeled_nums" : [-2, -1, 1, 2],
"y_labeled_nums" : [-1, 1],
"x_tick_frequency" : 0.5,
"y_tick_frequency" : 0.5,
"circle_color" : BLUE,
"example_radians" : 0.8,
"rotations_per_second" : 0.25,
"include_radial_line_dot" : True,
"remove_angle_label" : True,
"line_class" : DashedLine,
"theta_label" : "= 0.8",
}
def construct(self):
self.setup_axes()
self.add_title()
self.introduce_unit_circle()
self.draw_example_radians()
self.label_sine()
self.walk_around_circle()
def add_title(self):
title = TexMobject("f(\\theta) = \\sin(\\theta)")
title.to_corner(UP+LEFT)
self.add(title)
2017-01-30 16:48:26 -08:00
self.title = title
def introduce_unit_circle(self):
circle = self.get_unit_circle()
radial_line = Line(ORIGIN, self.unit_length*RIGHT)
2018-03-30 11:51:31 -07:00
radial_line.set_color(RED)
if self.include_radial_line_dot:
dot = Dot()
dot.move_to(radial_line.get_end())
radial_line.add(dot)
self.play(ShowCreation(radial_line))
self.play(
ShowCreation(circle),
Rotate(radial_line, 2*np.pi),
run_time = 2,
)
2018-01-15 19:15:05 -08:00
self.wait()
self.circle = circle
self.radial_line = radial_line
def draw_example_radians(self):
circle = self.circle
radial_line = self.radial_line
line = Line(
ORIGIN, self.example_radians*self.unit_length*UP,
color = YELLOW,
)
line.shift(FRAME_X_RADIUS*RIGHT/3).to_edge(UP)
line.insert_n_anchor_points(10)
line.make_smooth()
arc = Arc(
self.example_radians, radius = self.unit_length,
color = line.get_color(),
)
2018-03-30 11:51:31 -07:00
arc_copy = arc.copy().set_color(WHITE)
brace = Brace(line, RIGHT)
brace_text = brace.get_text("$\\theta%s$"%self.theta_label)
2018-03-30 11:51:31 -07:00
brace_text.set_color(line.get_color())
theta_copy = brace_text[0].copy()
self.play(
GrowFromCenter(line),
GrowFromCenter(brace),
)
self.play(Write(brace_text))
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
line.move_to, radial_line.get_end(), DOWN,
FadeOut(brace)
)
self.play(ReplacementTransform(line, arc))
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
Rotate(radial_line, self.example_radians),
ShowCreation(arc_copy)
)
2018-01-15 19:15:05 -08:00
self.wait()
arc_copy.generate_target()
arc_copy.target.scale(0.2)
theta_copy.generate_target()
theta_copy.target.next_to(
arc_copy.target, RIGHT,
aligned_edge = DOWN,
buff = SMALL_BUFF
)
theta_copy.target.shift(SMALL_BUFF*UP)
self.play(*map(MoveToTarget, [arc_copy, theta_copy]))
2018-01-15 19:15:05 -08:00
self.wait()
self.angle_label = VGroup(arc_copy, theta_copy)
self.example_theta_equation = brace_text
def label_sine(self):
radial_line = self.radial_line
2017-01-25 13:00:01 -08:00
drop_point = radial_line.get_end()[0]*RIGHT
v_line = self.line_class(radial_line.get_end(), drop_point)
brace = Brace(v_line, RIGHT)
brace_text = brace.get_text("$\\sin(\\theta)$")
2018-03-30 11:51:31 -07:00
brace_text[-2].set_color(YELLOW)
2017-01-25 13:00:01 -08:00
self.play(ShowCreation(v_line))
self.play(
GrowFromCenter(brace),
Write(brace_text)
)
2018-01-15 19:15:05 -08:00
self.wait()
faders = [brace, brace_text, self.example_theta_equation]
if self.remove_angle_label:
faders += self.angle_label
self.play(*map(FadeOut, faders))
self.v_line = v_line
def walk_around_circle(self):
radial_line = self.radial_line
v_line = self.v_line
def v_line_update(v_line):
drop_point = radial_line.get_end()[0]*RIGHT
v_line.put_start_and_end_on(
radial_line.get_end(), drop_point
)
return v_line
filler_arc = self.circle.copy()
2018-03-30 11:51:31 -07:00
filler_arc.set_color(YELLOW)
curr_arc_portion = self.example_radians/(2*np.pi)
filler_portion = 1 - curr_arc_portion
filler_arc.pointwise_become_partial(filler_arc, curr_arc_portion, 1)
self.play(
Rotate(radial_line, filler_portion*2*np.pi),
ShowCreation(filler_arc),
UpdateFromFunc(v_line, v_line_update),
run_time = filler_portion/self.rotations_per_second,
rate_func = None,
)
for x in range(5):
self.play(
Rotate(radial_line, 2*np.pi),
UpdateFromFunc(v_line, v_line_update),
run_time = 1./self.rotations_per_second,
rate_func = None,
)
##############
def setup_axes(self):
GraphScene.setup_axes(self)
VGroup(*self.x_axis.numbers[:2]).shift(MED_SMALL_BUFF*LEFT)
VGroup(*self.x_axis.numbers[2:]).shift(SMALL_BUFF*RIGHT)
self.y_axis.numbers[0].shift(MED_SMALL_BUFF*DOWN)
self.y_axis.numbers[1].shift(MED_SMALL_BUFF*UP)
def get_unit_circle(self):
return Circle(
radius = self.unit_length,
color = self.circle_color,
)
class DerivativeIntuitionFromSineGraph(GraphScene):
CONFIG = {
"graph_origin" : 6*LEFT,
"x_axis_width" : 11,
"x_min" : 0,
"x_max" : 4*np.pi,
"x_labeled_nums" : np.arange(0, 4*np.pi, np.pi),
"x_tick_frequency" : np.pi/4,
"x_axis_label" : "$\\theta$",
"y_axis_height" : 6,
"y_min" : -2,
"y_max" : 2,
"y_tick_frequency" : 0.5,
"y_axis_label" : "",
}
def construct(self):
self.setup_axes()
self.draw_sine_graph()
self.draw_derivative_from_slopes()
2017-01-31 22:17:16 -08:00
self.alter_derivative_graph()
def draw_sine_graph(self):
graph = self.get_graph(np.sin)
v_line = DashedLine(ORIGIN, UP)
rps = IntroduceUnitCircleWithSine.CONFIG["rotations_per_second"]
self.play(
ShowCreation(graph),
UpdateFromFunc(v_line, lambda v : self.v_line_update(v, graph)),
run_time = 2./rps,
rate_func = None
)
2018-01-15 19:15:05 -08:00
self.wait()
self.graph = graph
def draw_derivative_from_slopes(self):
ss_group = self.get_secant_slope_group(
0, self.graph,
dx = 0.01,
secant_line_color = RED,
)
deriv_graph = self.get_graph(np.cos, color = DERIVATIVE_COLOR)
v_line = DashedLine(
self.graph_origin, self.coords_to_point(0, 1),
color = RED
)
self.play(ShowCreation(ss_group, submobject_mode = "all_at_once"))
self.play(ShowCreation(v_line))
2018-01-15 19:15:05 -08:00
self.wait()
last_theta = 0
next_theta = np.pi/2
while last_theta < self.x_max:
deriv_copy = deriv_graph.copy()
self.animate_secant_slope_group_change(
ss_group,
target_x = next_theta,
added_anims = [
ShowCreation(
deriv_copy,
rate_func = lambda t : interpolate(
last_theta/self.x_max,
next_theta/self.x_max,
smooth(t)
),
run_time = 3,
),
UpdateFromFunc(
v_line,
lambda v : self.v_line_update(v, deriv_copy),
run_time = 3
),
]
)
2018-01-15 19:15:05 -08:00
self.wait()
if next_theta == 2*np.pi:
words = TextMobject("Looks a lot like $\\cos(\\theta)$")
words.next_to(self.graph_origin, RIGHT)
words.to_edge(UP)
arrow = Arrow(
words.get_bottom(),
deriv_graph.point_from_proportion(0.45)
)
2018-03-30 11:51:31 -07:00
VGroup(words, arrow).set_color(deriv_graph.get_color())
self.play(
Write(words),
ShowCreation(arrow)
)
self.remove(deriv_copy)
last_theta = next_theta
next_theta += np.pi/2
self.add(deriv_copy)
2017-01-31 22:17:16 -08:00
self.deriv_graph = deriv_copy
def alter_derivative_graph(self):
func_list = [
lambda x : 0.5*(np.cos(x)**3 + np.cos(x)),
lambda x : 0.75*(np.sign(np.cos(x))*np.cos(x)**2 + np.cos(x)),
lambda x : 2*np.cos(x),
lambda x : np.cos(x),
]
for func in func_list:
new_graph = self.get_graph(func, color = DERIVATIVE_COLOR)
self.play(
Transform(self.deriv_graph, new_graph),
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
######
def v_line_update(self, v_line, graph):
point = graph.point_from_proportion(1)
drop_point = point[0]*RIGHT
v_line.put_start_and_end_on(drop_point, point)
return v_line
def setup_axes(self):
GraphScene.setup_axes(self)
self.x_axis.remove(self.x_axis.numbers)
self.remove(self.x_axis.numbers)
for x in range(1, 4):
if x == 1:
label = TexMobject("\\pi")
else:
label = TexMobject("%d\\pi"%x)
label.next_to(self.coords_to_point(x*np.pi, 0), DOWN, MED_LARGE_BUFF)
self.add(label)
2018-03-30 11:51:31 -07:00
self.x_axis_label_mob.set_color(YELLOW)
2017-01-30 20:28:01 -08:00
class LookToFunctionsMeaning(TeacherStudentsScene):
def construct(self):
self.teacher_says("""
Look to the function's
actual meaning
""")
self.change_student_modes(*["pondering"]*3)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-01-30 20:28:01 -08:00
class DerivativeFromZoomingInOnSine(IntroduceUnitCircleWithSine, ZoomedScene):
CONFIG = {
"zoom_factor" : 10,
"zoomed_canvas_frame_shape" : (3, 4.5),
"include_radial_line_dot" : False,
"remove_angle_label" : False,
"theta_label" : "",
"line_class" : Line,
"example_radians" : 1.0,
"zoomed_canvas_corner_buff" : SMALL_BUFF,
"d_theta" : 0.05,
}
def construct(self):
self.setup_axes()
self.add_title()
self.introduce_unit_circle()
self.draw_example_radians()
self.label_sine()
self.zoom_in()
self.perform_nudge()
self.show_similar_triangles()
self.analyze_ratios()
def zoom_in(self):
self.activate_zooming()
self.little_rectangle.next_to(self.radial_line.get_end(), UP, LARGE_BUFF)
self.play(*map(FadeIn, [
self.little_rectangle, self.big_rectangle
]))
self.play(
self.little_rectangle.move_to,
self.radial_line.get_end(), DOWN+RIGHT,
self.little_rectangle.shift,
SMALL_BUFF*(DOWN+RIGHT)
)
2018-01-15 19:15:05 -08:00
self.wait()
def perform_nudge(self):
d_theta_arc = Arc(
start_angle = self.example_radians,
angle = self.d_theta,
radius = self.unit_length,
color = MAROON_B,
stroke_width = 6
)
d_theta_arc.scale(self.zoom_factor)
d_theta_brace = Brace(
d_theta_arc,
rotate_vector(RIGHT, self.example_radians)
)
d_theta_label = TexMobject("d\\theta")
d_theta_label.next_to(
d_theta_brace.get_center(), d_theta_brace.direction,
MED_LARGE_BUFF
)
2018-03-30 11:51:31 -07:00
d_theta_label.set_color(d_theta_arc.get_color())
group = VGroup(d_theta_arc, d_theta_brace, d_theta_label)
group.scale(1./self.zoom_factor)
point = self.radial_line.get_end()
nudged_point = d_theta_arc.point_from_proportion(1)
interim_point = nudged_point[0]*RIGHT+point[1]*UP
h_line = DashedLine(
interim_point, point,
dashed_segment_length = 0.01
)
d_sine_line = Line(interim_point, nudged_point, color = DERIVATIVE_COLOR)
d_sine_brace = Brace(Line(ORIGIN, UP), LEFT)
d_sine_brace.scale_to_fit_height(d_sine_line.get_height())
d_sine_brace.next_to(d_sine_line, LEFT, buff = SMALL_BUFF/self.zoom_factor)
d_sine = TexMobject("d(\\sin(\\theta))")
2018-03-30 11:51:31 -07:00
d_sine.set_color(d_sine_line.get_color())
d_sine.scale_to_fit_width(1.5*self.d_theta*self.unit_length)
d_sine.next_to(d_sine_brace, LEFT, SMALL_BUFF/self.zoom_factor)
2017-01-30 16:48:26 -08:00
self.play(ShowCreation(d_theta_arc))
self.play(
GrowFromCenter(d_theta_brace),
FadeIn(d_theta_label)
)
2018-01-15 19:15:05 -08:00
self.wait()
self.play(
ShowCreation(h_line),
ShowCreation(d_sine_line)
)
self.play(
GrowFromCenter(d_sine_brace),
Write(d_sine)
)
2018-01-15 19:15:05 -08:00
self.wait()
self.little_triangle = Polygon(
nudged_point, point, interim_point
)
2017-01-30 16:48:26 -08:00
self.d_theta_group = VGroup(d_theta_brace, d_theta_label)
self.d_sine_group = VGroup(d_sine_brace, d_sine)
def show_similar_triangles(self):
little_triangle = self.little_triangle
big_triangle = Polygon(
self.graph_origin,
self.radial_line.get_end(),
self.radial_line.get_end()[0]*RIGHT,
)
for triangle in little_triangle, big_triangle:
2018-03-30 11:51:31 -07:00
triangle.set_color(GREEN)
triangle.set_fill(GREEN, opacity = 0.5)
2017-01-31 22:17:16 -08:00
big_triangle_copy = big_triangle.copy()
big_triangle_copy.next_to(ORIGIN, UP+LEFT)
2017-01-30 16:48:26 -08:00
new_angle_label = self.angle_label.copy()
new_angle_label.scale(
little_triangle.get_width()/big_triangle.get_height()
)
new_angle_label.rotate(-np.pi/2)
new_angle_label.shift(little_triangle.points[0])
new_angle_label[1].rotate_in_place(np.pi/2)
2017-01-31 22:17:16 -08:00
little_triangle_lines = VGroup(*[
Line(*map(little_triangle.get_corner, pair))
for pair in [
(DOWN+RIGHT, UP+LEFT),
(UP+LEFT, DOWN+LEFT)
]
])
2018-03-30 11:51:31 -07:00
little_triangle_lines.set_color(little_triangle.get_color())
2017-01-31 22:17:16 -08:00
2017-01-30 16:48:26 -08:00
self.play(DrawBorderThenFill(little_triangle))
2017-01-31 22:17:16 -08:00
self.play(
little_triangle.scale, 2, little_triangle.get_corner(DOWN+RIGHT),
2018-03-30 11:51:31 -07:00
little_triangle.set_color, YELLOW,
2017-01-31 22:17:16 -08:00
rate_func = there_and_back
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
groups = [self.d_theta_group, self.d_sine_group]
for group, line in zip(groups, little_triangle_lines):
self.play(ApplyMethod(
line.rotate_in_place, np.pi/12,
rate_func = wiggle,
remover = True,
))
2017-01-30 16:48:26 -08:00
self.play(
2017-01-31 22:17:16 -08:00
group.scale, 1.2, group.get_corner(DOWN+RIGHT),
2018-03-30 11:51:31 -07:00
group.set_color, YELLOW,
2017-01-30 16:48:26 -08:00
rate_func = there_and_back,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-31 22:17:16 -08:00
self.play(ReplacementTransform(
little_triangle.copy().set_fill(opacity = 0),
big_triangle_copy,
path_arc = np.pi/2,
run_time = 2
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
self.play(
2017-01-31 22:17:16 -08:00
ReplacementTransform(big_triangle_copy, big_triangle),
2017-01-30 16:48:26 -08:00
Animation(self.angle_label)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
self.play(
self.radial_line.rotate_in_place, np.pi/12,
Animation(big_triangle),
rate_func = wiggle,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
self.play(
ReplacementTransform(
big_triangle.copy().set_fill(opacity = 0),
little_triangle,
path_arc = -np.pi/2,
run_time = 3,
),
2017-01-31 22:17:16 -08:00
ReplacementTransform(
self.angle_label.copy(),
new_angle_label,
path_arc = -np.pi/2,
run_time = 3,
),
)
self.play(
new_angle_label.scale_in_place, 2,
2018-03-30 11:51:31 -07:00
new_angle_label.set_color, RED,
2017-01-31 22:17:16 -08:00
rate_func = there_and_back
2017-01-30 16:48:26 -08:00
)
2018-01-15 19:15:05 -08:00
self.wait()
def analyze_ratios(self):
2017-01-30 16:48:26 -08:00
d_ratio = TexMobject("\\frac{d(\\sin(\\theta))}{d\\theta} = ")
2018-03-30 11:51:31 -07:00
VGroup(*d_ratio[:9]).set_color(GREEN)
VGroup(*d_ratio[10:12]).set_color(MAROON_B)
2017-01-30 16:48:26 -08:00
trig_ratio = TexMobject("\\frac{\\text{Adj.}}{\\text{Hyp.}}")
2018-03-30 11:51:31 -07:00
VGroup(*trig_ratio[:4]).set_color(GREEN)
VGroup(*trig_ratio[5:9]).set_color(MAROON_B)
2017-01-30 16:48:26 -08:00
cos = TexMobject("= \\cos(\\theta)")
cos.add_background_rectangle()
group = VGroup(d_ratio, trig_ratio, cos)
group.arrange_submobjects()
group.next_to(
self.title, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = LEFT
)
for mob in group:
self.play(Write(mob))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
2017-01-31 22:17:16 -08:00
class TryWithCos(Scene):
2017-01-30 16:48:26 -08:00
def construct(self):
2017-01-31 22:17:16 -08:00
words = TextMobject("What about $\\cos(\\theta)$?")
2018-03-30 11:51:31 -07:00
words.set_color(YELLOW)
2017-01-31 22:17:16 -08:00
self.play(Write(words))
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
class NextVideo(TeacherStudentsScene):
def construct(self):
series = VideoSeries()
next_video = series[3]
series.to_edge(UP)
d_sum = TexMobject("\\frac{d}{dx}(x^3 + x^2)")
d_product = TexMobject("\\frac{d}{dx} \\sin(x)x^2")
d_composition = TexMobject("\\frac{d}{dx} \\cos\\left(\\frac{1}{x}\\right)")
group = VGroup(d_sum, d_product, d_composition)
group.arrange_submobjects(RIGHT, buff = 2*LARGE_BUFF)
group.next_to(VGroup(*self.get_pi_creatures()), UP, buff = LARGE_BUFF)
2017-01-30 16:48:26 -08:00
self.play(
FadeIn(
series,
submobject_mode = "lagged_start",
run_time = 3,
),
*[
ApplyMethod(pi.look_at, next_video)
for pi in self.get_pi_creatures()
2017-01-30 16:48:26 -08:00
]
)
self.play(
2018-03-30 11:51:31 -07:00
next_video.set_color, YELLOW,
2017-01-30 16:48:26 -08:00
next_video.shift, MED_LARGE_BUFF*DOWN
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-01-30 16:48:26 -08:00
for mob in group:
self.play(
Write(mob, run_time = 1),
*[
ApplyMethod(pi.look_at, mob)
for pi in self.get_pi_creatures()
2017-01-30 16:48:26 -08:00
]
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-01-30 16:48:26 -08:00
class Chapter3PatreonThanks(PatreonThanks):
CONFIG = {
"specific_patrons" : [
"Ali Yahya",
"CrypticSwarm ",
"Yu Jun",
"Shelby Doolittle",
"Dave Nicponski",
"Damion Kistler",
"Juan Benet",
"Othman Alikhan",
"Markus Persson",
"Dan Buchoff",
"Derek Dai",
"Joseph John Cox",
"Luc Ritchie",
"Guido Gambardella",
"Jerry Ling",
"Mark Govea",
"Vecht ",
"Jonathan Eppele",
"Shimin Kuang",
"Rish Kundalia",
"Achille Brighton",
"Kirk Werklund",
"Ripta Pasay",
"Felipe Diniz",
]
}
2017-04-29 18:23:00 -07:00
class Promotion(PiCreatureScene):
CONFIG = {
"seconds_to_blink" : 5,
}
def construct(self):
url = TextMobject("https://brilliant.org/3b1b/")
url.to_corner(UP+LEFT)
rect = Rectangle(height = 9, width = 16)
rect.scale_to_fit_height(5.5)
rect.next_to(url, DOWN)
rect.to_edge(LEFT)
self.play(
Write(url),
self.pi_creature.change, "raise_right_hand"
)
self.play(ShowCreation(rect))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-29 18:23:00 -07:00
self.change_mode("thinking")
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-29 18:23:00 -07:00
self.look_at(url)
2018-01-15 19:15:05 -08:00
self.wait(10)
2017-04-29 18:23:00 -07:00
self.change_mode("happy")
2018-01-15 19:15:05 -08:00
self.wait(10)
2017-04-29 18:23:00 -07:00
self.change_mode("raise_right_hand")
2018-01-15 19:15:05 -08:00
self.wait(10)
2017-04-29 18:23:00 -07:00
2017-01-31 22:17:16 -08:00
class Thumbnail(NudgeSideLengthOfCube):
def construct(self):
self.introduce_cube()
VGroup(*self.get_mobjects()).to_edge(DOWN)
2017-01-30 16:48:26 -08:00
2017-01-31 22:17:16 -08:00
formula = TexMobject(
"\\frac{d(x^3)}{dx} = 3x^2"
)
2018-03-30 11:51:31 -07:00
VGroup(*formula[:5]).set_color(YELLOW)
VGroup(*formula[-3:]).set_color(GREEN_B)
formula.scale_to_fit_width(FRAME_X_RADIUS-1)
2017-01-31 22:17:16 -08:00
formula.to_edge(RIGHT)
self.add(formula)
2017-01-30 16:48:26 -08:00
2017-01-31 22:17:16 -08:00
title = TextMobject("Geometric derivatives")
title.scale_to_fit_width(FRAME_WIDTH-1)
2017-01-31 22:17:16 -08:00
title.to_edge(UP)
self.add(title)
2017-01-30 16:48:26 -08:00
2017-01-25 13:00:01 -08:00