2018-03-30 12:56:29 -07:00
|
|
|
from big_ol_pile_of_manim_imports import *
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-09 11:22:28 -08:00
|
|
|
DISTANCE_COLOR = BLUE
|
|
|
|
TIME_COLOR = YELLOW
|
|
|
|
VELOCITY_COLOR = GREEN
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-24 16:21:35 -08:00
|
|
|
|
|
|
|
#### Warning, scenes here not updated based on most recent GraphScene changes #######
|
|
|
|
|
|
|
|
|
2016-12-26 07:10:38 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
############################
|
|
|
|
|
|
|
|
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):
|
2017-01-12 16:36:35 -08:00
|
|
|
goals = TextMobject(
|
|
|
|
"Goals: ",
|
|
|
|
"1) Learn derivatives",
|
|
|
|
", 2) Avoid paradoxes.",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
goals[1].set_color(MAROON_B)
|
|
|
|
goals[2].set_color(RED)
|
|
|
|
goals[2][0].set_color(WHITE)
|
2017-01-12 16:36:35 -08:00
|
|
|
goals.to_edge(UP)
|
|
|
|
self.add(*goals[:2])
|
|
|
|
|
2016-12-26 07:10:38 -08:00
|
|
|
self.student_says(
|
2017-01-12 16:36:35 -08:00
|
|
|
"What is a derivative?",
|
|
|
|
run_time = 2
|
2016-12-26 07:10:38 -08:00
|
|
|
)
|
|
|
|
self.play(self.get_teacher().change_mode, "happy")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
self.teacher_says(
|
|
|
|
"It's actually a \\\\",
|
|
|
|
"very subtle idea",
|
|
|
|
target_mode = "well"
|
|
|
|
)
|
|
|
|
self.change_student_modes(None, "pondering", "thinking")
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(Write(goals[2], run_time = 2))
|
2016-12-26 07:10:38 -08:00
|
|
|
self.change_student_modes("erm")
|
|
|
|
self.student_says(
|
2017-01-12 16:36:35 -08:00
|
|
|
"Instantaneous rate of change", "?",
|
2016-12-26 07:10:38 -08:00
|
|
|
student_index = 0,
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
bubble = self.get_students()[0].bubble
|
2017-01-12 16:36:35 -08:00
|
|
|
phrase = bubble.content[0]
|
2016-12-26 07:10:38 -08:00
|
|
|
bubble.content.remove(phrase)
|
|
|
|
self.play(
|
2017-01-12 16:36:35 -08:00
|
|
|
FadeOut(bubble),
|
|
|
|
FadeOut(bubble.content),
|
|
|
|
FadeOut(goals),
|
2016-12-26 07:10:38 -08:00
|
|
|
phrase.center,
|
|
|
|
phrase.scale, 1.5,
|
|
|
|
phrase.to_edge, UP,
|
|
|
|
*it.chain(*[
|
|
|
|
[
|
|
|
|
pi.change_mode, mode,
|
2018-03-30 11:25:37 -07:00
|
|
|
pi.look_at, FRAME_Y_RADIUS*UP
|
2016-12-26 07:10:38 -08:00
|
|
|
]
|
2017-02-14 14:00:50 -08:00
|
|
|
for pi, mode in zip(self.get_pi_creatures(), [
|
2016-12-26 07:10:38 -08:00
|
|
|
"speaking", "pondering", "confused", "confused",
|
|
|
|
])
|
|
|
|
])
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
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(
|
2018-03-30 11:59:39 -07:00
|
|
|
change.set_color_by_gradient, BLUE, YELLOW,
|
2016-12-26 07:10:38 -08:00
|
|
|
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(
|
2018-03-30 11:51:31 -07:00
|
|
|
instantaneous.set_color, BLUE,
|
2016-12-26 07:10:38 -08:00
|
|
|
GrowFromCenter(instantaneous_brace),
|
|
|
|
Transform(change_description.copy(), instantaneous_description),
|
|
|
|
clock.copy().next_to, instantaneous_description, DOWN,
|
|
|
|
get_clock_anim(3)
|
|
|
|
)
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(get_clock_anim(12))
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
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")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(discover_brace, discover).set_color(BLUE)
|
2016-12-26 07:10:38 -08:00
|
|
|
rigor_brace = Brace(Mobject(*men[3:]), UP)
|
|
|
|
rigor = rigor_brace.get_text("Made it rigorous")
|
|
|
|
rigor.shift(0.1*DOWN)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(rigor_brace, rigor).set_color(YELLOW)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
class IntroduceCar(Scene):
|
2017-01-05 13:14:52 -08:00
|
|
|
CONFIG = {
|
|
|
|
"should_transition_to_graph" : True,
|
|
|
|
"show_distance" : True,
|
2017-04-12 09:06:04 -07:00
|
|
|
"point_A" : DOWN+4*LEFT,
|
|
|
|
"point_B" : DOWN+5*RIGHT,
|
2017-01-05 13:14:52 -08:00
|
|
|
}
|
2016-12-26 07:10:38 -08:00
|
|
|
def construct(self):
|
2017-04-12 09:06:04 -07:00
|
|
|
point_A, point_B = self.point_A, self.point_B
|
2016-12-26 07:10:38 -08:00
|
|
|
A = Dot(point_A)
|
|
|
|
B = Dot(point_B)
|
|
|
|
line = Line(point_A, point_B)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(A, B, line).set_color(WHITE)
|
2016-12-26 07:10:38 -08:00
|
|
|
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)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 13:14:52 -08:00
|
|
|
|
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 13:14:52 -08:00
|
|
|
|
|
|
|
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,
|
2017-04-13 22:29:34 -07:00
|
|
|
"x_max" : 10,
|
2016-12-29 14:31:01 -08:00
|
|
|
"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,
|
2017-01-09 11:22:28 -08:00
|
|
|
"default_graph_colors" : [DISTANCE_COLOR, VELOCITY_COLOR],
|
|
|
|
"default_derivative_color" : VELOCITY_COLOR,
|
2017-04-12 09:06:04 -07:00
|
|
|
"time_of_journey" : 10,
|
|
|
|
"care_movement_rate_func" : smooth,
|
2016-12-26 07:10:38 -08:00
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.setup_axes(animate = False)
|
2017-01-09 15:06:54 -08:00
|
|
|
graph = self.graph_sigmoid_trajectory_function()
|
2016-12-29 14:31:01 -08:00
|
|
|
origin = self.coords_to_point(0, 0)
|
|
|
|
|
2017-01-05 11:57:13 -08:00
|
|
|
self.introduce_graph(graph, origin)
|
|
|
|
self.comment_on_slope(graph, origin)
|
|
|
|
self.show_velocity_graph()
|
|
|
|
self.ask_critically_about_velocity()
|
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
def graph_sigmoid_trajectory_function(self, **kwargs):
|
2017-04-12 09:06:04 -07:00
|
|
|
graph = self.get_graph(
|
2017-01-09 15:06:54 -08:00
|
|
|
lambda t : 100*smooth(t/10.),
|
|
|
|
**kwargs
|
|
|
|
)
|
2017-04-12 09:06:04 -07:00
|
|
|
self.s_graph = graph
|
2017-01-09 15:06:54 -08:00
|
|
|
return graph
|
|
|
|
|
2017-01-05 11:57:13 -08:00
|
|
|
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)
|
2017-01-09 11:22:28 -08:00
|
|
|
for color in TIME_COLOR, DISTANCE_COLOR
|
2016-12-29 14:31:01 -08:00
|
|
|
]
|
2017-01-05 11:57:13 -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)
|
2017-01-05 11:57:13 -08:00
|
|
|
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)
|
2017-04-12 09:06:04 -07:00
|
|
|
car_target = origin*RIGHT + graph.point_from_proportion(1)*UP
|
|
|
|
|
|
|
|
|
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(
|
2017-04-12 09:06:04 -07:00
|
|
|
car, car_target,
|
|
|
|
rate_func = self.care_movement_rate_func
|
2016-12-29 14:31:01 -08:00
|
|
|
),
|
|
|
|
UpdateFromFunc(h_line, h_update),
|
|
|
|
UpdateFromFunc(v_line, v_update),
|
2017-04-12 09:06:04 -07:00
|
|
|
run_time = self.time_of_journey,
|
2016-12-29 14:31:01 -08:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
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())
|
2018-03-30 11:51:31 -07:00
|
|
|
dashed_h.set_color(h_line.get_color())
|
2017-01-05 11:57:13 -08:00
|
|
|
brace = Brace(dashed_h, RIGHT)
|
|
|
|
brace_text = brace.get_text("Distance traveled")
|
|
|
|
self.play(t_dot.restore)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(ShowCreation(dashed_h))
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(brace_text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-05 11:57:13 -08:00
|
|
|
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)
|
2018-03-30 11:51:31 -07:00
|
|
|
d.set_color(DISTANCE_COLOR)
|
2017-01-05 11:57:13 -08:00
|
|
|
|
|
|
|
self.play(Write(s_of_t))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
s.save_state()
|
|
|
|
self.play(Transform(s, d))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
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)
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(FadeIn(rect))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(Write(change_lines))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
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)
|
2017-01-05 11:57:13 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(FadeOut(text))
|
|
|
|
else:
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
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):
|
2017-04-12 09:06:04 -07:00
|
|
|
p1 = self.input_to_graph_point(
|
|
|
|
curr_time, self.s_graph
|
|
|
|
)
|
|
|
|
p2 = self.input_to_graph_point(
|
|
|
|
curr_time+delta_t, self.s_graph
|
|
|
|
)
|
2017-01-05 13:14:52 -08:00
|
|
|
interim_point = p2[0]*RIGHT + p1[1]*UP
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
|
|
|
|
2017-01-05 11:57:13 -08:00
|
|
|
def show_velocity_graph(self):
|
2017-04-12 09:06:04 -07:00
|
|
|
velocity_graph = self.get_derivative_graph(self.s_graph)
|
2017-01-05 11:57:13 -08:00
|
|
|
|
|
|
|
self.play(ShowCreation(velocity_graph))
|
|
|
|
def get_velocity_label(v_graph):
|
2017-04-12 09:06:04 -07:00
|
|
|
result = self.get_graph_label(
|
2017-01-05 11:57:13 -08:00
|
|
|
v_graph,
|
|
|
|
label = "v(t)",
|
|
|
|
direction = UP+RIGHT,
|
2017-04-12 09:06:04 -07:00
|
|
|
x_val = 5,
|
2017-01-05 11:57:13 -08:00
|
|
|
buff = SMALL_BUFF,
|
|
|
|
)
|
|
|
|
self.remove(result)
|
|
|
|
return result
|
|
|
|
label = get_velocity_label(velocity_graph)
|
|
|
|
self.play(Write(label))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
self.rect.move_to(self.coords_to_point(0, 0), DOWN+LEFT)
|
|
|
|
self.play(FadeIn(self.rect))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 13:14:52 -08:00
|
|
|
for time, show_slope in (4.5, True), (9, False):
|
2017-01-05 11:57:13 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 13:14:52 -08:00
|
|
|
self.play(FadeOut(change_lines))
|
|
|
|
else:
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(FadeOut(self.rect))
|
|
|
|
|
|
|
|
#Change distance and velocity graphs
|
2017-04-12 09:06:04 -07:00
|
|
|
self.s_graph.save_state()
|
2017-01-05 11:57:13 -08:00
|
|
|
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:
|
2017-04-12 09:06:04 -07:00
|
|
|
new_graph = self.get_graph(
|
2017-01-05 11:57:13 -08:00
|
|
|
graph_func,
|
2017-01-12 16:36:35 -08:00
|
|
|
color = DISTANCE_COLOR,
|
2017-01-05 11:57:13 -08:00
|
|
|
)
|
|
|
|
self.remove(new_graph)
|
2017-01-09 11:22:28 -08:00
|
|
|
new_velocity_graph = self.get_derivative_graph(
|
|
|
|
graph = new_graph,
|
|
|
|
)
|
2017-01-05 11:57:13 -08:00
|
|
|
new_velocity_label = get_velocity_label(new_velocity_graph)
|
|
|
|
|
2017-04-12 09:06:04 -07:00
|
|
|
self.play(Transform(self.s_graph, new_graph))
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(
|
|
|
|
Transform(velocity_graph, new_velocity_graph),
|
|
|
|
Transform(label, new_velocity_label),
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-04-12 09:06:04 -07:00
|
|
|
self.play(self.s_graph.restore)
|
2017-01-05 11:57:13 -08:00
|
|
|
self.play(
|
|
|
|
velocity_graph.restore,
|
|
|
|
label.restore,
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-05 11:57:13 -08:00
|
|
|
|
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 11:57:13 -08:00
|
|
|
|
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,
|
2017-04-12 09:06:04 -07:00
|
|
|
"speedometer_title_text" : "Speedometer",
|
2017-01-05 13:14:52 -08:00
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
start_angle = -np.pi/6
|
|
|
|
end_angle = 7*np.pi/6
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer = Arc(
|
2017-01-05 13:14:52 -08:00
|
|
|
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)
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer.add(tick, label)
|
2017-01-05 13:14:52 -08:00
|
|
|
|
|
|
|
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)
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer.add(needle)
|
|
|
|
speedometer.needle = needle
|
2017-01-05 13:14:52 -08:00
|
|
|
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer.center_offset = speedometer.get_center()
|
2017-01-05 13:14:52 -08:00
|
|
|
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer_title = TextMobject(self.speedometer_title_text)
|
|
|
|
speedometer_title.to_corner(UP+LEFT)
|
|
|
|
speedometer.next_to(speedometer_title, DOWN)
|
2017-01-05 13:14:52 -08:00
|
|
|
|
2017-04-12 09:06:04 -07:00
|
|
|
self.speedometer = speedometer
|
|
|
|
self.speedometer_title = speedometer_title
|
2017-01-05 13:14:52 -08:00
|
|
|
|
|
|
|
def introduce_added_mobjects(self):
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer = self.speedometer
|
|
|
|
speedometer_title = self.speedometer_title
|
|
|
|
|
|
|
|
speedometer.save_state()
|
|
|
|
speedometer.rotate(-np.pi/2, UP)
|
|
|
|
speedometer.scale_to_fit_height(self.car.get_height()/4)
|
|
|
|
speedometer.move_to(self.car)
|
|
|
|
speedometer.shift((self.car.get_width()/4)*RIGHT)
|
|
|
|
|
|
|
|
self.play(speedometer.restore, run_time = 2)
|
|
|
|
self.play(Write(speedometer_title, run_time = 1))
|
|
|
|
|
|
|
|
def get_added_movement_anims(self, **kwargs):
|
|
|
|
needle = self.speedometer.needle
|
|
|
|
center = self.speedometer.get_center() - self.speedometer.center_offset
|
|
|
|
default_kwargs = {
|
|
|
|
"about_point" : center,
|
|
|
|
"radians" : -np.pi/2,
|
|
|
|
"run_time" : 10,
|
|
|
|
"rate_func" : there_and_back,
|
|
|
|
}
|
|
|
|
default_kwargs.update(kwargs)
|
|
|
|
return [Rotating(needle, **default_kwargs)]
|
2016-12-29 14:31:01 -08:00
|
|
|
|
2017-01-05 13:14:52 -08:00
|
|
|
# def construct(self):
|
2017-04-12 09:06:04 -07:00
|
|
|
# self.add(self.speedometer)
|
2017-01-05 13:14:52 -08:00
|
|
|
# self.play(*self.get_added_movement_anims())
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-05 14:50:07 -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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 14:50:07 -08:00
|
|
|
|
|
|
|
class SnapshotOfACar(Scene):
|
|
|
|
def construct(self):
|
|
|
|
car = Car()
|
|
|
|
car.scale(1.5)
|
|
|
|
car.move_to(3*LEFT+DOWN)
|
|
|
|
flash_box = Rectangle(
|
2018-03-30 11:25:37 -07:00
|
|
|
width = FRAME_WIDTH,
|
|
|
|
height = FRAME_HEIGHT,
|
2017-01-05 14:50:07 -08:00
|
|
|
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
|
|
|
|
))
|
2018-03-30 11:51:31 -07:00
|
|
|
car.get_tires().set_color(GREY)
|
2017-01-05 14:50:07 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-05 14:50:07 -08:00
|
|
|
|
|
|
|
class CompareTwoTimes(Scene):
|
|
|
|
CONFIG = {
|
|
|
|
"start_distance" : 30,
|
|
|
|
"start_time" : 4,
|
|
|
|
"end_distance" : 50,
|
|
|
|
"end_time" : 5,
|
2017-01-09 11:22:28 -08:00
|
|
|
"fade_at_the_end" : True,
|
2017-01-05 14:50:07 -08:00
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.introduce_states()
|
|
|
|
self.show_equation()
|
2017-01-09 11:22:28 -08:00
|
|
|
if self.fade_at_the_end:
|
|
|
|
self.fade_all_but_one_moment()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-05 14:50:07 -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
|
|
|
|
2017-01-05 14:50:07 -08:00
|
|
|
state1.to_corner(UP+LEFT)
|
|
|
|
state2.to_corner(DOWN+LEFT)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-05 14:50:07 -08:00
|
|
|
dividers = VGroup(
|
2018-03-30 11:25:37 -07:00
|
|
|
Line(FRAME_X_RADIUS*LEFT, RIGHT),
|
|
|
|
Line(RIGHT+FRAME_Y_RADIUS*UP, RIGHT+FRAME_Y_RADIUS*DOWN),
|
2017-01-05 14:50:07 -08:00
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
dividers.set_color(GREY)
|
2017-01-05 14:50:07 -08:00
|
|
|
|
|
|
|
self.add(dividers, state1)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 14:50:07 -08:00
|
|
|
copied_state = state1.copy()
|
|
|
|
self.play(copied_state.move_to, state2)
|
|
|
|
self.play(Transform(copied_state, state2))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-05 14:50:07 -08:00
|
|
|
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(
|
2017-01-09 11:22:28 -08:00
|
|
|
"\\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),
|
2017-01-05 14:50:07 -08:00
|
|
|
)
|
|
|
|
)
|
2017-01-09 11:22:28 -08:00
|
|
|
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])
|
2018-03-30 11:51:31 -07:00
|
|
|
).set_color(DISTANCE_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
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]),
|
2018-03-30 11:51:31 -07:00
|
|
|
).set_color(TIME_COLOR)
|
2017-01-05 14:50:07 -08:00
|
|
|
|
|
|
|
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
|
|
|
|
2017-01-05 14:50:07 -08:00
|
|
|
self.play(FadeIn(
|
|
|
|
group, submobject_mode = "lagged_start",
|
|
|
|
run_time = 3
|
|
|
|
))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-01-09 11:22:28 -08:00
|
|
|
self.formula = formula
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-05 14:50:07 -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)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-05 14:50:07 -08:00
|
|
|
|
|
|
|
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"
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
distance_label.set_color_by_tex(str(distance), DISTANCE_COLOR)
|
2017-01-05 14:50:07 -08:00
|
|
|
brace.add(distance_label)
|
|
|
|
time_label = TextMobject(
|
|
|
|
"Time:", str(time), "seconds"
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
time_label.set_color_by_tex(str(time), TIME_COLOR)
|
2017-01-05 14:50:07 -08:00
|
|
|
time_label.next_to(
|
|
|
|
VGroup(line, car), UP,
|
|
|
|
aligned_edge = LEFT
|
|
|
|
)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-05 14:50:07 -08:00
|
|
|
return VGroup(line, car, front_line, brace, time_label)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-06 13:01:34 -08:00
|
|
|
class VelocityAtIndividualPointsVsPairs(GraphCarTrajectory):
|
|
|
|
CONFIG = {
|
2017-01-09 11:22:28 -08:00
|
|
|
"start_time" : 6.5,
|
2017-01-06 13:01:34 -08:00
|
|
|
"end_time" : 3,
|
2017-01-09 11:22:28 -08:00
|
|
|
"dt" : 1.0,
|
2017-01-06 13:01:34 -08:00
|
|
|
}
|
|
|
|
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,
|
2017-01-09 11:22:28 -08:00
|
|
|
direction = RIGHT,
|
2017-01-06 13:01:34 -08:00
|
|
|
buff = SMALL_BUFF
|
|
|
|
)
|
|
|
|
velocity_graph = self.get_derivative_graph()
|
|
|
|
self.play(ShowCreation(velocity_graph))
|
|
|
|
velocity_label = self.label_graph(
|
|
|
|
velocity_graph,
|
|
|
|
label = "v(t)",
|
2017-01-09 11:22:28 -08:00
|
|
|
proportion = self.start_time/10.0,
|
|
|
|
direction = UP,
|
2017-01-25 16:40:59 -08:00
|
|
|
buff = MED_SMALL_BUFF
|
2017-01-06 13:01:34 -08:00
|
|
|
)
|
|
|
|
velocity_graph.add(velocity_label)
|
|
|
|
|
|
|
|
self.show_individual_times_to_velocity(velocity_graph)
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(velocity_graph.fade, 0.4)
|
2017-01-06 13:01:34 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-06 13:01:34 -08:00
|
|
|
self.play(UpdateFromAlphaFunc(
|
|
|
|
line, line_update,
|
|
|
|
run_time = 4,
|
|
|
|
rate_func = there_and_back
|
|
|
|
))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-06 13:01:34 -08:00
|
|
|
velocity_graph.add(line)
|
|
|
|
|
|
|
|
def show_two_times_on_distance(self):
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
2017-01-06 13:01:34 -08:00
|
|
|
p1 = line1.get_end()
|
|
|
|
p2 = line2.get_end()
|
|
|
|
interim_point = p2[0]*RIGHT+p1[1]*UP
|
2017-01-09 11:22:28 -08:00
|
|
|
dt_line = Line(p1, interim_point, color = TIME_COLOR)
|
|
|
|
ds_line = Line(interim_point, p2, color = DISTANCE_COLOR)
|
2017-01-06 13:01:34 -08:00
|
|
|
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):
|
2018-03-30 11:51:31 -07:00
|
|
|
brace.set_color(line.get_color())
|
|
|
|
text.set_color(line.get_color())
|
2017-01-06 13:01:34 -08:00
|
|
|
text.add_background_rectangle()
|
|
|
|
self.play(
|
|
|
|
ShowCreation(line),
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-06 13:01:34 -08:00
|
|
|
|
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-06 13:01:34 -08:00
|
|
|
self.play(Blink(randy))
|
|
|
|
self.play(randy.change_mode, "erm")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-06 13:01:34 -08:00
|
|
|
self.play(Blink(randy))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
class FirstRealWorld(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
self.teacher_says("First, the real world.")
|
|
|
|
self.change_student_modes(
|
|
|
|
"happy", "hooray", "happy"
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-01-13 14:10:10 -08:00
|
|
|
|
|
|
|
class SidestepParadox(Scene):
|
|
|
|
def construct(self):
|
|
|
|
car = Car()
|
|
|
|
car.shift(DOWN)
|
|
|
|
show_speedometer = ShowSpeedometer(skip_animations = True)
|
2017-04-12 09:06:04 -07:00
|
|
|
speedometer = show_speedometer.speedometer
|
|
|
|
speedometer.next_to(car, UP)
|
2017-01-13 14:10:10 -08:00
|
|
|
|
|
|
|
title = TextMobject(
|
|
|
|
"Instantaneous", "rate of change"
|
|
|
|
)
|
|
|
|
title.to_edge(UP)
|
|
|
|
cross = TexMobject("\\times")
|
|
|
|
cross.replace(title[0], stretch = True)
|
|
|
|
cross.set_fill(RED, opacity = 0.8)
|
|
|
|
|
|
|
|
new_words = TextMobject("over a small time")
|
|
|
|
new_words.next_to(title[1], DOWN)
|
2018-03-30 11:51:31 -07:00
|
|
|
new_words.set_color(TIME_COLOR)
|
2017-01-13 14:10:10 -08:00
|
|
|
|
|
|
|
self.add(title, car)
|
2017-04-12 09:06:04 -07:00
|
|
|
self.play(Write(speedometer))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(Write(cross))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(Write(new_words))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
2018-03-30 11:51:31 -07:00
|
|
|
ds_text.set_color(DISTANCE_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
dt_brace = Brace(dt_symbols, DOWN)
|
|
|
|
dt_text = dt_brace.get_text("$dt$", buff = SMALL_BUFF)
|
2018-03-30 11:51:31 -07:00
|
|
|
dt_text.set_color(TIME_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(dt_brace),
|
|
|
|
Write(dt_text)
|
|
|
|
)
|
|
|
|
formula.add(dt_brace, dt_text)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
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)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
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)
|
2018-03-30 11:51:31 -07:00
|
|
|
text.set_color(line.get_color())
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
#Show as function
|
|
|
|
frac = TexMobject("\\frac{ds}{dt}")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*frac[:2]).set_color(DISTANCE_COLOR)
|
|
|
|
VGroup(*frac[-2:]).set_color(TIME_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
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")
|
2018-03-30 11:51:31 -07:00
|
|
|
dt_choice.set_color(TIME_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
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]
|
2018-03-30 11:51:31 -07:00
|
|
|
s_t_plus_dt.set_color(DISTANCE_COLOR)
|
|
|
|
s_t.set_color(DISTANCE_COLOR)
|
|
|
|
lower_dt.set_color(TIME_COLOR)
|
|
|
|
upper_dt.set_color(TIME_COLOR)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(FadeOut(rise_over_run))
|
|
|
|
self.play(Write(of_t))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(ShowCreation(velocity_graph))
|
|
|
|
velocity_label = self.label_graph(
|
|
|
|
velocity_graph,
|
|
|
|
label = "v(t)",
|
|
|
|
proportion = 0.6,
|
|
|
|
direction = DOWN+LEFT,
|
|
|
|
buff = SMALL_BUFF
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(Write(dt_choice))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
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)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
self.play(ShowCreation(v_line_at_t))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(ShowCreation(v_line_at_t_plus_dt))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(*map(FadeOut, [v_line_at_t, v_line_at_t_plus_dt]))
|
|
|
|
self.play(
|
|
|
|
Write(frac_line),
|
|
|
|
Write(lower_dt)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
|
|
|
#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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 11:22:28 -08:00
|
|
|
self.play(self.graph.restore)
|
|
|
|
self.play(
|
|
|
|
velocity_graph.restore,
|
|
|
|
velocity_label.restore,
|
|
|
|
)
|
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
#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")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.play(Blink(randy))
|
|
|
|
self.play(randy.change_mode, "thinking")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.play(Blink(randy))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
|
|
|
class DefineTrueDerivative(Scene):
|
|
|
|
def construct(self):
|
|
|
|
title = TextMobject("The true derivative")
|
|
|
|
title.to_edge(UP)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
lhs = TexMobject("\\frac{ds}{dt}(t) = ")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*lhs[:2]).set_color(DISTANCE_COLOR)
|
|
|
|
VGroup(*lhs[3:5]).set_color(TIME_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
lhs.shift(3*LEFT+UP)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
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)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
brace, dt_to_zero = self.get_brace_and_text(dt_rhs)
|
2017-01-09 11:22:28 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
self.add(lhs, dt_rhs)
|
|
|
|
self.play(Write(title))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
dt_rhs.save_state()
|
|
|
|
for num_rhs in numerical_rhs_list:
|
|
|
|
self.play(Transform(dt_rhs, num_rhs))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.play(dt_rhs.restore)
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(dt_to_zero)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
|
|
|
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:])
|
|
|
|
])
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*result[1:3]+result[4:6]).set_color(TIME_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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$")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*dt_to_zero[:2]).set_color(TIME_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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,
|
2017-01-09 11:22:28 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
}
|
|
|
|
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()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.draw_axes()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.show_tangent_line()
|
|
|
|
self.best_constant_approximation_around_a_point()
|
|
|
|
|
|
|
|
def get_ds_dt_group(self, dt, animate = False):
|
|
|
|
points = [
|
2017-04-12 09:06:04 -07:00
|
|
|
self.input_to_graph_point(time, self.graph)
|
2017-01-09 15:06:54 -08:00
|
|
|
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)
|
2018-03-30 11:51:31 -07:00
|
|
|
secant_line.set_color(VELOCITY_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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")
|
2018-03-30 11:51:31 -07:00
|
|
|
dt.set_color(TIME_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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")
|
2018-03-30 11:51:31 -07:00
|
|
|
ds.set_color(DISTANCE_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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.))
|
2017-04-12 09:06:04 -07:00
|
|
|
self.graph = self.get_graph(double_smooth_graph_function)
|
|
|
|
self.graph_label = self.get_graph_label(
|
|
|
|
self.graph, "s(t)",
|
|
|
|
x_val = self.x_max,
|
2017-01-09 15:06:54 -08:00
|
|
|
direction = DOWN+RIGHT,
|
|
|
|
buff = SMALL_BUFF,
|
|
|
|
)
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
def add_derivative_definition(self, target_upper_left):
|
|
|
|
deriv_frac = self.get_fraction("dt")
|
|
|
|
lhs = TexMobject("\\frac{ds}{dt}(t)=")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*lhs[:2]).set_color(DISTANCE_COLOR)
|
|
|
|
VGroup(*lhs[3:5]).set_color(TIME_COLOR)
|
2017-01-09 15:06:54 -08:00
|
|
|
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")
|
2017-01-25 16:40:59 -08:00
|
|
|
deriv_word.next_to(deriv_def, UP, buff = MED_LARGE_BUFF)
|
2017-01-09 15:06:54 -08:00
|
|
|
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
|
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
def draw_axes(self):
|
|
|
|
self.x_axis.remove(self.x_axis_label_mob)
|
|
|
|
self.y_axis.remove(self.y_axis_label_mob)
|
|
|
|
self.play(Write(
|
|
|
|
VGroup(
|
|
|
|
self.x_axis, self.y_axis,
|
|
|
|
self.graph, self.graph_label
|
|
|
|
),
|
|
|
|
run_time = 4
|
|
|
|
))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
def show_tangent_line(self):
|
|
|
|
self.curr_time = self.start_time
|
|
|
|
|
|
|
|
ds_dt_group = self.get_ds_dt_group(2, animate = True)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
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),
|
2017-01-13 14:10:10 -08:00
|
|
|
run_time = 15
|
2017-01-09 15:06:54 -08:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
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
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
what_dt_is_not_text = self.what_this_is_not_saying()
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(ds_dt_group, update_ds_dt_group),
|
|
|
|
run_time = 8,
|
|
|
|
rate_func = lambda t : 1-there_and_back(t)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
self.play(FadeOut(what_dt_is_not_text))
|
|
|
|
|
|
|
|
v_line = self.get_vertical_line_to_graph(
|
|
|
|
self.curr_time,
|
2017-04-12 09:06:04 -07:00
|
|
|
self.graph,
|
2017-01-09 15:06:54 -08:00
|
|
|
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),
|
2017-04-12 09:06:04 -07:00
|
|
|
self.input_to_graph_point(self.curr_time, self.graph),
|
2017-01-09 15:06:54 -08:00
|
|
|
)
|
|
|
|
return v_line
|
|
|
|
self.play(ShowCreation(v_line))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
|
|
|
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:
|
2018-03-30 11:51:31 -07:00
|
|
|
phrase[0].set_color(TIME_COLOR)
|
|
|
|
phrase[2].set_color(RED)
|
2017-01-09 15:06:54 -08:00
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
class UseOfDImpliesApproaching(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
statement = TextMobject("""
|
|
|
|
Using ``$d$''
|
|
|
|
announces that
|
|
|
|
$dt \\to 0$
|
|
|
|
""")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*statement[-4:-2]).set_color(TIME_COLOR)
|
2017-01-12 16:36:35 -08:00
|
|
|
self.teacher_says(statement)
|
|
|
|
self.change_student_modes(*["pondering"]*3)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(4)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
2017-01-09 15:06:54 -08:00
|
|
|
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.")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
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"
|
|
|
|
# )
|
2018-01-15 19:15:05 -08:00
|
|
|
# self.wait(2)
|
2017-01-09 15:06:54 -08:00
|
|
|
|
2017-01-09 17:15:12 -08:00
|
|
|
class TCubedExample(SecantLineToTangentLine):
|
2017-01-09 15:06:54 -08:00
|
|
|
CONFIG = {
|
2017-01-09 17:15:12 -08:00
|
|
|
"y_axis_label" : "Distance",
|
2017-01-09 15:06:54 -08:00
|
|
|
"y_min" : 0,
|
2017-01-09 17:15:12 -08:00
|
|
|
"y_max" : 16,
|
2017-01-09 15:06:54 -08:00
|
|
|
"y_tick_frequency" : 1,
|
2017-01-09 17:15:12 -08:00
|
|
|
"y_labeled_nums" : range(0, 17, 2),
|
2017-01-09 15:06:54 -08:00
|
|
|
"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,
|
2017-01-11 12:03:33 -08:00
|
|
|
"end_time" : 0.5,
|
2017-01-09 17:15:12 -08:00
|
|
|
"start_dt" : 0.25,
|
2017-01-11 12:03:33 -08:00
|
|
|
"end_dt" : 0.001,
|
|
|
|
"secant_line_length" : 0.01,
|
2017-01-09 15:06:54 -08:00
|
|
|
}
|
|
|
|
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()
|
2017-01-11 12:03:33 -08:00
|
|
|
self.react_to_simplicity()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
|
|
|
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)
|
2017-01-09 15:06:54 -08:00
|
|
|
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,
|
2017-01-09 15:06:54 -08:00
|
|
|
buff = SMALL_BUFF
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 15:06:54 -08:00
|
|
|
|
|
|
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
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))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
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) = ")
|
2017-01-25 16:40:59 -08:00
|
|
|
lhs.next_to(ds_dt_group, UP+RIGHT, buff = MED_LARGE_BUFF)
|
2017-01-09 17:15:12 -08:00
|
|
|
ds = VGroup(*lhs[:2])
|
|
|
|
dt = VGroup(*lhs[3:5])
|
2018-03-30 11:51:31 -07:00
|
|
|
ds.set_color(DISTANCE_COLOR)
|
|
|
|
dt.set_color(TIME_COLOR)
|
2017-01-09 17:15:12 -08:00
|
|
|
ds.target, dt.target = ds_dt_group[3:5]
|
|
|
|
for mob in ds, dt:
|
|
|
|
mob.save_state()
|
|
|
|
mob.move_to(mob.target)
|
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
nonzero_size = TextMobject("Nonzero size...for now")
|
2018-03-30 11:51:31 -07:00
|
|
|
nonzero_size.set_color(TIME_COLOR)
|
2017-01-13 14:10:10 -08:00
|
|
|
nonzero_size.next_to(dt, DOWN+2*RIGHT, buff = LARGE_BUFF)
|
|
|
|
arrow = Arrow(nonzero_size, dt)
|
|
|
|
|
2017-01-09 17:15:12 -08:00
|
|
|
rhs = TexMobject(
|
|
|
|
"\\frac{s(2+dt) - s(2)}{dt}"
|
|
|
|
)
|
|
|
|
rhs.next_to(lhs[-1])
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*rhs[4:6]).set_color(TIME_COLOR)
|
|
|
|
VGroup(*rhs[-2:]).set_color(TIME_COLOR)
|
2017-01-09 17:15:12 -08:00
|
|
|
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]))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
self.play(
|
2017-01-13 14:10:10 -08:00
|
|
|
ShowCreation(arrow),
|
|
|
|
Write(nonzero_size),
|
2017-01-09 17:15:12 -08:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(*map(FadeOut, [arrow, nonzero_size]))
|
2017-01-09 17:15:12 -08:00
|
|
|
self.play(Write(numerator))
|
|
|
|
self.play(ShowCreation(v_lines[1]))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(
|
2018-03-30 11:51:31 -07:00
|
|
|
v_lines[0].set_color, YELLOW,
|
2017-01-11 12:03:33 -08:00
|
|
|
rate_func = there_and_back
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
self.play(Write(non_numerator))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 17:15:12 -08:00
|
|
|
self.play(
|
|
|
|
*map(MoveToTarget, s_pair),
|
|
|
|
**{
|
|
|
|
"path_arc" : -np.pi/2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
self.play(numerator_non_minus.shift, 0.2*LEFT)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
|
|
|
|
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):
|
2017-01-13 14:10:10 -08:00
|
|
|
morty = Mortimer()
|
|
|
|
morty.next_to(self.rhs, DOWN, buff = LARGE_BUFF)
|
|
|
|
|
|
|
|
self.play(FadeIn(morty))
|
|
|
|
self.play(
|
|
|
|
morty.change_mode, "hooray",
|
|
|
|
morty.look_at, self.rhs
|
2017-01-09 17:15:12 -08:00
|
|
|
)
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(Blink(morty))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(
|
|
|
|
morty.change_mode, "sassy",
|
|
|
|
morty.look, OUT
|
2017-01-09 17:15:12 -08:00
|
|
|
)
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(Blink(morty))
|
|
|
|
self.play(morty.change_mode, "pondering")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(FadeOut(morty))
|
2017-01-09 17:15:12 -08:00
|
|
|
|
|
|
|
def show_expansion(self):
|
|
|
|
expression = TexMobject("""
|
|
|
|
\\frac{
|
|
|
|
2^3 +
|
2017-01-11 12:03:33 -08:00
|
|
|
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+"),
|
2017-01-11 12:03:33 -08:00
|
|
|
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 = [
|
2017-01-11 12:03:33 -08:00
|
|
|
VGroup(*terms[1][-2:]),
|
|
|
|
VGroup(*terms[2][6:8]),
|
2017-01-09 17:15:12 -08:00
|
|
|
VGroup(*terms[3][1:3]),
|
|
|
|
terms[-1]
|
|
|
|
]
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*dts).set_color(TIME_COLOR)
|
2017-01-09 17:15:12 -08:00
|
|
|
|
|
|
|
two_cubed_terms = terms[0], terms[4]
|
|
|
|
|
|
|
|
for term in terms:
|
|
|
|
self.play(FadeIn(term))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
|
|
|
|
#Cancel out two_cubed terms
|
|
|
|
self.play(*it.chain(*[
|
|
|
|
[
|
|
|
|
tc.scale, 1.3, tc.get_corner(vect),
|
2018-03-30 11:51:31 -07:00
|
|
|
tc.set_color, RED
|
2017-01-09 17:15:12 -08:00
|
|
|
]
|
|
|
|
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(
|
2017-01-11 12:03:33 -08:00
|
|
|
numerator.scale, 1.4, numerator.get_bottom(),
|
|
|
|
terms[-1].scale, 1.4, terms[-1].get_top()
|
2017-01-09 17:15:12 -08:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-09 17:15:12 -08:00
|
|
|
|
|
|
|
#Cancel out dt
|
2017-01-11 12:03:33 -08:00
|
|
|
#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(
|
2018-03-30 11:51:31 -07:00
|
|
|
faders.set_color, BLACK,
|
2017-01-12 16:36:35 -08:00
|
|
|
FadeIn(new_exp),
|
|
|
|
run_time = 2,
|
2017-01-11 12:03:33 -08:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-11 12:03:33 -08:00
|
|
|
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,
|
2017-01-25 16:40:59 -08:00
|
|
|
buff = MED_SMALL_BUFF
|
2017-01-11 12:03:33 -08:00
|
|
|
)
|
|
|
|
brace = Brace(VGroup(terms[2][0], terms[3][-1]), DOWN)
|
|
|
|
brace_text = brace.get_text("Contains $dt$")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*brace_text[-2:]).set_color(TIME_COLOR)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
self.play(ShowCreation(arrow))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(brace_text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
#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))
|
2017-01-13 14:10:10 -08:00
|
|
|
self.secant_line_length = 10
|
|
|
|
self.play(Transform(
|
|
|
|
self.ds_dt_group,
|
|
|
|
self.get_ds_dt_group(self.start_dt)
|
|
|
|
))
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(self.ds_dt_group, ds_dt_group_update),
|
|
|
|
faders.fade, 0.7,
|
|
|
|
run_time = 5
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
#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(),
|
2017-01-25 16:40:59 -08:00
|
|
|
buff = MED_SMALL_BUFF,
|
2017-01-11 12:03:33 -08:00
|
|
|
color = WHITE
|
|
|
|
)
|
|
|
|
approach_text = TextMobject("As $dt \\to 0$")
|
|
|
|
approach_text.next_to(arrow.get_center(), RIGHT)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*approach_text[2:4]).set_color(TIME_COLOR)
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(
|
|
|
|
ShowCreation(arrow),
|
|
|
|
Write(approach_text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
|
|
|
self.wait()
|
2017-01-09 17:15:12 -08:00
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
#Ephasize slope
|
|
|
|
v_line = self.vertical_lines[0]
|
|
|
|
slope_text = TextMobject("Slope = $12$")
|
2018-03-30 11:51:31 -07:00
|
|
|
slope_text.set_color(VELOCITY_COLOR)
|
2017-01-13 14:10:10 -08:00
|
|
|
slope_text.next_to(v_line.get_end(), LEFT)
|
|
|
|
self.play(Write(slope_text))
|
|
|
|
self.play(
|
|
|
|
self.ds_dt_group.rotate_in_place, np.pi/24,
|
|
|
|
rate_func = wiggle
|
|
|
|
)
|
|
|
|
self.play(ShowCreation(v_line))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-13 14:10:10 -08:00
|
|
|
self.play(FadeOut(v_line))
|
|
|
|
self.play(FadeOut(slope_text))
|
|
|
|
|
2017-01-11 12:03:33 -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
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
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)
|
2018-03-30 11:51:31 -07:00
|
|
|
mob.target.set_color(MAROON_B)
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(
|
|
|
|
MoveToTarget(
|
|
|
|
mob, rate_func = there_and_back,
|
|
|
|
run_time = 1.5,
|
|
|
|
),
|
|
|
|
morty.look_at, mob
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(Blink(morty))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
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)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-11 12:03:33 -08:00
|
|
|
self.student_thinks(
|
|
|
|
"$\\frac{d(t^3)}{dt} = 3t^2$",
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
series = VideoSeries()
|
2018-03-30 11:25:37 -07:00
|
|
|
series.scale_to_fit_width(FRAME_WIDTH-1)
|
2017-01-11 12:03:33 -08:00
|
|
|
series.to_edge(UP)
|
|
|
|
this_video = series[1]
|
|
|
|
next_video = series[2]
|
|
|
|
this_video.save_state()
|
2018-03-30 11:51:31 -07:00
|
|
|
this_video.set_color(YELLOW)
|
2017-01-11 12:03:33 -08:00
|
|
|
self.play(FadeIn(series, submobject_mode = "lagged_start"))
|
|
|
|
self.play(
|
|
|
|
this_video.restore,
|
2018-03-30 11:51:31 -07:00
|
|
|
next_video.set_color, YELLOW,
|
2017-01-11 12:03:33 -08:00
|
|
|
next_video.shift, 0.5*DOWN
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
class ContrastConcreteDtWithLimit(Scene):
|
|
|
|
def construct(self):
|
2018-03-30 11:25:37 -07:00
|
|
|
v_line = Line(UP, DOWN).scale(FRAME_Y_RADIUS)
|
2017-01-11 12:03:33 -08:00
|
|
|
self.add(v_line)
|
|
|
|
|
|
|
|
l_title = TextMobject("""
|
|
|
|
If $dt$ has a
|
|
|
|
specific size.
|
|
|
|
""")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*l_title[2:4]).set_color(TIME_COLOR)
|
2017-01-11 12:03:33 -08:00
|
|
|
r_title = TexMobject("dt \\to 0")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*r_title[:2]).set_color(TIME_COLOR)
|
2017-01-11 12:03:33 -08:00
|
|
|
for title, vect in (l_title, LEFT), (r_title, RIGHT):
|
|
|
|
title.to_edge(UP)
|
2018-03-30 11:25:37 -07:00
|
|
|
title.shift(FRAME_X_RADIUS*vect/2)
|
2017-01-11 12:03:33 -08:00
|
|
|
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],
|
2018-03-30 11:51:31 -07:00
|
|
|
)).set_color(TIME_COLOR)
|
2018-03-30 11:25:37 -07:00
|
|
|
l_formula.scale_to_fit_width(FRAME_X_RADIUS-MED_LARGE_BUFF)
|
2017-01-11 12:03:33 -08:00
|
|
|
l_formula.to_edge(LEFT)
|
|
|
|
|
|
|
|
l_brace = Brace(l_formula, DOWN)
|
|
|
|
l_text = l_brace.get_text("Messy")
|
2018-03-30 11:51:31 -07:00
|
|
|
l_text.set_color(RED)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
|
|
|
r_formula = TexMobject(
|
|
|
|
"\\frac{d(t^3)}{dt} = 3t^2"
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*r_formula[6:8]).set_color(TIME_COLOR)
|
2018-03-30 11:25:37 -07:00
|
|
|
r_formula.shift(FRAME_X_RADIUS*RIGHT/2)
|
2017-01-11 12:03:33 -08:00
|
|
|
r_brace = Brace(r_formula, DOWN)
|
|
|
|
r_text = r_brace.get_text("Simple")
|
2018-03-30 11:51:31 -07:00
|
|
|
r_text.set_color(GREEN)
|
2017-01-11 12:03:33 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
triplets = [
|
|
|
|
(l_formula, l_brace, l_text),
|
|
|
|
(r_formula, r_brace, r_text),
|
|
|
|
]
|
|
|
|
for formula, brace, text in triplets:
|
|
|
|
self.play(Write(formula, run_time = 1))
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
class TimeForAnActualParadox(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
words = TextMobject("``Instantaneous rate of change''")
|
|
|
|
paradoxes = TextMobject("Paradoxes")
|
|
|
|
arrow = Arrow(ORIGIN, DOWN, buff = 0)
|
|
|
|
group = VGroup(words, arrow, paradoxes)
|
|
|
|
group.arrange_submobjects(DOWN)
|
|
|
|
group.to_edge(UP)
|
|
|
|
|
|
|
|
teacher = self.get_teacher()
|
|
|
|
self.play(
|
|
|
|
teacher.change_mode, "raise_right_hand",
|
|
|
|
teacher.look_at, words,
|
|
|
|
Write(words)
|
|
|
|
)
|
|
|
|
self.play(*map(Write, [arrow, paradoxes]))
|
|
|
|
self.play(*it.chain(*[
|
|
|
|
[pi.change_mode, mode, pi.look_at, words]
|
|
|
|
for pi, mode in zip(
|
|
|
|
self.get_students(),
|
|
|
|
["pondering", "happy", "hesitant"]
|
|
|
|
)
|
|
|
|
]))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(4)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
class ParadoxAtTEquals0(TCubedExample):
|
|
|
|
CONFIG = {
|
|
|
|
"tangent_line_length" : 20,
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.draw_graph()
|
|
|
|
self.ask_question()
|
|
|
|
self.show_derivative_text()
|
|
|
|
self.show_tangent_line()
|
|
|
|
self.if_not_then_when()
|
|
|
|
self.single_out_question()
|
|
|
|
|
|
|
|
def draw_graph(self):
|
|
|
|
self.setup_axes(animate = False)
|
|
|
|
self.x_axis_label_mob.set_fill(opacity = 0)
|
|
|
|
graph = self.graph_function(lambda t : t**3, animate = False)
|
|
|
|
graph_x_max = 3.0
|
|
|
|
graph.pointwise_become_partial(graph, 0, graph_x_max/self.x_max)
|
|
|
|
|
|
|
|
origin = self.coords_to_point(0, 0)
|
|
|
|
h_line = Line(LEFT, RIGHT, color = TIME_COLOR)
|
|
|
|
v_line = Line(UP, DOWN, color = DISTANCE_COLOR)
|
|
|
|
VGroup(h_line, v_line).set_stroke(width = 2)
|
|
|
|
|
|
|
|
def h_line_update(h_line):
|
|
|
|
point = graph.point_from_proportion(1)
|
|
|
|
y_axis_point = origin[0]*RIGHT + point[1]*UP
|
|
|
|
h_line.put_start_and_end_on(y_axis_point, point)
|
|
|
|
return h_line
|
|
|
|
|
|
|
|
def v_line_update(v_line):
|
|
|
|
point = graph.point_from_proportion(1)
|
|
|
|
x_axis_point = point[0]*RIGHT + origin[1]*UP
|
|
|
|
v_line.put_start_and_end_on(x_axis_point, point)
|
|
|
|
return v_line
|
|
|
|
|
|
|
|
car = Car()
|
|
|
|
car.rotate(np.pi/2)
|
|
|
|
car.move_to(origin)
|
|
|
|
self.add(car)
|
|
|
|
#Should be 0, 1, but for some reason I don't know
|
|
|
|
#the car was lagging the graph.
|
|
|
|
car_target_point = self.coords_to_point(0, 1.15)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
MoveCar(
|
|
|
|
car, car_target_point,
|
|
|
|
rate_func = lambda t : (t*graph_x_max)**3
|
|
|
|
),
|
|
|
|
ShowCreation(graph, rate_func = None),
|
|
|
|
UpdateFromFunc(h_line, h_line_update),
|
|
|
|
UpdateFromFunc(v_line, v_line_update),
|
|
|
|
run_time = 5
|
|
|
|
)
|
|
|
|
self.play(*map(FadeOut, [h_line, v_line]))
|
|
|
|
|
|
|
|
self.label_graph(
|
|
|
|
graph,
|
|
|
|
label = "s(t) = t^3",
|
|
|
|
proportion = 0.8,
|
|
|
|
direction = RIGHT,
|
|
|
|
buff = SMALL_BUFF
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
self.car = car
|
|
|
|
|
|
|
|
def ask_question(self):
|
|
|
|
question = TextMobject(
|
|
|
|
"At time $t=0$,",
|
|
|
|
"is \\\\ the car moving?"
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*question[0][-4:-1]).set_color(RED)
|
2017-01-12 16:36:35 -08:00
|
|
|
question.next_to(
|
|
|
|
self.coords_to_point(0, 10),
|
|
|
|
RIGHT
|
|
|
|
)
|
|
|
|
origin = self.coords_to_point(0, 0)
|
|
|
|
arrow = Arrow(question.get_bottom(), origin)
|
|
|
|
|
|
|
|
self.play(Write(question[0], run_time = 1))
|
|
|
|
self.play(MoveCar(self.car, origin))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(Write(question[1]))
|
|
|
|
self.play(ShowCreation(arrow))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
self.question = question
|
|
|
|
|
|
|
|
def show_derivative_text(self):
|
|
|
|
derivative = TexMobject(
|
|
|
|
"\\frac{ds}{dt}(t) = 3t^2",
|
|
|
|
"= 3(0)^2",
|
|
|
|
"= 0",
|
|
|
|
"\\frac{\\text{m}}{\\text{s}}",
|
|
|
|
)
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*derivative[0][:2]).set_color(DISTANCE_COLOR)
|
|
|
|
VGroup(*derivative[0][3:5]).set_color(TIME_COLOR)
|
|
|
|
derivative[1][3].set_color(RED)
|
2017-01-12 16:36:35 -08:00
|
|
|
derivative[-1].scale_in_place(0.7)
|
|
|
|
derivative.to_edge(RIGHT, buff = LARGE_BUFF)
|
|
|
|
derivative.shift(2*UP)
|
|
|
|
|
|
|
|
self.play(Write(derivative[0]))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(FadeIn(derivative[1]))
|
|
|
|
self.play(*map(FadeIn, derivative[2:]))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
self.derivative = derivative
|
|
|
|
|
|
|
|
def show_tangent_line(self):
|
|
|
|
dot = Dot()
|
|
|
|
line = Line(ORIGIN, RIGHT, color = VELOCITY_COLOR)
|
|
|
|
line.scale(self.tangent_line_length)
|
|
|
|
|
|
|
|
start_time = 2
|
|
|
|
end_time = 0
|
|
|
|
|
|
|
|
def get_time_and_point(alpha):
|
|
|
|
time = interpolate(start_time, end_time, alpha)
|
|
|
|
point = self.input_to_graph_point(time)
|
|
|
|
return time, point
|
|
|
|
|
|
|
|
def dot_update(dot, alpha):
|
|
|
|
dot.move_to(get_time_and_point(alpha)[1])
|
2017-01-09 17:15:12 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
def line_update(line, alpha):
|
|
|
|
time, point = get_time_and_point(alpha)
|
|
|
|
line.rotate(
|
|
|
|
self.angle_of_tangent(time)-line.get_angle()
|
|
|
|
)
|
|
|
|
line.move_to(point)
|
|
|
|
|
|
|
|
dot_update(dot, 0)
|
|
|
|
line_update(line, 0)
|
|
|
|
self.play(
|
|
|
|
ShowCreation(line),
|
|
|
|
ShowCreation(dot)
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(line, line_update),
|
|
|
|
UpdateFromAlphaFunc(dot, dot_update),
|
|
|
|
run_time = 4
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
self.tangent_line = line
|
|
|
|
|
|
|
|
def if_not_then_when(self):
|
|
|
|
morty = Mortimer()
|
|
|
|
morty.scale(0.7)
|
|
|
|
morty.to_corner(DOWN+RIGHT)
|
|
|
|
|
|
|
|
self.play(FadeIn(morty))
|
|
|
|
self.play(PiCreatureSays(
|
|
|
|
morty, "If not at $t=0$, when?",
|
|
|
|
target_mode = "maybe"
|
|
|
|
))
|
|
|
|
self.play(Blink(morty))
|
|
|
|
self.play(MoveCar(
|
|
|
|
self.car, self.coords_to_point(0, 1),
|
|
|
|
rate_func = lambda t : (3*t)**3,
|
|
|
|
run_time = 5
|
|
|
|
))
|
|
|
|
self.play(
|
|
|
|
morty.change_mode, "pondering",
|
|
|
|
FadeOut(morty.bubble),
|
|
|
|
FadeOut(morty.bubble.content),
|
|
|
|
)
|
|
|
|
self.play(MoveCar(self.car, self.coords_to_point(0, 0)))
|
|
|
|
self.play(Blink(morty))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
|
|
|
|
self.morty = morty
|
|
|
|
|
|
|
|
def single_out_question(self):
|
|
|
|
morty, question = self.morty, self.question
|
|
|
|
|
|
|
|
#Shouldn't need this
|
|
|
|
morty.bubble.content.set_fill(opacity = 0)
|
|
|
|
morty.bubble.set_fill(opacity = 0)
|
|
|
|
morty.bubble.set_stroke(width = 0)
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
change_word = VGroup(*question[1][-7:-1])
|
|
|
|
moment_word = question[0]
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
brace = Brace(VGroup(*self.derivative[1:]))
|
|
|
|
brace_text = brace.get_text("Best constant \\\\ approximation")
|
|
|
|
|
|
|
|
self.remove(question, morty)
|
|
|
|
pre_everything = Mobject(*self.get_mobjects())
|
|
|
|
everything = Mobject(*pre_everything.family_members_with_points())
|
|
|
|
everything.save_state()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
everything.fade, 0.8,
|
|
|
|
question.center,
|
|
|
|
morty.change_mode, "confused",
|
|
|
|
morty.look_at, ORIGIN
|
|
|
|
)
|
|
|
|
self.play(Blink(morty))
|
|
|
|
for word in change_word, moment_word:
|
|
|
|
self.play(
|
|
|
|
word.scale_in_place, 1.2,
|
2018-03-30 11:51:31 -07:00
|
|
|
word.set_color, YELLOW,
|
2017-01-12 16:36:35 -08:00
|
|
|
rate_func = there_and_back,
|
|
|
|
run_time = 1.5
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(
|
|
|
|
everything.restore,
|
|
|
|
FadeOut(question),
|
|
|
|
morty.change_mode, "raise_right_hand",
|
|
|
|
morty.look_at, self.derivative
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
FadeIn(brace_text)
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(
|
|
|
|
self.tangent_line.rotate_in_place, np.pi/24,
|
|
|
|
rate_func = wiggle,
|
|
|
|
run_time = 1
|
|
|
|
)
|
|
|
|
self.play(Blink(morty))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
class TinyMovement(ZoomedScene):
|
|
|
|
CONFIG = {
|
|
|
|
"distance" : 0.05,
|
|
|
|
"distance_label" : "(0.1)^3 = 0.001",
|
|
|
|
"time_label" : "0.1",
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.activate_zooming()
|
|
|
|
self.show_initial_motion()
|
|
|
|
self.show_ratios()
|
2017-01-06 13:01:34 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
def show_initial_motion(self):
|
|
|
|
car = Car()
|
|
|
|
car.move_to(ORIGIN)
|
|
|
|
car_points = car.get_all_points()
|
|
|
|
lowest_to_highest_indices = np.argsort(car_points[:,1])
|
|
|
|
wheel_point = car_points[lowest_to_highest_indices[2]]
|
|
|
|
target_wheel_point = wheel_point+self.distance*RIGHT
|
|
|
|
|
|
|
|
dots = VGroup(*[
|
|
|
|
Dot(point, radius = self.distance/10)
|
|
|
|
for point in wheel_point, target_wheel_point
|
|
|
|
])
|
|
|
|
brace = Brace(Line(ORIGIN, RIGHT))
|
|
|
|
distance_label = TexMobject(self.distance_label)
|
|
|
|
distance_label.next_to(brace, DOWN)
|
2018-03-30 11:51:31 -07:00
|
|
|
distance_label.set_color(DISTANCE_COLOR)
|
2017-01-12 16:36:35 -08:00
|
|
|
brace.add(distance_label)
|
|
|
|
brace.scale(self.distance)
|
|
|
|
brace.next_to(dots, DOWN, buff = self.distance/5)
|
|
|
|
|
|
|
|
zoom_rect = self.little_rectangle
|
|
|
|
zoom_rect.scale(2)
|
|
|
|
zoom_rect.move_to(wheel_point)
|
|
|
|
|
|
|
|
time_label = TextMobject("Time $t = $")
|
|
|
|
time_label.next_to(car, UP, buff = LARGE_BUFF)
|
|
|
|
start_time = TexMobject("0")
|
|
|
|
end_time = TexMobject(self.time_label)
|
|
|
|
for time in start_time, end_time:
|
2018-03-30 11:51:31 -07:00
|
|
|
time.set_color(TIME_COLOR)
|
2017-01-12 16:36:35 -08:00
|
|
|
time.next_to(time_label, RIGHT)
|
|
|
|
|
|
|
|
self.add(car, time_label, start_time)
|
|
|
|
self.play(
|
|
|
|
zoom_rect.scale_in_place,
|
|
|
|
10*self.distance / zoom_rect.get_width()
|
|
|
|
)
|
|
|
|
self.play(ShowCreation(dots[0]))
|
|
|
|
self.play(Transform(start_time, end_time))
|
|
|
|
self.play(MoveCar(car, self.distance*RIGHT))
|
|
|
|
self.play(ShowCreation(dots[1]))
|
|
|
|
self.play(Write(brace, run_time = 1))
|
|
|
|
self.play(
|
|
|
|
zoom_rect.scale, 0.5,
|
|
|
|
zoom_rect.move_to, brace
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
def show_ratios(self):
|
|
|
|
ratios = [
|
|
|
|
self.get_ratio(n)
|
|
|
|
for n in range(1, 5)
|
|
|
|
]
|
|
|
|
ratio = ratios[0]
|
|
|
|
self.play(FadeIn(ratio))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
for new_ratio in ratios[1:]:
|
|
|
|
self.play(Transform(ratio, new_ratio))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
def get_ratio(self, power = 1):
|
|
|
|
dt = "0.%s1"%("0"*(power-1))
|
|
|
|
ds_dt = "0.%s1"%("0"*(2*power-1))
|
|
|
|
expression = TexMobject("""
|
|
|
|
\\frac{(%s)^3 \\text{ meters}}{%s \\text{ seconds}}
|
|
|
|
= %s \\frac{\\text{meters}}{\\text{second}}
|
|
|
|
"""%(dt, dt, ds_dt))
|
|
|
|
expression.next_to(ORIGIN, DOWN, buff = LARGE_BUFF)
|
|
|
|
lengths = [
|
|
|
|
0,
|
|
|
|
len("("),
|
|
|
|
len(dt),
|
|
|
|
len(")3meters_"),
|
|
|
|
len(dt),
|
|
|
|
len("seconds="),
|
|
|
|
len(ds_dt),
|
|
|
|
len("meters_second")
|
|
|
|
]
|
|
|
|
result = VGroup(*[
|
|
|
|
VGroup(*expression[i1:i2])
|
|
|
|
for i1, i2 in zip(
|
|
|
|
np.cumsum(lengths),
|
|
|
|
np.cumsum(lengths)[1:],
|
|
|
|
)
|
|
|
|
])
|
2018-03-30 11:51:31 -07:00
|
|
|
result[1].set_color(DISTANCE_COLOR)
|
|
|
|
result[3].set_color(TIME_COLOR)
|
|
|
|
result[5].set_color(VELOCITY_COLOR)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
return result
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
class NextVideos(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
series = VideoSeries()
|
2018-03-30 11:25:37 -07:00
|
|
|
series.scale_to_fit_width(FRAME_WIDTH - 1)
|
2017-01-12 16:36:35 -08:00
|
|
|
series.to_edge(UP)
|
2018-03-30 11:51:31 -07:00
|
|
|
series[1].set_color(YELLOW)
|
2017-01-12 16:36:35 -08:00
|
|
|
self.add(series)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
brace = Brace(VGroup(*series[2:6]))
|
|
|
|
brace_text = brace.get_text("More derivative stuffs")
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
self.get_teacher().change_mode, "raise_right_hand"
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Write(brace_text),
|
|
|
|
*it.chain(*[
|
|
|
|
[pi.look_at, brace]
|
|
|
|
for pi in self.get_students()
|
|
|
|
])
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-01-12 16:36:35 -08:00
|
|
|
self.change_student_modes(*["thinking"]*3)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-04-29 18:23:00 -07:00
|
|
|
|
2017-01-12 16:36:35 -08:00
|
|
|
class Chapter2PatreonThanks(PatreonThanks):
|
|
|
|
CONFIG = {
|
|
|
|
"specific_patrons" : [
|
|
|
|
"Meshal Alshammari",
|
|
|
|
"Ali Yahya",
|
|
|
|
"CrypticSwarm ",
|
|
|
|
"Yu Jun",
|
|
|
|
"Shelby Doolittle",
|
|
|
|
"Dave Nicponski",
|
|
|
|
"Damion Kistler",
|
|
|
|
"Juan Benet",
|
|
|
|
"Othman Alikhan",
|
|
|
|
"Markus Persson",
|
|
|
|
"Dan Buchoff",
|
|
|
|
"Derek Dai",
|
|
|
|
"Joseph Cox",
|
|
|
|
"Luc Ritchie",
|
|
|
|
"Mark Govea",
|
|
|
|
"Guido Gambardella",
|
|
|
|
"Vecht",
|
|
|
|
"Jonathan Eppele",
|
|
|
|
"Shimin Kuang",
|
|
|
|
"Rish Kundalia",
|
|
|
|
"Achille Brighton",
|
|
|
|
"Kirk Werklund",
|
|
|
|
"Ripta Pasay",
|
|
|
|
"Felipe Diniz",
|
|
|
|
]
|
|
|
|
}
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-04-26 16:22:21 -07:00
|
|
|
class Promotion(PiCreatureScene):
|
|
|
|
CONFIG = {
|
|
|
|
"camera_class" : ThreeDCamera,
|
|
|
|
"seconds_to_blink" : 5,
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
aops_logo = AoPSLogo()
|
|
|
|
aops_logo.next_to(self.pi_creature, UP+LEFT)
|
|
|
|
url = TextMobject(
|
|
|
|
"AoPS.com/", "3blue1brown",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
|
|
|
url.to_corner(UP+LEFT)
|
|
|
|
url_rect = Rectangle(color = BLUE)
|
|
|
|
url_rect.replace(
|
|
|
|
url.get_part_by_tex("3blue1brown"),
|
|
|
|
stretch = True
|
|
|
|
)
|
|
|
|
|
|
|
|
url_rect.stretch_in_place(1.1, dim = 1)
|
|
|
|
|
|
|
|
rect = Rectangle(height = 9, width = 16)
|
|
|
|
rect.scale_to_fit_height(4.5)
|
|
|
|
rect.next_to(url, DOWN)
|
|
|
|
rect.to_edge(LEFT)
|
|
|
|
mathy = Mathematician()
|
|
|
|
mathy.flip()
|
|
|
|
mathy.to_corner(DOWN+RIGHT)
|
|
|
|
morty = self.pi_creature
|
|
|
|
morty.save_state()
|
|
|
|
book_spot = mathy.get_corner(UP+LEFT) + UP+LEFT
|
|
|
|
mathy.get_center = mathy.get_top
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
self.pi_creature.change_mode, "raise_right_hand",
|
|
|
|
*[
|
|
|
|
DrawBorderThenFill(
|
|
|
|
submob,
|
|
|
|
run_time = 3,
|
|
|
|
rate_func = squish_rate_func(double_smooth, a, a+0.5)
|
|
|
|
)
|
|
|
|
for submob, a in zip(aops_logo, np.linspace(0, 0.5, len(aops_logo)))
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.play(Write(url))
|
|
|
|
self.play(
|
|
|
|
morty.change_mode, "plain",
|
|
|
|
morty.flip,
|
|
|
|
morty.scale, 0.7,
|
|
|
|
morty.next_to, mathy, LEFT, LARGE_BUFF,
|
|
|
|
morty.to_edge, DOWN,
|
|
|
|
FadeIn(mathy),
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
PiCreatureSays(
|
|
|
|
mathy, "",
|
|
|
|
bubble_kwargs = {"width" : 5},
|
|
|
|
look_at_arg = morty.eyes,
|
|
|
|
),
|
|
|
|
aops_logo.shift, 1.5*UP + 0.5*RIGHT
|
|
|
|
)
|
|
|
|
self.change_mode("happy")
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(Blink(mathy))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(
|
|
|
|
RemovePiCreatureBubble(
|
|
|
|
mathy, target_mode = "happy"
|
|
|
|
),
|
|
|
|
aops_logo.to_corner, UP+RIGHT,
|
|
|
|
aops_logo.shift, MED_SMALL_BUFF*DOWN,
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
mathy.look_at, morty.eyes,
|
|
|
|
morty.look_at, mathy.eyes,
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(
|
|
|
|
Animation(VectorizedPoint(book_spot)),
|
|
|
|
mathy.change, "raise_right_hand", book_spot,
|
|
|
|
morty.change, "pondering",
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(Blink(mathy))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(7)
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(
|
|
|
|
ShowCreation(rect),
|
|
|
|
morty.restore,
|
|
|
|
morty.change, "happy", rect,
|
|
|
|
FadeOut(mathy),
|
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(10)
|
2017-04-26 16:22:21 -07:00
|
|
|
self.play(ShowCreation(url_rect))
|
|
|
|
self.play(
|
|
|
|
FadeOut(url_rect),
|
2018-03-30 11:51:31 -07:00
|
|
|
url.get_part_by_tex("3blue1brown").set_color, BLUE,
|
2017-04-26 16:22:21 -07:00
|
|
|
)
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(3)
|
2017-04-26 16:22:21 -07:00
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
class Thumbnail(SecantLineToTangentLine):
|
|
|
|
def construct(self):
|
|
|
|
self.setup_axes(animate = False)
|
|
|
|
self.add_graph()
|
|
|
|
self.curr_time = 6
|
|
|
|
ds_dt_group = self.get_ds_dt_group(1)
|
|
|
|
self.add(ds_dt_group)
|
|
|
|
self.remove(self.x_axis_label_mob)
|
|
|
|
self.remove(self.y_axis_label_mob)
|
|
|
|
VGroup(*self.get_mobjects()).fade(0.4)
|
|
|
|
|
|
|
|
title = TextMobject("Derivative paradox")
|
2018-03-30 11:25:37 -07:00
|
|
|
title.scale_to_fit_width(FRAME_WIDTH-1)
|
2017-01-13 14:10:10 -08:00
|
|
|
title.to_edge(UP)
|
|
|
|
title.add_background_rectangle()
|
2018-03-30 11:59:39 -07:00
|
|
|
title.set_color_by_gradient(GREEN, YELLOW)
|
2017-01-13 14:10:10 -08:00
|
|
|
|
|
|
|
randy = Randolph(mode = "confused")
|
|
|
|
randy.scale(1.7)
|
|
|
|
randy.to_corner(DOWN+LEFT)
|
|
|
|
randy.shift(RIGHT)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
deriv = TexMobject("\\frac{ds}{dt}(t)")
|
2018-03-30 11:51:31 -07:00
|
|
|
VGroup(*deriv[:2]).set_color(DISTANCE_COLOR)
|
|
|
|
VGroup(*deriv[3:5]).set_color(TIME_COLOR)
|
2017-01-13 14:10:10 -08:00
|
|
|
deriv.scale(3)
|
|
|
|
# deriv.next_to(randy, RIGHT, buff = 2)
|
|
|
|
deriv.to_edge(RIGHT, buff = LARGE_BUFF)
|
|
|
|
randy.look_at(deriv)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
2017-01-13 14:10:10 -08:00
|
|
|
self.add(title, randy, deriv)
|
2016-12-26 07:10:38 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|