3b1b-manim/eoc/chapter2.py

2061 lines
64 KiB
Python
Raw Normal View History

2016-12-26 07:10:38 -08:00
from helpers import *
from mobject.tex_mobject import TexMobject
from mobject import Mobject
from mobject.image_mobject import ImageMobject
from mobject.vectorized_mobject import *
from animation.animation import Animation
from animation.transform import *
from animation.simple_animations import *
from animation.playground import *
from topics.geometry import *
from topics.characters import *
from topics.functions import *
from topics.fractals import *
from topics.number_line import *
from topics.combinatorics import *
from topics.numerals import *
from topics.three_dimensions import *
from topics.objects import *
from scene import Scene
from scene.zoomed_scene import ZoomedScene
from camera import Camera
from mobject.svg_mobject import *
from mobject.tex_mobject import *
from eoc.chapter1 import OpeningQuote
from eoc.graph_scene import *
DISTANCE_COLOR = BLUE
TIME_COLOR = YELLOW
VELOCITY_COLOR = GREEN
2016-12-26 07:10:38 -08:00
class Car(SVGMobject):
CONFIG = {
"file_name" : "Car",
"height" : 1,
2016-12-29 14:31:01 -08:00
"color" : "#BBBBBB",
2016-12-26 07:10:38 -08:00
}
def __init__(self, **kwargs):
SVGMobject.__init__(self, **kwargs)
self.scale_to_fit_height(self.height)
self.set_stroke(color = WHITE, width = 0)
self.set_fill(self.color, opacity = 1)
randy = Randolph(mode = "happy")
randy.scale_to_fit_height(0.6*self.get_height())
randy.stretch(0.8, 0)
randy.look(RIGHT)
randy.move_to(self)
randy.shift(0.07*self.height*(RIGHT+UP))
self.add_to_back(randy)
orientation_line = Line(self.get_left(), self.get_right())
orientation_line.set_stroke(width = 0)
self.add(orientation_line)
self.orientation_line = orientation_line
self.add_treds_to_tires()
def move_to(self, point_or_mobject):
vect = rotate_vector(
UP+LEFT, self.orientation_line.get_angle()
)
self.next_to(point_or_mobject, vect, buff = 0)
return self
def get_front_line(self):
return DashedLine(
self.get_corner(UP+RIGHT),
self.get_corner(DOWN+RIGHT),
color = DISTANCE_COLOR,
2016-12-26 07:10:38 -08:00
dashed_segment_length = 0.05,
)
def add_treds_to_tires(self):
for tire in self.get_tires():
radius = tire.get_width()/2
center = tire.get_center()
tred = Line(
0.9*radius*RIGHT, 1.4*radius*RIGHT,
stroke_width = 2,
color = BLACK
)
tred.rotate_in_place(np.pi/4)
for theta in np.arange(0, 2*np.pi, np.pi/4):
new_tred = tred.copy()
new_tred.rotate(theta)
new_tred.shift(center)
tire.add(new_tred)
return self
def get_tires(self):
return VGroup(self[1][1], self[1][3])
2016-12-26 07:10:38 -08:00
class MoveCar(ApplyMethod):
def __init__(self, car, target_point, **kwargs):
ApplyMethod.__init__(self, car.move_to, target_point, **kwargs)
displacement = self.ending_mobject.get_right()-self.starting_mobject.get_right()
distance = np.linalg.norm(displacement)
tire_radius = car.get_tires()[0].get_width()/2
self.total_tire_radians = -distance/tire_radius
def update_mobject(self, alpha):
ApplyMethod.update_mobject(self, alpha)
if alpha == 0:
return
radians = alpha*self.total_tire_radians
for tire in self.mobject.get_tires():
tire.rotate_in_place(radians)
class IncrementNumber(Succession):
CONFIG = {
"start_num" : 0,
"changes_per_second" : 1,
"run_time" : 11,
}
def __init__(self, num_mob, **kwargs):
digest_config(self, kwargs)
n_iterations = int(self.run_time * self.changes_per_second)
new_num_mobs = [
TexMobject(str(num)).move_to(num_mob, LEFT)
for num in range(self.start_num, self.start_num+n_iterations)
]
transforms = [
Transform(
num_mob, new_num_mob,
run_time = 1.0/self.changes_per_second,
rate_func = squish_rate_func(smooth, 0, 0.5)
)
for new_num_mob in new_num_mobs
]
Succession.__init__(
self, *transforms, **{
"rate_func" : None,
"run_time" : self.run_time,
}
)
class IncrementTest(Scene):
def construct(self):
num = TexMobject("0")
num.shift(UP)
self.play(IncrementNumber(num))
self.dither()
############################
class Chapter2OpeningQuote(OpeningQuote):
CONFIG = {
"quote" : [
"So far as the theories of mathematics are about",
"reality,",
"they are not",
"certain;",
"so far as they are",
"certain,",
"they are not about",
"reality.",
],
"highlighted_quote_terms" : {
"reality," : BLUE,
"certain;" : GREEN,
"certain," : GREEN,
"reality." : BLUE,
},
"author" : "Albert Einstein"
}
class Introduction(TeacherStudentsScene):
def construct(self):
self.student_says(
"What is a derivative?"
)
self.play(self.get_teacher().change_mode, "happy")
self.dither()
self.teacher_says(
"It's actually a \\\\",
"very subtle idea",
target_mode = "well"
)
self.change_student_modes(None, "pondering", "thinking")
self.dither()
self.change_student_modes("erm")
self.student_says(
"Doesn't the derivative measure\\\\",
"instantaneous rate of change", "?",
student_index = 0,
)
self.dither()
bubble = self.get_students()[0].bubble
phrase = bubble.content[1]
bubble.content.remove(phrase)
self.play(
phrase.center,
phrase.scale, 1.5,
phrase.to_edge, UP,
FadeOut(bubble),
FadeOut(bubble.content),
*it.chain(*[
[
pi.change_mode, mode,
pi.look_at, SPACE_HEIGHT*UP
]
for pi, mode in zip(self.get_everyone(), [
"speaking", "pondering", "confused", "confused",
])
])
)
self.dither()
change = VGroup(*phrase[-len("change"):])
instantaneous = VGroup(*phrase[:len("instantaneous")])
change_brace = Brace(change)
change_description = change_brace.get_text(
"Requires multiple \\\\ points in time"
)
instantaneous_brace = Brace(instantaneous)
instantaneous_description = instantaneous_brace.get_text(
"One point \\\\ in time"
)
clock = Clock()
clock.next_to(change_description, DOWN)
def get_clock_anim(run_time = 3):
return ClockPassesTime(
clock,
hours_passed = 0.4*run_time,
run_time = run_time,
)
self.play(FadeIn(clock))
self.play(
change.gradient_highlight, BLUE, YELLOW,
GrowFromCenter(change_brace),
Write(change_description),
get_clock_anim()
)
self.play(get_clock_anim(1))
stopped_clock = clock.copy()
stopped_clock.next_to(instantaneous_description, DOWN)
self.play(
instantaneous.highlight, BLUE,
GrowFromCenter(instantaneous_brace),
Transform(change_description.copy(), instantaneous_description),
clock.copy().next_to, instantaneous_description, DOWN,
get_clock_anim(3)
)
self.play(get_clock_anim(6))
class FathersOfCalculus(Scene):
CONFIG = {
"names" : [
"Barrow",
"Newton",
"Leibniz",
"Cauchy",
"Weierstrass",
],
"picture_height" : 2.5,
}
def construct(self):
title = TextMobject("(A few) Fathers of Calculus")
title.to_edge(UP)
self.add(title)
men = Mobject()
for name in self.names:
image = ImageMobject(name, invert = False)
image.scale_to_fit_height(self.picture_height)
title = TextMobject(name)
title.scale(0.8)
title.next_to(image, DOWN)
image.add(title)
men.add(image)
men.arrange_submobjects(RIGHT, aligned_edge = UP)
men.shift(DOWN)
discover_brace = Brace(Mobject(*men[:3]), UP)
discover = discover_brace.get_text("Discovered it")
VGroup(discover_brace, discover).highlight(BLUE)
rigor_brace = Brace(Mobject(*men[3:]), UP)
rigor = rigor_brace.get_text("Made it rigorous")
rigor.shift(0.1*DOWN)
VGroup(rigor_brace, rigor).highlight(YELLOW)
for man in men:
self.play(FadeIn(man))
self.play(
GrowFromCenter(discover_brace),
Write(discover, run_time = 1)
)
self.play(
GrowFromCenter(rigor_brace),
Write(rigor, run_time = 1)
)
self.dither()
class IntroduceCar(Scene):
2017-01-05 13:14:52 -08:00
CONFIG = {
"should_transition_to_graph" : True,
"show_distance" : True,
}
2016-12-26 07:10:38 -08:00
def construct(self):
point_A = DOWN+4*LEFT
point_B = DOWN+5*RIGHT
A = Dot(point_A)
B = Dot(point_B)
line = Line(point_A, point_B)
VGroup(A, B, line).highlight(WHITE)
for dot, tex in (A, "A"), (B, "B"):
label = TexMobject(tex).next_to(dot, DOWN)
dot.add(label)
car = Car()
2017-01-05 13:14:52 -08:00
self.car = car #For introduce_added_mobjects use in subclasses
2016-12-26 07:10:38 -08:00
car.move_to(point_A)
front_line = car.get_front_line()
time_label = TextMobject("Time (in seconds):", "0")
time_label.shift(2*UP)
distance_brace = Brace(line, UP)
# distance_brace.set_fill(opacity = 0.5)
distance = distance_brace.get_text("100m")
self.add(A, B, line, car, time_label)
self.play(ShowCreation(front_line))
self.play(FadeOut(front_line))
2017-01-05 13:14:52 -08:00
self.introduce_added_mobjects()
2016-12-26 07:10:38 -08:00
self.play(
MoveCar(car, point_B, run_time = 10),
2017-01-05 13:14:52 -08:00
IncrementNumber(time_label[1], run_time = 11),
*self.get_added_movement_anims()
2016-12-26 07:10:38 -08:00
)
front_line = car.get_front_line()
self.play(ShowCreation(front_line))
self.play(FadeOut(front_line))
2017-01-05 13:14:52 -08:00
if self.show_distance:
self.play(
GrowFromCenter(distance_brace),
Write(distance)
)
self.dither()
if self.should_transition_to_graph:
self.play(
car.move_to, point_A,
FadeOut(time_label),
FadeOut(distance_brace),
FadeOut(distance),
)
graph_scene = GraphCarTrajectory(skip_animations = True)
origin = graph_scene.graph_origin
top = graph_scene.coords_to_point(0, 100)
new_length = np.linalg.norm(top-origin)
new_point_B = point_A + new_length*RIGHT
car_line_group = VGroup(car, A, B, line)
for mob in car_line_group:
mob.generate_target()
car_line_group.target = VGroup(*[
m.target for m in car_line_group
])
B = car_line_group[2]
B.target.shift(new_point_B - point_B)
line.target.put_start_and_end_on(
point_A, new_point_B
)
car_line_group.target.rotate(np.pi/2, about_point = point_A)
car_line_group.target.shift(graph_scene.graph_origin - point_A)
self.play(MoveToTarget(car_line_group, path_arc = np.pi/2))
self.dither()
def introduce_added_mobjects(self):
pass
def get_added_movement_anims(self):
return []
2016-12-26 07:10:38 -08:00
class GraphCarTrajectory(GraphScene):
CONFIG = {
"x_min" : 0,
2016-12-29 14:31:01 -08:00
"x_max" : 10.01,
"x_labeled_nums" : range(1, 11),
2016-12-26 07:10:38 -08:00
"x_axis_label" : "Time (seconds)",
"y_min" : 0,
"y_max" : 110,
"y_tick_frequency" : 10,
"y_labeled_nums" : range(10, 110, 10),
"y_axis_label" : "Distance traveled \\\\ (meters)",
"graph_origin" : 2.5*DOWN + 5*LEFT,
"default_graph_colors" : [DISTANCE_COLOR, VELOCITY_COLOR],
"default_derivative_color" : VELOCITY_COLOR,
2016-12-26 07:10:38 -08:00
}
def construct(self):
self.setup_axes(animate = False)
graph = self.graph_sigmoid_trajectory_function()
2016-12-29 14:31:01 -08:00
origin = self.coords_to_point(0, 0)
self.introduce_graph(graph, origin)
self.comment_on_slope(graph, origin)
self.show_velocity_graph()
self.ask_critically_about_velocity()
def graph_sigmoid_trajectory_function(self, **kwargs):
graph = self.graph_function(
lambda t : 100*smooth(t/10.),
**kwargs
)
return graph
def introduce_graph(self, graph, origin):
2016-12-29 14:31:01 -08:00
h_line, v_line = [
Line(origin, origin, color = color, stroke_width = 2)
for color in TIME_COLOR, DISTANCE_COLOR
2016-12-29 14:31:01 -08:00
]
def h_update(h_line, proportion = 1):
end = graph.point_from_proportion(proportion)
2016-12-29 14:31:01 -08:00
t_axis_point = end[0]*RIGHT + origin[1]*UP
h_line.put_start_and_end_on(t_axis_point, end)
def v_update(v_line, proportion = 1):
end = graph.point_from_proportion(proportion)
2016-12-29 14:31:01 -08:00
d_axis_point = origin[0]*RIGHT + end[1]*UP
v_line.put_start_and_end_on(d_axis_point, end)
2016-12-26 07:10:38 -08:00
car = Car()
car.rotate(np.pi/2)
2016-12-29 14:31:01 -08:00
car.move_to(origin)
2016-12-26 07:10:38 -08:00
self.add(car)
2016-12-29 14:31:01 -08:00
self.play(
ShowCreation(
graph,
rate_func = None,
),
MoveCar(
car, self.coords_to_point(0, 100),
),
UpdateFromFunc(h_line, h_update),
UpdateFromFunc(v_line, v_update),
run_time = 10,
)
self.dither()
self.play(*map(FadeOut, [h_line, v_line, car]))
#Show example vertical distance
h_update(h_line, 0.6)
t_dot = Dot(h_line.get_start(), color = h_line.get_color())
t_dot.save_state()
t_dot.move_to(self.x_axis_label_mob)
t_dot.set_fill(opacity = 0)
dashed_h = DashedLine(*h_line.get_start_and_end())
dashed_h.highlight(h_line.get_color())
brace = Brace(dashed_h, RIGHT)
brace_text = brace.get_text("Distance traveled")
self.play(t_dot.restore)
self.dither()
self.play(ShowCreation(dashed_h))
self.play(
GrowFromCenter(brace),
Write(brace_text)
)
self.dither(2)
self.play(*map(FadeOut, [t_dot, dashed_h, brace, brace_text]))
#Name graph
s_of_t = TexMobject("s(t)")
s_of_t.next_to(
graph.point_from_proportion(1),
DOWN+RIGHT,
buff = SMALL_BUFF
)
s = s_of_t[0]
d = TexMobject("d")
d.move_to(s, DOWN)
d.highlight(DISTANCE_COLOR)
self.play(Write(s_of_t))
self.dither()
s.save_state()
self.play(Transform(s, d))
self.dither()
self.play(s.restore)
def comment_on_slope(self, graph, origin):
delta_t = 1
curr_time = 0
ghost_line = Line(
origin,
self.coords_to_point(delta_t, self.y_max)
)
rect = Rectangle().replace(ghost_line, stretch = True)
rect.set_stroke(width = 0)
rect.set_fill(TIME_COLOR, opacity = 0.3)
2017-01-05 13:14:52 -08:00
change_lines = self.get_change_lines(curr_time, delta_t)
self.play(FadeIn(rect))
self.dither()
self.play(Write(change_lines))
self.dither()
for x in range(1, 10):
curr_time = x
2017-01-05 13:14:52 -08:00
new_change_lines = self.get_change_lines(curr_time, delta_t)
self.play(
rect.move_to, self.coords_to_point(curr_time, 0), DOWN+LEFT,
Transform(change_lines, new_change_lines)
)
if curr_time == 5:
text = change_lines[-1].get_text(
"$\\frac{\\text{meters}}{\\text{second}}$"
)
self.play(Write(text))
self.dither()
self.play(FadeOut(text))
else:
self.dither()
self.play(*map(FadeOut, [rect, change_lines]))
self.rect = rect
2017-01-05 13:14:52 -08:00
def get_change_lines(self, curr_time, delta_t = 1):
p1 = self.input_to_graph_point(curr_time)
p2 = self.input_to_graph_point(curr_time+delta_t)
interim_point = p2[0]*RIGHT + p1[1]*UP
delta_t_line = Line(p1, interim_point, color = TIME_COLOR)
delta_s_line = Line(interim_point, p2, color = DISTANCE_COLOR)
2017-01-05 13:14:52 -08:00
brace = Brace(delta_s_line, RIGHT, buff = SMALL_BUFF)
return VGroup(delta_t_line, delta_s_line, brace)
def show_velocity_graph(self):
velocity_graph = self.get_derivative_graph()
self.play(ShowCreation(velocity_graph))
def get_velocity_label(v_graph):
result = self.label_graph(
v_graph,
label = "v(t)",
direction = UP+RIGHT,
proportion = 0.5,
buff = SMALL_BUFF,
animate = False,
)
self.remove(result)
return result
label = get_velocity_label(velocity_graph)
self.play(Write(label))
self.dither()
self.rect.move_to(self.coords_to_point(0, 0), DOWN+LEFT)
self.play(FadeIn(self.rect))
self.dither()
2017-01-05 13:14:52 -08:00
for time, show_slope in (4.5, True), (9, False):
self.play(
self.rect.move_to, self.coords_to_point(time, 0), DOWN+LEFT
)
2017-01-05 13:14:52 -08:00
if show_slope:
change_lines = self.get_change_lines(time)
self.play(FadeIn(change_lines))
self.dither()
self.play(FadeOut(change_lines))
else:
self.dither()
self.play(FadeOut(self.rect))
#Change distance and velocity graphs
self.graph.save_state()
velocity_graph.save_state()
label.save_state()
def shallow_slope(t):
return 100*smooth(t/10., inflection = 4)
def steep_slope(t):
return 100*smooth(t/10., inflection = 25)
def double_smooth_graph_function(t):
if t < 5:
return 50*smooth(t/5.)
else:
return 50*(1+smooth((t-5)/5.))
graph_funcs = [
shallow_slope,
steep_slope,
double_smooth_graph_function,
]
for graph_func in graph_funcs:
new_graph = self.graph_function(
graph_func,
is_main_graph = False
)
self.remove(new_graph)
new_velocity_graph = self.get_derivative_graph(
graph = new_graph,
)
new_velocity_label = get_velocity_label(new_velocity_graph)
self.play(Transform(self.graph, new_graph))
self.play(
Transform(velocity_graph, new_velocity_graph),
Transform(label, new_velocity_label),
)
self.dither(2)
self.play(self.graph.restore)
self.play(
velocity_graph.restore,
label.restore,
)
self.dither(2)
def ask_critically_about_velocity(self):
morty = Mortimer().flip()
morty.to_corner(DOWN+LEFT)
self.play(PiCreatureSays(morty,
"Think critically about \\\\",
"what velocity means."
))
self.play(Blink(morty))
self.dither()
2017-01-05 13:14:52 -08:00
class ShowSpeedometer(IntroduceCar):
CONFIG = {
"num_ticks" : 8,
"tick_length" : 0.2,
"needle_width" : 0.1,
"needle_height" : 0.8,
"should_transition_to_graph" : False,
"show_distance" : False,
}
def setup(self):
start_angle = -np.pi/6
end_angle = 7*np.pi/6
speedomoeter = Arc(
start_angle = start_angle,
angle = end_angle-start_angle
)
tick_angle_range = np.linspace(end_angle, start_angle, self.num_ticks)
for index, angle in enumerate(tick_angle_range):
vect = rotate_vector(RIGHT, angle)
tick = Line((1-self.tick_length)*vect, vect)
label = TexMobject(str(10*index))
label.scale_to_fit_height(self.tick_length)
label.shift((1+self.tick_length)*vect)
speedomoeter.add(tick, label)
needle = Polygon(
LEFT, UP, RIGHT,
stroke_width = 0,
fill_opacity = 1,
fill_color = YELLOW
)
needle.stretch_to_fit_width(self.needle_width)
needle.stretch_to_fit_height(self.needle_height)
needle.rotate(end_angle-np.pi/2)
speedomoeter.add(needle)
speedomoeter.needle = needle
speedomoeter.center_offset = speedomoeter.get_center()
speedomoeter_title = TextMobject("Speedometer")
speedomoeter_title.to_corner(UP+LEFT)
speedomoeter.next_to(speedomoeter_title, DOWN)
self.speedomoeter = speedomoeter
self.speedomoeter_title = speedomoeter_title
def introduce_added_mobjects(self):
speedomoeter = self.speedomoeter
speedomoeter_title = self.speedomoeter_title
speedomoeter.save_state()
speedomoeter.rotate(-np.pi/2, UP)
speedomoeter.scale_to_fit_height(self.car.get_height()/4)
speedomoeter.move_to(self.car)
speedomoeter.shift((self.car.get_width()/4)*RIGHT)
self.play(speedomoeter.restore, run_time = 2)
self.play(Write(speedomoeter_title, run_time = 1))
def get_added_movement_anims(self):
needle = self.speedomoeter.needle
center = self.speedomoeter.get_center() - self.speedomoeter.center_offset
return [
Rotating(
needle,
about_point = center,
radians = -np.pi/2,
run_time = 10,
rate_func = there_and_back
)
]
2016-12-29 14:31:01 -08:00
2017-01-05 13:14:52 -08:00
# def construct(self):
# self.add(self.speedomoeter)
# self.play(*self.get_added_movement_anims())
2016-12-26 07:10:38 -08:00
class VelocityInAMomentMakesNoSense(Scene):
def construct(self):
randy = Randolph()
randy.next_to(ORIGIN, DOWN+LEFT)
words = TextMobject("Velocity in \\\\ a moment")
words.next_to(randy, UP+RIGHT)
randy.look_at(words)
q_marks = TextMobject("???")
q_marks.next_to(randy, UP)
self.play(
randy.change_mode, "confused",
Write(words)
)
self.play(Blink(randy))
self.play(Write(q_marks))
self.play(Blink(randy))
self.dither()
class SnapshotOfACar(Scene):
def construct(self):
car = Car()
car.scale(1.5)
car.move_to(3*LEFT+DOWN)
flash_box = Rectangle(
width = 2*SPACE_WIDTH,
height = 2*SPACE_HEIGHT,
stroke_width = 0,
fill_color = WHITE,
fill_opacity = 1,
)
speed_lines = VGroup(*[
Line(point, point+0.5*LEFT)
for point in [
0.5*UP+0.25*RIGHT,
ORIGIN,
0.5*DOWN+0.25*RIGHT
]
])
question = TextMobject("""
How fast is
this car going?
""")
self.play(MoveCar(
car, RIGHT+DOWN,
run_time = 2,
rate_func = rush_into
))
car.get_tires().highlight(GREY)
speed_lines.next_to(car, LEFT)
self.add(speed_lines)
self.play(
flash_box.set_fill, None, 0,
rate_func = rush_from
)
question.next_to(car, UP, buff = LARGE_BUFF)
self.play(Write(question, run_time = 2))
self.dither(2)
class CompareTwoTimes(Scene):
CONFIG = {
"start_distance" : 30,
"start_time" : 4,
"end_distance" : 50,
"end_time" : 5,
"fade_at_the_end" : True,
}
def construct(self):
self.introduce_states()
self.show_equation()
if self.fade_at_the_end:
self.fade_all_but_one_moment()
2016-12-26 07:10:38 -08:00
def introduce_states(self):
state1 = self.get_car_state(self.start_distance, self.start_time)
state2 = self.get_car_state(self.end_distance, self.end_time)
2016-12-26 07:10:38 -08:00
state1.to_corner(UP+LEFT)
state2.to_corner(DOWN+LEFT)
2016-12-26 07:10:38 -08:00
dividers = VGroup(
Line(SPACE_WIDTH*LEFT, RIGHT),
Line(RIGHT+SPACE_HEIGHT*UP, RIGHT+SPACE_HEIGHT*DOWN),
)
dividers.highlight(GREY)
self.add(dividers, state1)
self.dither()
copied_state = state1.copy()
self.play(copied_state.move_to, state2)
self.play(Transform(copied_state, state2))
self.dither(2)
self.keeper = state1
def show_equation(self):
velocity = TextMobject("Velocity")
change_over_change = TexMobject(
"\\frac{\\text{Change in distance}}{\\text{Change in time}}"
)
formula = TexMobject(
"\\frac{(%s - %s) \\text{ meters}}{(%s - %s) \\text{ seconds}}"%(
str(self.end_distance), str(self.start_distance),
str(self.end_time), str(self.start_time),
)
)
ed_len = len(str(self.end_distance))
sd_len = len(str(self.start_distance))
et_len = len(str(self.end_time))
st_len = len(str(self.start_time))
seconds_len = len("seconds")
VGroup(
VGroup(*formula[1:1+ed_len]),
VGroup(*formula[2+ed_len:2+ed_len+sd_len])
).highlight(DISTANCE_COLOR)
VGroup(
VGroup(*formula[-2-seconds_len-et_len-st_len:-2-seconds_len-st_len]),
VGroup(*formula[-1-seconds_len-st_len:-1-seconds_len]),
).highlight(TIME_COLOR)
down_arrow1 = TexMobject("\\Downarrow")
down_arrow2 = TexMobject("\\Downarrow")
group = VGroup(
velocity, down_arrow1,
change_over_change, down_arrow2,
formula,
)
group.arrange_submobjects(DOWN)
group.to_corner(UP+RIGHT)
2016-12-26 07:10:38 -08:00
self.play(FadeIn(
group, submobject_mode = "lagged_start",
run_time = 3
))
self.dither(3)
self.formula = formula
2016-12-26 07:10:38 -08:00
def fade_all_but_one_moment(self):
anims = [
ApplyMethod(mob.fade, 0.5)
for mob in self.get_mobjects()
]
anims.append(Animation(self.keeper.copy()))
self.play(*anims)
self.dither()
def get_car_state(self, distance, time):
line = Line(3*LEFT, 3*RIGHT)
dots = map(Dot, line.get_start_and_end())
line.add(*dots)
car = Car()
car.move_to(line.get_start())
car.shift((distance/10)*RIGHT)
front_line = car.get_front_line()
brace = Brace(VGroup(dots[0], front_line), DOWN)
distance_label = brace.get_text(
str(distance), " meters"
)
distance_label.highlight_by_tex(str(distance), DISTANCE_COLOR)
brace.add(distance_label)
time_label = TextMobject(
"Time:", str(time), "seconds"
)
time_label.highlight_by_tex(str(time), TIME_COLOR)
time_label.next_to(
VGroup(line, car), UP,
aligned_edge = LEFT
)
2016-12-26 07:10:38 -08:00
return VGroup(line, car, front_line, brace, time_label)
2016-12-26 07:10:38 -08:00
class VelocityAtIndividualPointsVsPairs(GraphCarTrajectory):
CONFIG = {
"start_time" : 6.5,
"end_time" : 3,
"dt" : 1.0,
}
def construct(self):
self.setup_axes(animate = False)
distance_graph = self.graph_function(lambda t : 100*smooth(t/10.))
distance_label = self.label_graph(
distance_graph,
label = "s(t)",
proportion = 1,
direction = RIGHT,
buff = SMALL_BUFF
)
velocity_graph = self.get_derivative_graph()
self.play(ShowCreation(velocity_graph))
velocity_label = self.label_graph(
velocity_graph,
label = "v(t)",
proportion = self.start_time/10.0,
direction = UP,
buff = MED_BUFF
)
velocity_graph.add(velocity_label)
self.show_individual_times_to_velocity(velocity_graph)
self.play(velocity_graph.fade, 0.4)
self.show_two_times_on_distance()
self.show_confused_pi_creature()
def show_individual_times_to_velocity(self, velocity_graph):
start_time = self.start_time
end_time = self.end_time
line = self.get_vertical_line_to_graph(start_time, velocity_graph)
def line_update(line, alpha):
time = interpolate(start_time, end_time, alpha)
line.put_start_and_end_on(
self.coords_to_point(time, 0),
self.input_to_graph_point(time, graph = velocity_graph)
)
self.play(ShowCreation(line))
self.dither()
self.play(UpdateFromAlphaFunc(
line, line_update,
run_time = 4,
rate_func = there_and_back
))
self.dither()
velocity_graph.add(line)
def show_two_times_on_distance(self):
line1 = self.get_vertical_line_to_graph(self.start_time-self.dt/2.0)
line2 = self.get_vertical_line_to_graph(self.start_time+self.dt/2.0)
p1 = line1.get_end()
p2 = line2.get_end()
interim_point = p2[0]*RIGHT+p1[1]*UP
dt_line = Line(p1, interim_point, color = TIME_COLOR)
ds_line = Line(interim_point, p2, color = DISTANCE_COLOR)
dt_brace = Brace(dt_line, DOWN, buff = SMALL_BUFF)
ds_brace = Brace(ds_line, RIGHT, buff = SMALL_BUFF)
dt_text = dt_brace.get_text("Change in time", buff = SMALL_BUFF)
ds_text = ds_brace.get_text("Change in distance", buff = SMALL_BUFF)
self.play(ShowCreation(VGroup(line1, line2)))
for line, brace, text in (dt_line, dt_brace, dt_text), (ds_line, ds_brace, ds_text):
brace.highlight(line.get_color())
text.highlight(line.get_color())
text.add_background_rectangle()
self.play(
ShowCreation(line),
GrowFromCenter(brace),
Write(text)
)
self.dither()
def show_confused_pi_creature(self):
randy = Randolph()
randy.to_corner(DOWN+LEFT)
randy.shift(2*RIGHT)
self.play(randy.change_mode, "confused")
self.play(Blink(randy))
self.dither(2)
self.play(Blink(randy))
self.play(randy.change_mode, "erm")
self.dither()
self.play(Blink(randy))
self.dither(2)
class CompareTwoVerySimilarTimes(CompareTwoTimes):
CONFIG = {
"start_distance" : 20,
"start_time" : 3,
"end_distance" : 20.21,
"end_time" : 3.01,
"fade_at_the_end" : False,
}
def construct(self):
CompareTwoTimes.construct(self)
formula = self.formula
ds_symbols, dt_symbols = [
VGroup(*[
mob
for mob in formula
if mob.get_color() == Color(color)
])
for color in DISTANCE_COLOR, TIME_COLOR
]
ds_brace = Brace(ds_symbols, UP)
ds_text = ds_brace.get_text("$ds$", buff = SMALL_BUFF)
ds_text.highlight(DISTANCE_COLOR)
dt_brace = Brace(dt_symbols, DOWN)
dt_text = dt_brace.get_text("$dt$", buff = SMALL_BUFF)
dt_text.highlight(TIME_COLOR)
self.play(
GrowFromCenter(dt_brace),
Write(dt_text)
)
formula.add(dt_brace, dt_text)
self.dither(2)
formula.generate_target()
VGroup(
ds_brace, ds_text, formula.target
).move_to(formula, UP).shift(0.5*UP)
self.play(
MoveToTarget(formula),
GrowFromCenter(ds_brace),
Write(ds_text)
)
self.dither(2)
class DsOverDtGraphically(GraphCarTrajectory, ZoomedScene):
CONFIG = {
"dt" : 0.1,
"zoom_factor" : 4,#Before being shrunk by dt
"start_time" : 3,
"end_time" : 7,
}
def construct(self):
self.setup_axes(animate = False)
distance_graph = self.graph_function(
lambda t : 100*smooth(t/10.),
animate = False,
)
distance_label = self.label_graph(
distance_graph,
label = "s(t)",
proportion = 0.9,
direction = UP+LEFT,
buff = SMALL_BUFF
)
input_point_line = self.get_vertical_line_to_graph(
self.start_time,
line_kwargs = {
"dashed_segment_length" : 0.02,
"stroke_width" : 4,
"color" : WHITE,
},
)
def get_ds_dt_group(time):
point1 = self.input_to_graph_point(time)
point2 = self.input_to_graph_point(time+self.dt)
interim_point = point2[0]*RIGHT+point1[1]*UP
dt_line = Line(point1, interim_point, color = TIME_COLOR)
ds_line = Line(interim_point, point2, color = DISTANCE_COLOR)
result = VGroup()
for line, char, vect in (dt_line, "t", DOWN), (ds_line, "s", RIGHT):
line.scale(1./self.dt)
brace = Brace(line, vect)
text = brace.get_text("$d%s$"%char)
text.next_to(brace, vect)
text.highlight(line.get_color())
subgroup = VGroup(line, brace, text)
subgroup.scale(self.dt)
result.add(subgroup)
return result
def align_little_rectangle_on_ds_dt_group(rect):
rect.move_to(ds_dt_group, DOWN+RIGHT)
rect.shift(self.dt*(DOWN+RIGHT)/4)
return rect
ds_dt_group = get_ds_dt_group(self.start_time)
#Initially zoom in
self.play(ShowCreation(input_point_line))
self.activate_zooming()
self.play(*map(FadeIn, [self.big_rectangle, self.little_rectangle]))
self.play(
ApplyFunction(
align_little_rectangle_on_ds_dt_group,
self.little_rectangle
)
)
self.little_rectangle.generate_target()
self.little_rectangle.target.scale(self.zoom_factor*self.dt)
align_little_rectangle_on_ds_dt_group(
self.little_rectangle.target
)
self.play(
MoveToTarget(self.little_rectangle),
run_time = 3
)
for subgroup in ds_dt_group:
line, brace, text= subgroup
self.play(ShowCreation(line))
self.play(
GrowFromCenter(brace),
Write(text)
)
self.dither()
#Show as function
frac = TexMobject("\\frac{ds}{dt}")
VGroup(*frac[:2]).highlight(DISTANCE_COLOR)
VGroup(*frac[-2:]).highlight(TIME_COLOR)
frac.next_to(self.input_to_graph_point(5.25), DOWN+RIGHT)
rise_over_run = TexMobject(
"=\\frac{\\text{rise}}{\\text{run}}"
)
rise_over_run.next_to(frac, RIGHT)
of_t = TexMobject("(t)")
of_t.next_to(frac, RIGHT, buff = SMALL_BUFF)
dt_choice = TexMobject("dt = 0.01")
dt_choice.highlight(TIME_COLOR)
dt_choice.next_to(of_t, UP, aligned_edge = LEFT, buff = LARGE_BUFF)
full_formula = TexMobject(
"=\\frac{s(t+dt) - s(t)}{dt}"
)
full_formula.next_to(of_t)
s_t_plus_dt = VGroup(*full_formula[1:8])
s_t = VGroup(*full_formula[9:13])
numerator = VGroup(*full_formula[1:13])
lower_dt = VGroup(*full_formula[-2:])
upper_dt = VGroup(*full_formula[5:7])
equals = full_formula[0]
frac_line = full_formula[-3]
s_t_plus_dt.highlight(DISTANCE_COLOR)
s_t.highlight(DISTANCE_COLOR)
lower_dt.highlight(TIME_COLOR)
upper_dt.highlight(TIME_COLOR)
velocity_graph = self.get_derivative_graph()
t_tick_marks = VGroup(*[
Line(
UP, DOWN,
color = TIME_COLOR,
stroke_width = 3,
).scale(0.1).move_to(self.coords_to_point(t, 0))
for t in np.linspace(0, 10, 75)
])
v_line_at_t, v_line_at_t_plus_dt = [
self.get_vertical_line_to_graph(
time,
line_class = Line,
line_kwargs = {"color" : MAROON_B}
)
for time in self.end_time, self.end_time + self.dt
]
self.play(Write(frac))
self.play(Write(rise_over_run))
self.dither()
def input_point_line_update(line, alpha):
time = interpolate(self.start_time, self.end_time, alpha)
line.put_start_and_end_on(
self.coords_to_point(time, 0),
self.input_to_graph_point(time),
)
def ds_dt_group_update(group, alpha):
time = interpolate(self.start_time, self.end_time, alpha)
new_group = get_ds_dt_group(time)
Transform(group, new_group).update(1)
self.play(
UpdateFromAlphaFunc(input_point_line, input_point_line_update),
UpdateFromAlphaFunc(ds_dt_group, ds_dt_group_update),
UpdateFromFunc(self.little_rectangle, align_little_rectangle_on_ds_dt_group),
run_time = 6,
)
self.play(FadeOut(input_point_line))
self.dither()
self.play(FadeOut(rise_over_run))
self.play(Write(of_t))
self.dither(2)
self.play(ShowCreation(velocity_graph))
velocity_label = self.label_graph(
velocity_graph,
label = "v(t)",
proportion = 0.6,
direction = DOWN+LEFT,
buff = SMALL_BUFF
)
self.dither(2)
self.play(Write(dt_choice))
self.dither()
for anim_class in FadeIn, FadeOut:
self.play(anim_class(
t_tick_marks, submobject_mode = "lagged_start",
run_time = 2
))
self.play(
Write(equals),
Write(numerator)
)
self.dither()
self.play(ShowCreation(v_line_at_t))
self.dither()
self.play(ShowCreation(v_line_at_t_plus_dt))
self.dither()
self.play(*map(FadeOut, [v_line_at_t, v_line_at_t_plus_dt]))
self.play(
Write(frac_line),
Write(lower_dt)
)
self.dither(2)
#Show different curves
self.disactivate_zooming()
self.remove(ds_dt_group)
self.graph.save_state()
velocity_graph.save_state()
velocity_label.save_state()
def steep_slope(t):
return 100*smooth(t/10., inflection = 25)
def sin_wiggle(t):
return (10/(2*np.pi/10.))*(np.sin(2*np.pi*t/10.) + 2*np.pi*t/10.)
def double_smooth_graph_function(t):
if t < 5:
return 50*smooth(t/5.)
else:
return 50*(1+smooth((t-5)/5.))
graph_funcs = [
steep_slope,
sin_wiggle,
double_smooth_graph_function,
]
for graph_func in graph_funcs:
new_graph = self.graph_function(
graph_func,
color = DISTANCE_COLOR,
is_main_graph = False
)
self.remove(new_graph)
new_velocity_graph = self.get_derivative_graph(
graph = new_graph,
)
self.play(Transform(self.graph, new_graph))
self.play(Transform(velocity_graph, new_velocity_graph))
self.dither(2)
self.play(self.graph.restore)
self.play(
velocity_graph.restore,
velocity_label.restore,
)
#Pause and reflect
randy = Randolph()
randy.to_corner(DOWN+LEFT).shift(2*RIGHT)
randy.look_at(frac_line)
self.play(FadeIn(randy))
self.play(randy.change_mode, "pondering")
self.dither()
self.play(Blink(randy))
self.play(randy.change_mode, "thinking")
self.dither()
self.play(Blink(randy))
self.dither()
class DefineTrueDerivative(Scene):
def construct(self):
title = TextMobject("The true derivative")
title.to_edge(UP)
lhs = TexMobject("\\frac{ds}{dt}(t) = ")
VGroup(*lhs[:2]).highlight(DISTANCE_COLOR)
VGroup(*lhs[3:5]).highlight(TIME_COLOR)
lhs.shift(3*LEFT+UP)
dt_rhs = self.get_fraction("dt")
numerical_rhs_list = [
self.get_fraction("0.%s1"%("0"*x))
for x in range(7)
]
for rhs in [dt_rhs] + numerical_rhs_list:
rhs.next_to(lhs, RIGHT)
brace, dt_to_zero = self.get_brace_and_text(dt_rhs)
self.add(lhs, dt_rhs)
self.play(Write(title))
self.dither()
dt_rhs.save_state()
for num_rhs in numerical_rhs_list:
self.play(Transform(dt_rhs, num_rhs))
self.dither()
self.play(dt_rhs.restore)
self.play(
GrowFromCenter(brace),
Write(dt_to_zero)
)
self.dither()
def get_fraction(self, dt_string):
tex_mob = TexMobject(
"\\frac{s(t + %s) - s(t)}{%s}"%(dt_string, dt_string)
)
part_lengths = [
0,
len("s(t+"),
1,#1 and -1 below are purely for transformation quirks
len(dt_string)-1,
len(")-s(t)_"),#Underscore represents frac_line
1,
len(dt_string)-1,
]
pl_cumsum = np.cumsum(part_lengths)
result = VGroup(*[
VGroup(*tex_mob[i1:i2])
for i1, i2 in zip(pl_cumsum, pl_cumsum[1:])
])
VGroup(*result[1:3]+result[4:6]).highlight(TIME_COLOR)
return result
def get_brace_and_text(self, deriv_frac):
brace = Brace(VGroup(deriv_frac), DOWN)
dt_to_zero = brace.get_text("$dt \\to 0$")
VGroup(*dt_to_zero[:2]).highlight(TIME_COLOR)
return brace, dt_to_zero
class SecantLineToTangentLine(GraphCarTrajectory, DefineTrueDerivative):
CONFIG = {
"start_time" : 6,
"end_time" : 2,
"alt_end_time" : 10,
"start_dt" : 2,
"end_dt" : 0.01,
"secant_line_length" : 10,
}
def construct(self):
self.setup_axes(animate = False)
self.remove(self.y_axis_label_mob, self.x_axis_label_mob)
self.add_derivative_definition(self.y_axis_label_mob)
self.add_graph()
self.show_tangent_line()
self.best_constant_approximation_around_a_point()
def get_ds_dt_group(self, dt, animate = False):
points = [
self.input_to_graph_point(time)
for time in self.curr_time, self.curr_time+dt
]
dots = map(Dot, points)
for dot in dots:
dot.scale_in_place(0.5)
secant_line = Line(*points)
secant_line.highlight(VELOCITY_COLOR)
secant_line.scale_in_place(
self.secant_line_length/secant_line.get_length()
)
interim_point = points[1][0]*RIGHT + points[0][1]*UP
dt_line = Line(points[0], interim_point, color = TIME_COLOR)
ds_line = Line(interim_point, points[1], color = DISTANCE_COLOR)
dt = TexMobject("dt")
dt.highlight(TIME_COLOR)
if dt.get_width() > dt_line.get_width():
dt.scale(
dt_line.get_width()/dt.get_width(),
about_point = dt.get_top()
)
dt.next_to(dt_line, DOWN, buff = SMALL_BUFF)
ds = TexMobject("ds")
ds.highlight(DISTANCE_COLOR)
if ds.get_height() > ds_line.get_height():
ds.scale(
ds_line.get_height()/ds.get_height(),
about_point = ds.get_left()
)
ds.next_to(ds_line, RIGHT, buff = SMALL_BUFF)
group = VGroup(
secant_line,
ds_line, dt_line,
ds, dt,
*dots
)
if animate:
self.play(
ShowCreation(dt_line),
Write(dt),
ShowCreation(dots[0]),
)
self.play(
ShowCreation(ds_line),
Write(ds),
ShowCreation(dots[1]),
)
self.play(
ShowCreation(secant_line),
Animation(VGroup(*dots))
)
return group
def add_graph(self):
def double_smooth_graph_function(t):
if t < 5:
return 50*smooth(t/5.)
else:
return 50*(1+smooth((t-5)/5.))
graph = self.graph_function(
double_smooth_graph_function,
animate = False
)
self.label_graph(
graph, "s(t)",
proportion = 1,
direction = DOWN+RIGHT,
buff = SMALL_BUFF,
animate = False
)
def add_derivative_definition(self, target_upper_left):
deriv_frac = self.get_fraction("dt")
lhs = TexMobject("\\frac{ds}{dt}(t)=")
VGroup(*lhs[:2]).highlight(DISTANCE_COLOR)
VGroup(*lhs[3:5]).highlight(TIME_COLOR)
lhs.next_to(deriv_frac, LEFT)
brace, text = self.get_brace_and_text(deriv_frac)
deriv_def = VGroup(lhs, deriv_frac, brace, text)
deriv_word = TextMobject("Derivative")
deriv_word.next_to(deriv_def, UP, buff = 2*MED_BUFF)
deriv_def.add(deriv_word)
rect = Rectangle(color = WHITE)
rect.replace(deriv_def, stretch = True)
rect.scale_in_place(1.2)
deriv_def.add(rect)
deriv_def.scale(0.7)
deriv_def.move_to(target_upper_left, UP+LEFT)
self.add(deriv_def)
return deriv_def
def show_tangent_line(self):
self.curr_time = self.start_time
ds_dt_group = self.get_ds_dt_group(2, animate = True)
self.dither()
def update_ds_dt_group(ds_dt_group, alpha):
new_dt = interpolate(self.start_dt, self.end_dt, alpha)
new_group = self.get_ds_dt_group(new_dt)
Transform(ds_dt_group, new_group).update(1)
self.play(
UpdateFromAlphaFunc(ds_dt_group, update_ds_dt_group),
run_time = 8
)
self.dither()
def update_as_tangent_line(ds_dt_group, alpha):
self.curr_time = interpolate(self.start_time, self.end_time, alpha)
new_group = self.get_ds_dt_group(self.end_dt)
Transform(ds_dt_group, new_group).update(1)
self.play(
UpdateFromAlphaFunc(ds_dt_group, update_as_tangent_line),
run_time = 8,
rate_func = there_and_back
)
self.dither()
what_dt_is_not_text = self.what_this_is_not_saying()
self.dither()
self.play(
UpdateFromAlphaFunc(ds_dt_group, update_ds_dt_group),
run_time = 8,
rate_func = lambda t : 1-there_and_back(t)
)
self.dither()
self.play(FadeOut(what_dt_is_not_text))
v_line = self.get_vertical_line_to_graph(
self.curr_time,
line_class = Line,
line_kwargs = {
"color" : MAROON_B,
"stroke_width" : 3
}
)
def v_line_update(v_line):
v_line.put_start_and_end_on(
self.coords_to_point(self.curr_time, 0),
self.input_to_graph_point(self.curr_time),
)
return v_line
self.play(ShowCreation(v_line))
self.dither()
original_end_time = self.end_time
for end_time in self.alt_end_time, original_end_time, self.start_time:
self.end_time = end_time
self.play(
UpdateFromAlphaFunc(ds_dt_group, update_as_tangent_line),
UpdateFromFunc(v_line, v_line_update),
run_time = abs(self.curr_time-self.end_time),
)
self.start_time = end_time
self.play(FadeOut(v_line))
def what_this_is_not_saying(self):
phrases = [
TextMobject(
"$dt$", "is", "not", s
)
for s in "``infinitely small''", "0"
]
for phrase in phrases:
phrase[0].highlight(TIME_COLOR)
phrase[2].highlight(RED)
phrases[0].shift(DOWN+2*RIGHT)
phrases[1].next_to(phrases[0], DOWN, aligned_edge = LEFT)
for phrase in phrases:
self.play(Write(phrase))
return VGroup(*phrases)
def best_constant_approximation_around_a_point(self):
words = TextMobject("""
Best constant
approximation
around a point
""")
words.next_to(self.x_axis, UP, aligned_edge = RIGHT)
circle = Circle(
radius = 0.25,
color = WHITE
).shift(self.input_to_graph_point(self.curr_time))
self.play(Write(words))
self.play(ShowCreation(circle))
self.dither()
class LeadIntoASpecificExample(TeacherStudentsScene, SecantLineToTangentLine):
def setup(self):
TeacherStudentsScene.setup(self)
def construct(self):
dot = Dot() #Just to coordinate derivative definition
dot.to_corner(UP+LEFT, buff = SMALL_BUFF)
deriv_def = self.add_derivative_definition(dot)
self.remove(deriv_def)
self.teacher_says("An example \\\\ should help.")
self.dither()
self.play(
Write(deriv_def),
*it.chain(*[
[pi.change_mode, "thinking", pi.look_at, dot]
for pi in self.get_students()
])
)
self.random_blink(3)
# self.teacher_says(
# """
# The idea of
# ``approaching''
# actually makes
# things easier
# """,
# height = 3,
# target_mode = "hooray"
# )
# self.dither(2)
2017-01-09 17:15:12 -08:00
class TCubedExample(SecantLineToTangentLine):
CONFIG = {
2017-01-09 17:15:12 -08:00
"y_axis_label" : "Distance",
"y_min" : 0,
2017-01-09 17:15:12 -08:00
"y_max" : 16,
"y_tick_frequency" : 1,
2017-01-09 17:15:12 -08:00
"y_labeled_nums" : range(0, 17, 2),
"x_min" : 0,
"x_max" : 4,
"x_labeled_nums" : range(1, 5),
"graph_origin" : 2.5*DOWN + 6*LEFT,
2017-01-09 17:15:12 -08:00
"start_time" : 2,
"end_time" : 0.5,
2017-01-09 17:15:12 -08:00
"start_dt" : 0.25,
"end_dt" : 0.001,
"secant_line_length" : 0.01,
}
def construct(self):
self.draw_graph()
self.show_vertical_lines()
2017-01-09 17:15:12 -08:00
self.bear_with_me()
self.add_ds_dt_group()
self.brace_for_details()
self.show_expansion()
self.react_to_simplicity()
def draw_graph(self):
self.setup_axes(animate = False)
2017-01-09 17:15:12 -08:00
self.x_axis_label_mob.shift(0.5*DOWN)
# self.y_axis_label_mob.next_to(self.y_axis, UP)
graph = self.graph_function(lambda t : t**3, animate = True)
self.label_graph(
graph,
label = "s(t) = t^3",
2017-01-09 17:15:12 -08:00
proportion = 0.62,
direction = LEFT,
buff = SMALL_BUFF
)
self.dither()
def show_vertical_lines(self):
for t in 1, 2:
v_line = self.get_vertical_line_to_graph(
t, line_kwargs = {"color" : WHITE}
)
brace = Brace(v_line, RIGHT)
text = TexMobject("%d^3 = %d"%(t, t**3))
text.next_to(brace, RIGHT)
text.shift(0.2*UP)
group = VGroup(v_line, brace, text)
if t == 1:
self.play(ShowCreation(v_line))
self.play(
GrowFromCenter(brace),
Write(text)
)
last_group = group
else:
self.play(Transform(last_group, group))
self.dither()
2017-01-09 17:15:12 -08:00
self.play(FadeOut(last_group))
def bear_with_me(self):
morty = Mortimer()
morty.to_corner(DOWN+RIGHT)
self.play(FadeIn(morty))
self.play(PiCreatureSays(
morty, "Bear with \\\\ me here",
target_mode = "sassy"
))
self.play(Blink(morty))
self.dither()
self.play(*map(
FadeOut,
[morty, morty.bubble, morty.bubble.content]
))
def add_ds_dt_group(self):
self.curr_time = self.start_time
self.curr_dt = self.start_dt
ds_dt_group = self.get_ds_dt_group(dt = self.start_dt)
v_lines = self.get_vertical_lines()
lhs = TexMobject("\\frac{ds}{dt}(2) = ")
lhs.next_to(ds_dt_group, UP+RIGHT, buff = 2*MED_BUFF)
ds = VGroup(*lhs[:2])
dt = VGroup(*lhs[3:5])
ds.highlight(DISTANCE_COLOR)
dt.highlight(TIME_COLOR)
ds.target, dt.target = ds_dt_group[3:5]
for mob in ds, dt:
mob.save_state()
mob.move_to(mob.target)
rhs = TexMobject(
"\\frac{s(2+dt) - s(2)}{dt}"
)
rhs.next_to(lhs[-1])
VGroup(*rhs[4:6]).highlight(TIME_COLOR)
VGroup(*rhs[-2:]).highlight(TIME_COLOR)
numerator = VGroup(*rhs[:-3])
non_numerator = VGroup(*rhs[-3:])
numerator_non_minus = VGroup(*numerator)
numerator_non_minus.remove(rhs[7])
s_pair = rhs[0], rhs[8]
lp_pair = rhs[6], rhs[11]
for s, lp in zip(s_pair, lp_pair):
s.target = TexMobject("3").scale(0.7)
s.target.move_to(lp.get_corner(UP+RIGHT), LEFT)
self.play(Write(ds_dt_group, run_time = 2))
self.play(
FadeIn(lhs),
*[mob.restore for mob in ds, dt]
)
self.play(ShowCreation(v_lines[0]))
self.dither()
self.play(
dt.scale_in_place, 1.2,
2017-01-09 17:15:12 -08:00
rate_func = there_and_back
)
self.dither(2)
self.play(Write(numerator))
self.play(ShowCreation(v_lines[1]))
self.dither()
self.play(
v_lines[0].highlight, YELLOW,
rate_func = there_and_back
)
self.dither()
2017-01-09 17:15:12 -08:00
self.play(Write(non_numerator))
self.dither(2)
self.play(
*map(MoveToTarget, s_pair),
**{
"path_arc" : -np.pi/2
}
)
self.play(numerator_non_minus.shift, 0.2*LEFT)
self.dither()
self.vertical_lines = v_lines
self.ds_dt_group = ds_dt_group
self.lhs = lhs
self.rhs = rhs
def get_vertical_lines(self):
return VGroup(*[
self.get_vertical_line_to_graph(
time,
line_class = DashedLine,
line_kwargs = {
"color" : WHITE,
"dashed_segment_length" : 0.05,
}
)
for time in self.start_time, self.start_time+self.start_dt
])
def brace_for_details(self):
brace_yourself = TextMobject(
"(Brace yourself for details)"
)
brace_yourself.next_to(
self.lhs, DOWN,
buff = LARGE_BUFF,
aligned_edge = LEFT
)
self.play(FadeIn(brace_yourself))
self.dither()
self.play(FadeOut(brace_yourself))
def show_expansion(self):
expression = TexMobject("""
\\frac{
2^3 +
3 (2)^2 dt
+ 3 (2)(dt)^2 +
2017-01-09 17:15:12 -08:00
(dt)^3
- 2^3
}{dt}
""")
expression.scale_to_fit_width(
VGroup(self.lhs, self.rhs).get_width()
)
expression.next_to(
self.lhs, DOWN,
aligned_edge = LEFT,
buff = LARGE_BUFF
)
term_lens = [
len("23+"),
len("3(2)2dt"),
len("+3(2)(dt)2+"),
2017-01-09 17:15:12 -08:00
len("(dt)3"),
len("-23"),
len("_"),#frac bar
len("dt"),
]
terms = [
VGroup(*expression[i1:i2])
for i1, i2 in zip(
[0]+list(np.cumsum(term_lens)),
np.cumsum(term_lens)
)
]
dts = [
VGroup(*terms[1][-2:]),
VGroup(*terms[2][6:8]),
2017-01-09 17:15:12 -08:00
VGroup(*terms[3][1:3]),
terms[-1]
]
VGroup(*dts).highlight(TIME_COLOR)
two_cubed_terms = terms[0], terms[4]
for term in terms:
self.play(FadeIn(term))
self.dither()
#Cancel out two_cubed terms
self.play(*it.chain(*[
[
tc.scale, 1.3, tc.get_corner(vect),
tc.highlight, RED
]
for tc, vect in zip(
two_cubed_terms,
[DOWN+RIGHT, DOWN+LEFT]
)
]))
self.play(*map(FadeOut, two_cubed_terms))
numerator = VGroup(*terms[1:4])
self.play(
numerator.scale, 1.4, numerator.get_bottom(),
terms[-1].scale, 1.4, terms[-1].get_top()
2017-01-09 17:15:12 -08:00
)
self.dither(2)
2017-01-09 17:15:12 -08:00
#Cancel out dt
#This is all way too hacky...
faders = VGroup(
terms[-1],
VGroup(*terms[1][-2:]), #"3(2)^2 dt"
terms[2][-2], # "+3(2)(dt)2+"
terms[3][-1], # "(dt)3"
)
new_exp = TexMobject("2").replace(faders[-1], dim_to_match = 1)
self.play(
faders.highlight, BLACK,
run_time = 3,
submobject_mode = "lagged_start"
)
self.play(FadeIn(new_exp))
terms[3].add(new_exp)
shift_val = 0.4*DOWN
self.play(
FadeOut(terms[-2]),#frac_line
terms[1].shift, shift_val + 0.45*RIGHT,
terms[2].shift, shift_val,
terms[3].shift, shift_val,
)
#Isolate dominant term
arrow = Arrow(
self.lhs[4].get_bottom(), terms[1][2].get_top(),
color = WHITE,
buff = MED_BUFF
)
brace = Brace(VGroup(terms[2][0], terms[3][-1]), DOWN)
brace_text = brace.get_text("Contains $dt$")
VGroup(*brace_text[-2:]).highlight(TIME_COLOR)
self.play(ShowCreation(arrow))
self.dither()
self.play(
GrowFromCenter(brace),
Write(brace_text)
)
self.dither(2)
#Shink dt
faders = VGroup(*terms[2:4] + [brace, brace_text])
def ds_dt_group_update(group, alpha):
new_dt = interpolate(self.start_dt, self.end_dt, alpha)
new_group = self.get_ds_dt_group(new_dt)
Transform(group, new_group).update(1)
self.play(FadeOut(self.vertical_lines))
self.play(
UpdateFromAlphaFunc(self.ds_dt_group, ds_dt_group_update),
faders.fade, 0.7,
run_time = 5
)
self.dither(2)
#Show as derivative
deriv_term = VGroup(*terms[1][:5])
deriv_term.generate_target()
lhs_copy = self.lhs.copy()
lhs_copy.generate_target()
lhs_copy.target.shift(3*DOWN)
#hack a little, hack a lot
deriv_term.target.scale(1.1)
deriv_term.target.next_to(lhs_copy.target)
deriv_term.target.shift(0.07*DOWN)
self.play(
FadeOut(arrow),
FadeOut(faders),
MoveToTarget(deriv_term),
MoveToTarget(lhs_copy),
)
arrow = Arrow(
self.rhs.get_bottom(), deriv_term.target.get_top(),
buff = MED_BUFF,
color = WHITE
)
approach_text = TextMobject("As $dt \\to 0$")
approach_text.next_to(arrow.get_center(), RIGHT)
VGroup(*approach_text[2:4]).highlight(TIME_COLOR)
self.play(
ShowCreation(arrow),
Write(approach_text)
)
self.dither(2)
self.secant_line_length = 10
self.play(Transform(
self.ds_dt_group,
self.get_ds_dt_group(self.end_dt)
))
self.dither()
2017-01-09 17:15:12 -08:00
#Generalize to more t
twos = [
self.lhs[6],
self.rhs[2],
self.rhs[10],
lhs_copy[6],
deriv_term[2]
]
for two in twos:
two.target = TexMobject("t")
two.target.replace(two, dim_to_match = 1)
self.play(*map(MoveToTarget, twos))
def update_as_tangent_line(group, alpha):
self.curr_time = interpolate(self.start_time, self.end_time, alpha)
new_group = self.get_ds_dt_group(self.end_dt)
Transform(group, new_group).update(1)
self.play(
UpdateFromAlphaFunc(self.ds_dt_group, update_as_tangent_line),
run_time = 5,
rate_func = there_and_back
)
self.dither(2)
self.lhs_copy = lhs_copy
self.deriv_term = deriv_term
self.approach_text = approach_text
def react_to_simplicity(self):
morty = Mortimer().flip().to_corner(DOWN+LEFT)
self.play(FadeIn(morty))
self.play(PiCreatureSays(
morty, "That's \\\\ beautiful!",
target_mode = "hooray"
))
self.play(Blink(morty))
self.play(
morty.change_mode, 'happy',
*map(FadeOut, [morty.bubble, morty.bubble.content])
)
numerator = VGroup(*self.rhs[:12])
denominator = VGroup(*self.rhs[-2:])
for mob in numerator, denominator, self.approach_text, self.deriv_term:
mob.generate_target()
mob.target.scale_in_place(1.2)
mob.target.highlight(MAROON_B)
self.play(
MoveToTarget(
mob, rate_func = there_and_back,
run_time = 1.5,
),
morty.look_at, mob
)
self.dither()
self.play(Blink(morty))
self.dither()
class YouWouldntDoThisEveryTime(TeacherStudentsScene):
def construct(self):
self.change_student_modes(
"pleading", "guilty", "hesitant",
run_time = 0
)
self.teacher_says(
"You wouldn't do this \\\\ every time"
)
self.change_student_modes(*["happy"]*3)
self.dither(2)
self.student_thinks(
"$\\frac{d(t^3)}{dt} = 3t^2$",
)
self.dither(3)
series = VideoSeries()
series.scale_to_fit_width(2*SPACE_WIDTH-1)
series.to_edge(UP)
this_video = series[1]
next_video = series[2]
this_video.save_state()
this_video.highlight(YELLOW)
self.play(FadeIn(series, submobject_mode = "lagged_start"))
self.play(
this_video.restore,
next_video.highlight, YELLOW,
next_video.shift, 0.5*DOWN
)
self.dither(2)
class ContrastConcreteDtWithLimit(Scene):
def construct(self):
v_line = Line(UP, DOWN).scale(SPACE_HEIGHT)
self.add(v_line)
l_title = TextMobject("""
If $dt$ has a
specific size.
""")
VGroup(*l_title[2:4]).highlight(TIME_COLOR)
r_title = TexMobject("dt \\to 0")
VGroup(*r_title[:2]).highlight(TIME_COLOR)
for title, vect in (l_title, LEFT), (r_title, RIGHT):
title.to_edge(UP)
title.shift(SPACE_WIDTH*vect/2)
self.add(title)
l_formula = TexMobject("""
\\frac{d(t^3)}{dt} =
\\frac{
t^3+
3t^2 \\, dt +
3t \\, (dt)^2 +
(dt)^3
- t^3
}{dt}
""")
VGroup(*it.chain(
l_formula[6:8],
l_formula[15:17],
l_formula[21:23],
l_formula[27:29],
l_formula[35:37],
)).highlight(TIME_COLOR)
l_formula.scale_to_fit_width(SPACE_WIDTH-2*MED_BUFF)
l_formula.to_edge(LEFT)
l_brace = Brace(l_formula, DOWN)
l_text = l_brace.get_text("Messy")
l_text.highlight(RED)
r_formula = TexMobject(
"\\frac{d(t^3)}{dt} = 3t^2"
)
VGroup(*r_formula[6:8]).highlight(TIME_COLOR)
r_formula.shift(SPACE_WIDTH*RIGHT/2)
r_brace = Brace(r_formula, DOWN)
r_text = r_brace.get_text("Simple")
r_text.highlight(GREEN)
self.add(r_formula, r_brace, r_text, l_formula, l_brace, l_text)
2017-01-09 17:15:12 -08:00
2016-12-26 07:10:38 -08:00