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

2169 lines
65 KiB
Python
Raw Normal View History

2017-04-17 10:19:30 -07:00
import scipy
2017-04-18 18:37:15 -07:00
import fractions
2017-04-17 10:19:30 -07:00
from big_ol_pile_of_manim_imports import *
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
class Chapter9OpeningQuote(OpeningQuote):
CONFIG = {
"quote" : [
"We often hear that mathematics consists mainly of",
"proving theorems.",
"Is a writer's job mainly that of\\\\",
"writing sentences?"
],
"highlighted_quote_terms" : {
"proving theorems." : MAROON_B,
"writing sentences?" : MAROON_B,
},
"author" : "Gian-Carlo Rota",
}
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
class AverageOfContinuousVariable(GraphScene):
CONFIG = {
"bounds" : [1, 7],
"bound_colors" : [RED, GREEN],
}
def construct(self):
self.setup_axes()
graph = self.get_graph(
lambda x : 0.1*x*(x-3)*(x-6) + 4
)
graph_label = self.get_graph_label(graph, "f(x)")
boundary_lines = self.get_vertical_lines_to_graph(
graph, *self.bounds, num_lines = 2,
line_class = DashedLine
)
for line, color in zip(boundary_lines, self.bound_colors):
2018-03-30 11:51:31 -07:00
line.set_color(color)
2017-04-18 18:37:15 -07:00
v_line = self.get_vertical_line_to_graph(
self.bounds[0], graph, color = YELLOW,
)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
question = TextMobject(
"What is the average \\\\ value of $f(x)$?"
)
question.next_to(boundary_lines, UP)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.play(ShowCreation(graph), Write(graph_label))
self.play(ShowCreation(boundary_lines))
self.play(FadeIn(
question,
run_time = 2,
submobject_mode = "lagged_start",
))
self.play(ShowCreation(v_line))
for bound in reversed(self.bounds):
self.play(self.get_v_line_change_anim(
v_line, graph, bound,
run_time = 3,
))
2018-01-15 19:15:05 -08:00
self.wait()
self.wait()
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def get_v_line_change_anim(self, v_line, graph, target_x, **kwargs):
start_x = self.x_axis.point_to_number(v_line.get_bottom())
def update(v_line, alpha):
new_x = interpolate(start_x, target_x, alpha)
v_line.put_start_and_end_on(
self.coords_to_point(new_x, 0),
self.input_to_graph_point(new_x, graph)
)
return v_line
return UpdateFromAlphaFunc(v_line, update, **kwargs)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
class ThisVideo(TeacherStudentsScene):
def construct(self):
series = VideoSeries()
series.to_edge(UP)
this_video = series[8]
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.play(FadeIn(series, submobject_mode = "lagged_start"))
self.teacher_says(
"A new view of \\\\ the fundamental theorem",
bubble_kwargs = {"height" : 3},
added_anims = [
this_video.shift, this_video.get_height()*DOWN/2,
2018-03-30 11:51:31 -07:00
this_video.set_color, YELLOW,
2017-04-18 18:37:15 -07:00
]
)
self.change_student_modes(*["pondering"]*3)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
class AverageOfSineStart(AverageOfContinuousVariable):
CONFIG = {
"y_min" : -2,
"y_max" : 2,
"x_min" : -1,
"x_max" : 2.5*np.pi,
"x_leftmost_tick" : 0,
"x_tick_frequency" : np.pi/4,
"x_axis_width" : 12,
"graph_origin" : 5*LEFT,
"x_label_scale_val" : 0.75,
"func" : np.sin,
"graph_color" : BLUE,
"bounds" : [0, np.pi],
}
def construct(self):
self.setup_axes()
self.add_graph()
self.ask_about_average()
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def add_graph(self, run_time = 1):
graph = self.get_graph(self.func, color = self.graph_color)
graph_label = self.get_graph_label(
graph, "\\sin(x)",
direction = UP
)
self.play(
ShowCreation(graph),
Write(graph_label),
run_time = run_time
)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.graph = graph
self.graph_label = graph_label
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def ask_about_average(self):
half_period_graph = self.get_graph_portion_between_bounds()
question = TextMobject("Average height?")
question.to_edge(UP)
arrow = Arrow(question.get_bottom(), half_period_graph.get_top())
midpoint = np.mean(self.bounds)
v_line = self.get_vertical_line_to_graph(
midpoint, self.graph,
line_class = DashedLine,
color = WHITE
)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.play(FadeIn(half_period_graph))
self.play(
Write(question, run_time = 2),
ShowCreation(arrow)
)
self.play(ShowCreation(v_line))
for bound in self.bounds + [midpoint]:
self.play(self.get_v_line_change_anim(
v_line, self.graph, bound,
run_time = 3
))
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
#########
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def get_graph_portion_between_bounds(self):
self.graph_portion_between_bounds = self.get_graph(
self.func,
x_min = self.bounds[0],
x_max = self.bounds[1],
color = YELLOW
)
return self.graph_portion_between_bounds
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def setup_axes(self):
GraphScene.setup_axes(self)
self.add_x_axis_labels()
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def add_x_axis_labels(self):
labels_and_x_values = [
("\\pi/2", np.pi/2),
("\\pi", np.pi),
("3\\pi/2", 3*np.pi/2),
("2\\pi", 2*np.pi),
]
self.x_axis_labels = VGroup()
for label, x in labels_and_x_values:
tex_mob = TexMobject(label)
tex_mob.scale(self.x_label_scale_val)
tex_mob.move_to(
self.coords_to_point(x, -3*self.x_axis.tick_size),
)
self.add(tex_mob)
self.x_axis_labels.add(tex_mob)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
class LengthOfDayGraph(GraphScene):
CONFIG = {
"x_min" : 0,
"x_max" : 365,
"x_axis_width" : 12,
"x_tick_frequency" : 25,
2018-08-09 17:56:05 -07:00
"x_labeled_nums" : list(range(50, 365, 50)),
2017-04-18 18:37:15 -07:00
"x_axis_label" : "Days since March 21",
"y_min" : 0,
"y_max" : 16,
"y_axis_height" : 6,
"y_tick_frequency" : 1,
2018-08-09 17:56:05 -07:00
"y_labeled_nums" : list(range(2, 15, 2)),
2017-04-18 18:37:15 -07:00
"y_axis_label" : "Hours of daylight",
"graph_origin" : 6*LEFT + 3*DOWN,
"camera_class" : ThreeDCamera,
"camera_config" : {
"shading_factor" : 1,
}
}
def construct(self):
self.setup_axes()
self.add_graph()
self.show_solar_pannel()
2018-03-30 11:51:31 -07:00
self.set_color_summer_months()
2017-04-18 18:37:15 -07:00
self.mention_constants()
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
def add_graph(self):
x_label = self.x_axis_label_mob
y_label = self.y_axis_label_mob
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
graph = self.get_graph(
lambda x : 2.7*np.sin((2*np.pi)*x/365 ) + 12.4,
color = GREEN,
)
graph_label = TexMobject("2.7\\sin(2\\pi x/365) + 12.4")
graph_label.to_corner(UP+RIGHT).shift(LEFT)
2018-03-30 11:51:31 -07:00
VGroup(*graph_label[3:6]).set_color(graph.get_color())
graph_label[9].set_color(YELLOW)
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.remove(x_label, y_label)
for label in y_label, x_label:
self.play(FadeIn(
label,
run_time = 2,
submobject_mode = "lagged_start"
))
self.play(
ShowCreation(graph, rate_func = None),
FadeIn(
graph_label,
rate_func = squish_rate_func(smooth, 0.5, 1),
submobject_mode = "lagged_start"
),
run_time = 3,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-17 10:19:30 -07:00
2017-04-18 18:37:15 -07:00
self.graph = graph
self.graph_label = graph_label
def show_solar_pannel(self):
randy = Randolph()
randy.to_edge(DOWN)
panel = ThreeDMobject(*[
Rectangle(
height = 0.7, width = 0.25,
fill_color = DARK_GREY,
fill_opacity = 1,
stroke_width = 1,
stroke_color = GREY,
)
for x in range(6)
])
panel.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
panel.center()
panels = ThreeDMobject(panel, panel.copy(), panel.copy())
panels.arrange_submobjects(DOWN)
panels.rotate(4*np.pi/12, DOWN)
panels.rotate(-np.pi/6, OUT)
side_vect = RIGHT
side_vect = rotate_vector(side_vect, 4*np.pi/12, DOWN)
side_vect = rotate_vector(side_vect, -np.pi/3, OUT)
panels.next_to(randy.get_corner(UP+RIGHT), RIGHT)
self.play(FadeIn(randy))
self.play(
randy.change, "thinking", panels.get_right(),
FadeIn(
panels,
run_time = 2,
submobject_mode = "lagged_start"
)
)
for angle in -np.pi/4, np.pi/4:
self.play(*[
Rotate(
panel, angle,
axis = side_vect,
in_place = True,
run_time = 2,
rate_func = squish_rate_func(smooth, a, a+0.8)
)
for panel, a in zip(panels, np.linspace(0, 0.2, len(panels)))
])
self.play(Blink(randy))
2018-08-09 17:56:05 -07:00
self.play(*list(map(FadeOut, [randy, panels])))
2017-04-18 18:37:15 -07:00
2018-03-30 11:51:31 -07:00
def set_color_summer_months(self):
2017-04-18 18:37:15 -07:00
summer_rect = Rectangle()
summer_rect.set_stroke(width = 0)
summer_rect.set_fill(YELLOW, opacity = 0.25)
summer_rect.replace(Line(
self.graph_origin,
self.coords_to_point(365/2, 15.5)
), stretch = True)
winter_rect = Rectangle()
winter_rect.set_stroke(width = 0)
winter_rect.set_fill(BLUE, opacity = 0.25)
winter_rect.replace(Line(
self.coords_to_point(365/2, 15.5),
self.coords_to_point(365, 0),
), stretch = True)
summer_words, winter_words = [
TextMobject("%s \\\\ months"%s).move_to(rect)
for s, rect in [
("Summer", summer_rect),
("Winter", winter_rect),
]
]
for rect, words in (summer_rect, summer_words), (winter_rect, winter_words):
self.play(
FadeIn(rect),
Write(words, run_time = 2)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
def mention_constants(self):
#2.7\\sin(2\\pi t/365) + 12.4
constants = VGroup(*[
VGroup(*self.graph_label[i:j])
for i, j in [(0, 3), (7, 9), (11, 14), (16, 20)]
])
self.play(*[
ApplyFunction(
2018-03-30 11:51:31 -07:00
lambda c : c.scale_in_place(0.9).shift(SMALL_BUFF*DOWN).set_color(RED),
2017-04-18 18:37:15 -07:00
constant,
run_time = 3,
rate_func = squish_rate_func(there_and_back, a, a+0.7)
)
for constant, a in zip(
constants,
np.linspace(0, 0.3, len(constants))
)
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
#####
class AskAboutAverageOfContinuousVariables(TeacherStudentsScene):
def construct(self):
self.student_says(
"The average \\dots of a \\\\ continuous thing?",
target_mode = "sassy",
)
self.change_student_modes("confused", "sassy", "confused")
self.play(self.teacher.change_mode, "happy")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
class AverageOfFiniteSet(Scene):
CONFIG = {
"lengths" : [1, 4, 2, 5]
}
def construct(self):
lengths = self.lengths
lines = VGroup(*[
Line(ORIGIN, length*RIGHT)
for length in lengths
])
colors = Color(BLUE).range_to(RED, len(lengths))
lines.set_color_by_gradient(*colors)
2017-04-18 18:37:15 -07:00
lines.arrange_submobjects(RIGHT)
lines.generate_target()
lines.target.arrange_submobjects(RIGHT, buff = 0)
for mob in lines, lines.target:
mob.shift(UP)
brace = Brace(lines.target, UP)
labels = VGroup(*[
2018-03-30 11:51:31 -07:00
TexMobject(str(d)).next_to(line, UP).set_color(line.get_color())
2017-04-18 18:37:15 -07:00
for d, line in zip(lengths, lines)
])
plusses = [TexMobject("+") for x in range(len(lengths)-1)]
symbols = VGroup(*
plusses + [TexMobject("=")]
)
symbols.set_fill(opacity = 0)
labels.generate_target()
symbols.generate_target()
symbols.target.set_fill(opacity = 1)
2018-08-09 17:56:05 -07:00
sum_eq = VGroup(*it.chain(*list(zip(labels.target, symbols.target))))
2017-04-18 18:37:15 -07:00
sum_eq.arrange_submobjects(RIGHT)
sum_eq.next_to(brace, UP)
sum_mob = TexMobject(str(sum(lengths)))
sum_mob.next_to(sum_eq, RIGHT)
dividing_lines = VGroup(*[
DashedLine(p + MED_SMALL_BUFF*UP, p + MED_LARGE_BUFF*DOWN)
for alpha in np.linspace(0, 1, len(lengths)+1)
for p in [interpolate(
lines.target.get_left(),
lines.target.get_right(),
alpha
)]
])
lower_braces = VGroup(*[
Brace(VGroup(*dividing_lines[i:i+2]), DOWN)
for i in range(len(lengths))
])
averages = VGroup(*[
lb.get_text("$%d/%d$"%(sum(lengths), len(lengths)))
for lb in lower_braces
])
circle = Circle(color = YELLOW)
circle.replace(averages[1], stretch = True)
circle.scale_in_place(1.5)
self.add(lines)
self.play(FadeIn(
labels,
submobject_mode = "lagged_start",
run_time = 3
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(
GrowFromCenter(brace),
2018-08-09 17:56:05 -07:00
*list(map(MoveToTarget, [lines, labels, symbols])),
2017-04-18 18:37:15 -07:00
run_time = 2
)
self.play(Write(sum_mob))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(ShowCreation(dividing_lines, run_time = 2))
self.play(*it.chain(
2018-08-09 17:56:05 -07:00
list(map(Write, averages)),
list(map(GrowFromCenter, lower_braces))
2017-04-18 18:37:15 -07:00
))
self.play(ShowCreation(circle))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
class TryToAddInfinitelyManyPoints(AverageOfSineStart):
CONFIG = {
"max_denominator" : 40,
}
def construct(self):
self.add_graph()
self.try_to_add_infinitely_many_values()
self.show_continuum()
self.mention_integral()
def add_graph(self):
self.setup_axes()
AverageOfSineStart.add_graph(self, run_time = 0)
self.add(self.get_graph_portion_between_bounds())
self.graph_label.to_edge(RIGHT)
self.graph_label.shift(DOWN)
def try_to_add_infinitely_many_values(self):
v_lines = VGroup(*[
self.get_vertical_line_to_graph(
numerator*np.pi/denominator, self.graph,
color = YELLOW,
stroke_width = 6./denominator
)
for denominator in range(self.max_denominator)
for numerator in range(1, denominator)
if fractions.gcd(numerator, denominator) == 1
])
ghost_lines = v_lines.copy().set_stroke(GREY)
v_lines.generate_target()
start_lines = VGroup(*v_lines.target[:15])
end_lines = VGroup(*v_lines.target[15:])
plusses = VGroup(*[TexMobject("+") for x in start_lines])
2018-08-09 17:56:05 -07:00
sum_eq = VGroup(*it.chain(*list(zip(start_lines, plusses))))
2017-04-18 18:37:15 -07:00
sum_eq.add(*end_lines)
sum_eq.arrange_submobjects(RIGHT)
sum_eq.next_to(v_lines[0], UP, aligned_edge = LEFT)
sum_eq.to_edge(UP, buff = MED_SMALL_BUFF)
h_line = Line(LEFT, RIGHT)
h_line.set_width(start_lines.get_width())
2018-03-30 11:51:31 -07:00
h_line.set_color(WHITE)
2017-04-18 18:37:15 -07:00
h_line.next_to(sum_eq, DOWN, aligned_edge = LEFT)
infinity = TexMobject("\\infty")
infinity.next_to(h_line, DOWN)
self.play(ShowCreation(
v_lines,
run_time = 3,
))
self.add(ghost_lines, v_lines)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
self.play(
MoveToTarget(
v_lines,
run_time = 3,
submobject_mode = "lagged_start"
),
Write(plusses)
)
self.play(ShowCreation(h_line))
self.play(Write(infinity))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
def show_continuum(self):
arrow = Arrow(ORIGIN, UP+LEFT)
input_range = Line(*[
self.coords_to_point(bound, 0)
for bound in self.bounds
])
2018-03-30 11:51:31 -07:00
VGroup(arrow, input_range).set_color(RED)
2017-04-18 18:37:15 -07:00
self.play(FadeIn(arrow))
self.play(
arrow.next_to, input_range.get_start(),
DOWN+RIGHT, SMALL_BUFF
)
self.play(
arrow.next_to, input_range.copy().get_end(),
DOWN+RIGHT, SMALL_BUFF,
ShowCreation(input_range),
run_time = 3,
)
self.play(
arrow.next_to, input_range.get_start(),
DOWN+RIGHT, SMALL_BUFF,
run_time = 3
)
self.play(FadeOut(arrow))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
def mention_integral(self):
randy = Randolph()
randy.to_edge(DOWN)
randy.shift(3*LEFT)
self.play(FadeIn(randy))
self.play(PiCreatureBubbleIntroduction(
randy, "Use an integral!",
bubble_class = ThoughtBubble,
target_mode = "hooray"
))
self.play(Blink(randy))
curr_bubble = randy.bubble
new_bubble = randy.get_bubble("Somehow...")
self.play(
Transform(curr_bubble, new_bubble),
Transform(curr_bubble.content, new_bubble.content),
randy.change_mode, "shruggie",
)
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
class FiniteSample(TryToAddInfinitelyManyPoints):
CONFIG = {
"dx" : 0.1,
"graph_origin" : 6*LEFT + 0.5*DOWN,
}
def construct(self):
self.add_graph()
self.show_finite_sample()
def show_finite_sample(self):
v_lines = self.get_sample_lines(dx = self.dx)
summed_v_lines = v_lines.copy()
plusses = VGroup(*[
TexMobject("+").scale(0.75)
for l in v_lines
])
2018-08-09 17:56:05 -07:00
numerator = VGroup(*it.chain(*list(zip(summed_v_lines, plusses))))
2017-04-18 18:37:15 -07:00
for group in numerator, plusses:
group.remove(plusses[-1])
numerator.arrange_submobjects(
RIGHT,
buff = SMALL_BUFF,
aligned_edge = DOWN
)
# numerator.set_width(FRAME_X_RADIUS)
2017-04-18 18:37:15 -07:00
numerator.scale(0.5)
numerator.move_to(self.coords_to_point(3*np.pi/2, 0))
numerator.to_edge(UP)
frac_line = TexMobject("\\over \\,")
frac_line.stretch_to_fit_width(numerator.get_width())
frac_line.next_to(numerator, DOWN)
denominator = TextMobject("(Num. samples)")
denominator.next_to(frac_line, DOWN)
self.play(ShowCreation(v_lines, run_time = 3))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(
ReplacementTransform(
v_lines.copy(),
summed_v_lines,
run_time = 3,
submobject_mode = "lagged_start"
),
Write(
plusses,
rate_func = squish_rate_func(smooth, 0.3, 1)
)
)
self.play(Write(frac_line, run_time = 1))
self.play(Write(denominator))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.plusses = plusses
self.average = VGroup(numerator, frac_line, denominator)
self.v_lines = v_lines
###
def get_sample_lines(self, dx, color = YELLOW, stroke_width = 2):
return VGroup(*[
self.get_vertical_line_to_graph(
x, self.graph,
color = color,
stroke_width = stroke_width,
)
for x in np.arange(
self.bounds[0]+dx,
self.bounds[1],
dx
)
])
class FiniteSampleWithMoreSamplePoints(FiniteSample):
CONFIG = {
"dx" : 0.05
}
2017-04-20 13:30:51 -07:00
class FeelsRelatedToAnIntegral(TeacherStudentsScene):
def construct(self):
self.student_says(
"Seems integral-ish...",
target_mode = "maybe"
)
self.play(self.teacher.change_mode, "happy")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
2017-04-18 18:37:15 -07:00
class IntegralOfSine(FiniteSample):
CONFIG = {
"thin_dx" : 0.01,
"rect_opacity" : 0.75,
}
def construct(self):
self.force_skipping()
FiniteSample.construct(self)
self.remove(self.y_axis_label_mob)
self.remove(*self.x_axis_labels[::2])
self.revert_to_original_skipping_status()
self.put_average_in_corner()
self.write_integral()
self.show_riemann_rectangles()
self.let_dx_approach_zero()
self.bring_back_average()
self.distribute_dx()
self.let_dx_approach_zero(restore = False)
self.write_area_over_width()
self.show_moving_v_line()
def put_average_in_corner(self):
self.average.save_state()
self.plusses.set_stroke(width = 0.5)
self.play(
self.average.scale, 0.75,
self.average.to_corner, DOWN+RIGHT,
)
def write_integral(self):
integral = TexMobject("\\int_0^\\pi", "\\sin(x)", "\\,dx")
integral.move_to(self.graph_portion_between_bounds)
integral.to_edge(UP)
self.play(Write(integral))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
self.integral = integral
def show_riemann_rectangles(self):
kwargs = {
"dx" : self.dx,
"x_min" : self.bounds[0],
"x_max" : self.bounds[1],
"fill_opacity" : self.rect_opacity,
}
rects = self.get_riemann_rectangles(self.graph, **kwargs)
rects.set_stroke(YELLOW, width = 1)
flat_rects = self.get_riemann_rectangles(
self.get_graph(lambda x : 0),
**kwargs
)
thin_kwargs = dict(kwargs)
thin_kwargs["dx"] = self.thin_dx
thin_kwargs["stroke_width"] = 0
self.thin_rects = self.get_riemann_rectangles(
self.graph,
**thin_kwargs
)
start_index = 20
end_index = start_index + 5
low_opacity = 0.5
high_opacity = 1
start_rect = rects[start_index]
side_brace = Brace(start_rect, LEFT, buff = SMALL_BUFF)
bottom_brace = Brace(start_rect, DOWN, buff = SMALL_BUFF)
sin_x = TexMobject("\\sin(x)")
sin_x.next_to(side_brace, LEFT, SMALL_BUFF)
dx = bottom_brace.get_text("$dx$", buff = SMALL_BUFF)
self.transform_between_riemann_rects(
flat_rects, rects,
replace_mobject_with_target_in_scene = True,
)
self.remove(self.v_lines)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
rects.save_state()
self.play(*it.chain(
[
ApplyMethod(
rect.set_style_data, BLACK, 1,
None, #Fill color
high_opacity if rect is start_rect else low_opacity
)
for rect in rects
],
2018-08-09 17:56:05 -07:00
list(map(GrowFromCenter, [side_brace, bottom_brace])),
list(map(Write, [sin_x, dx])),
2017-04-18 18:37:15 -07:00
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
for i in range(start_index+1, end_index):
self.play(
rects[i-1].set_fill, None, low_opacity,
rects[i].set_fill, None, high_opacity,
side_brace.set_height, rects[i].get_height(),
2017-04-18 18:37:15 -07:00
side_brace.next_to, rects[i], LEFT, SMALL_BUFF,
bottom_brace.next_to, rects[i], DOWN, SMALL_BUFF,
MaintainPositionRelativeTo(sin_x, side_brace),
MaintainPositionRelativeTo(dx, bottom_brace),
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(
rects.restore,
2018-08-09 17:56:05 -07:00
*list(map(FadeOut, [sin_x, dx, side_brace, bottom_brace]))
2017-04-18 18:37:15 -07:00
)
self.rects = rects
self.dx_brace = bottom_brace
self.dx_label = dx
def let_dx_approach_zero(self, restore = True):
start_state = self.rects.copy()
self.transform_between_riemann_rects(
self.rects, self.thin_rects,
run_time = 3
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
if restore:
self.transform_between_riemann_rects(
self.rects, start_state.copy(),
run_time = 2,
)
self.remove(self.rects)
self.rects = start_state
self.rects.set_fill(opacity = 1)
self.play(
self.rects.set_fill, None,
self.rect_opacity,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
def bring_back_average(self):
num_samples = self.average[-1]
example_dx = TexMobject("0.1")
example_dx.move_to(self.dx_label)
input_range = Line(*[
self.coords_to_point(bound, 0)
for bound in self.bounds
])
2018-03-30 11:51:31 -07:00
input_range.set_color(RED)
2017-04-18 18:37:15 -07:00
#Bring back average
self.play(
self.average.restore,
self.average.center,
self.average.to_edge, UP,
self.integral.to_edge, DOWN,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(
Write(self.dx_brace),
Write(self.dx_label),
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(
FadeOut(self.dx_label),
FadeIn(example_dx)
)
self.play(Indicate(example_dx))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.play(ShowCreation(input_range))
self.play(FadeOut(input_range))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
#Ask how many there are
num_samples_copy = num_samples.copy()
v_lines = self.v_lines
self.play(*[
ApplyFunction(
2018-03-30 11:51:31 -07:00
lambda l : l.shift(0.5*UP).set_color(GREEN),
2017-04-18 18:37:15 -07:00
line,
rate_func = squish_rate_func(
there_and_back, a, a+0.3
),
run_time = 3,
)
for line, a in zip(
self.v_lines,
np.linspace(0, 0.7, len(self.v_lines))
)
] + [
2018-03-30 11:51:31 -07:00
num_samples_copy.set_color, GREEN
2017-04-18 18:37:15 -07:00
])
self.play(FadeOut(v_lines))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
#Count number of samples
num_samples_copy.generate_target()
num_samples_copy.target.shift(DOWN + 0.5*LEFT)
rhs = TexMobject("\\approx", "\\pi", "/", "0.1")
rhs.next_to(num_samples_copy.target, RIGHT)
self.play(
MoveToTarget(num_samples_copy),
Write(rhs.get_part_by_tex("approx")),
)
self.play(ShowCreation(input_range))
self.play(ReplacementTransform(
self.x_axis_labels[1].copy(),
rhs.get_part_by_tex("pi")
))
self.play(FadeOut(input_range))
self.play(
ReplacementTransform(
example_dx.copy(),
rhs.get_part_by_tex("0.1")
),
Write(rhs.get_part_by_tex("/"))
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
#Substitute number of samples
self.play(ReplacementTransform(
example_dx, self.dx_label
))
dx = rhs.get_part_by_tex("0.1")
self.play(Transform(
dx, TexMobject("dx").move_to(dx)
))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
approx = rhs.get_part_by_tex("approx")
rhs.remove(approx)
self.play(
FadeOut(num_samples),
FadeOut(num_samples_copy),
FadeOut(approx),
rhs.next_to, self.average[1], DOWN
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.pi_over_dx = rhs
def distribute_dx(self):
numerator, frac_line, denominator = self.average
pi, over, dx = self.pi_over_dx
integral = self.integral
dx.generate_target()
lp, rp = parens = TexMobject("()")
parens.set_height(numerator.get_height())
2017-04-18 18:37:15 -07:00
lp.next_to(numerator, LEFT)
rp.next_to(numerator, RIGHT)
dx.target.next_to(rp, RIGHT)
self.play(
MoveToTarget(dx, path_arc = np.pi/2),
Write(parens),
frac_line.stretch_to_fit_width,
parens.get_width() + dx.get_width(),
frac_line.shift, dx.get_width()*RIGHT/2,
FadeOut(over)
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
average = VGroup(parens, numerator, dx, frac_line, pi)
integral.generate_target()
over_pi = TexMobject("\\frac{\\phantom{\\int \\sin(x)\\dx}}{\\pi}")
integral.target.set_width(over_pi.get_width())
2017-04-18 18:37:15 -07:00
integral.target.next_to(over_pi, UP)
integral_over_pi = VGroup(integral.target, over_pi)
integral_over_pi.to_corner(UP+RIGHT)
arrow = Arrow(LEFT, RIGHT)
arrow.next_to(integral.target, LEFT)
self.play(
average.scale, 0.9,
average.next_to, arrow, LEFT,
average.shift_onto_screen,
ShowCreation(arrow),
Write(over_pi),
MoveToTarget(integral, run_time = 2)
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2018-08-09 17:56:05 -07:00
self.play(*list(map(FadeOut, [self.dx_label, self.dx_brace])))
2017-04-18 18:37:15 -07:00
self.integral_over_pi = VGroup(integral, over_pi)
self.average = average
self.average_arrow = arrow
def write_area_over_width(self):
self.play(
self.integral_over_pi.shift, 2*LEFT,
2018-08-09 17:56:05 -07:00
*list(map(FadeOut, [self.average, self.average_arrow]))
2017-04-18 18:37:15 -07:00
)
average_height = TextMobject("Average height = ")
area_over_width = TexMobject(
"{\\text{Area}", "\\over\\,", "\\text{Width}}", "="
)
area_over_width.get_part_by_tex("Area").set_color_by_gradient(
2017-04-18 18:37:15 -07:00
BLUE, GREEN
)
area_over_width.next_to(self.integral_over_pi[1][0], LEFT)
average_height.next_to(area_over_width, LEFT)
2018-08-09 17:56:05 -07:00
self.play(*list(map(FadeIn, [average_height, area_over_width])))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
def show_moving_v_line(self):
mean = np.mean(self.bounds)
v_line = self.get_vertical_line_to_graph(
mean, self.graph,
line_class = DashedLine,
color = WHITE,
)
self.play(ShowCreation(v_line))
for count in range(2):
for x in self.bounds + [mean]:
self.play(self.get_v_line_change_anim(
v_line, self.graph, x,
run_time = 3
))
2017-04-20 13:30:51 -07:00
class Approx31(Scene):
def construct(self):
tex = TexMobject("\\approx 31")
tex.set_width(FRAME_WIDTH - LARGE_BUFF)
2017-04-20 13:30:51 -07:00
tex.to_edge(LEFT)
self.play(Write(tex))
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-04-20 13:30:51 -07:00
2017-04-18 18:37:15 -07:00
class LetsSolveThis(TeacherStudentsScene):
def construct(self):
expression = TexMobject(
"{\\int_0^\\pi ", " \\sin(x)", "\\,dx \\over \\pi}"
)
expression.to_corner(UP+LEFT)
question = TextMobject(
"What's the antiderivative \\\\ of",
"$\\sin(x)$",
"?"
)
for tex_mob in expression, question:
2018-03-30 11:51:31 -07:00
tex_mob.set_color_by_tex("sin", BLUE)
2017-04-18 18:37:15 -07:00
self.add(expression)
self.teacher_says("Let's compute it.")
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
self.student_thinks(question)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
class Antiderivative(AverageOfSineStart):
CONFIG = {
"antideriv_color" : GREEN,
"deriv_color" : BLUE,
2017-04-18 23:22:20 -07:00
"riemann_rect_dx" : 0.01,
"y_axis_label" : "",
"graph_origin" : 4*LEFT + DOWN,
2017-04-18 18:37:15 -07:00
}
def construct(self):
self.setup_axes()
self.add_x_axis_labels()
self.negate_derivative_of_cosine()
self.walk_through_slopes()
self.apply_ftoc()
self.show_difference_in_antiderivative()
self.comment_on_area()
2017-04-18 23:22:20 -07:00
self.divide_by_pi()
2018-03-30 11:51:31 -07:00
self.set_color_antiderivative_fraction()
2017-04-18 23:22:20 -07:00
self.show_slope()
self.bring_back_derivative()
self.show_tangent_slope()
def add_x_axis_labels(self):
AverageOfSineStart.add_x_axis_labels(self)
self.remove(*self.x_axis_labels[::2])
2017-04-18 18:37:15 -07:00
def negate_derivative_of_cosine(self):
cos, neg_cos, sin, neg_sin = graphs = [
self.get_graph(func)
for func in [
np.cos,
lambda x : -np.cos(x),
np.sin,
lambda x : -np.sin(x),
]
]
2018-03-30 11:51:31 -07:00
VGroup(cos, neg_cos).set_color(self.antideriv_color)
VGroup(sin, neg_sin).set_color(self.deriv_color)
2017-04-18 18:37:15 -07:00
labels = ["\\cos(x)", "-\\cos(x)", "\\sin(x)", "-\\sin(x)"]
x_vals = [2*np.pi, 2*np.pi, 5*np.pi/2, 5*np.pi/2]
vects = [UP, DOWN, UP, DOWN]
for graph, label, x_val, vect in zip(graphs, labels, x_vals, vects):
graph.label = self.get_graph_label(
graph, label,
x_val = x_val,
2017-04-18 23:22:20 -07:00
direction = vect,
buff = SMALL_BUFF
2017-04-18 18:37:15 -07:00
)
derivs = []
for F, f in ("\\cos", "-\\sin"), ("-\\cos", "\\sin"):
deriv = TexMobject(
"{d(", F, ")", "\\over\\,", "dx}", "(x)",
"=", f, "(x)"
)
2018-03-30 11:51:31 -07:00
deriv.set_color_by_tex(F, self.antideriv_color)
deriv.set_color_by_tex(f, self.deriv_color)
2017-04-18 18:37:15 -07:00
deriv.to_edge(UP)
derivs.append(deriv)
cos_deriv, neg_cos_deriv = derivs
self.add(cos_deriv)
for graph in cos, neg_sin:
self.play(
ShowCreation(graph, rate_func = smooth),
Write(
graph.label,
rate_func = squish_rate_func(smooth, 0.3, 1)
),
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
self.wait()
2017-04-18 18:37:15 -07:00
self.play(*[
ReplacementTransform(*pair)
for pair in [
(derivs),
(cos, neg_cos),
(cos.label, neg_cos.label),
(neg_sin, sin),
(neg_sin.label, sin.label),
]
])
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 18:37:15 -07:00
self.neg_cos = neg_cos
self.sin = sin
self.deriv = neg_cos_deriv
def walk_through_slopes(self):
neg_cos = self.neg_cos
sin = self.sin
faders = sin, sin.label
for mob in faders:
mob.save_state()
sin_copy = self.get_graph(
np.sin,
x_min = 0,
x_max = 2*np.pi,
color = BLUE,
)
v_line = self.get_vertical_line_to_graph(
0, neg_cos,
line_class = DashedLine,
color = WHITE
)
ss_group = self.get_secant_slope_group(
0, neg_cos,
dx = 0.001,
secant_line_color = YELLOW
)
def quad_smooth(t):
return 0.25*(np.floor(4*t) + smooth((4*t) % 1))
self.play(*[
2017-04-18 23:22:20 -07:00
ApplyMethod(m.fade, 0.6)
2017-04-18 18:37:15 -07:00
for m in faders
])
2018-01-15 19:15:05 -08:00
self.wait()
2018-08-09 17:56:05 -07:00
self.play(*list(map(ShowCreation, ss_group)), run_time = 2)
2017-04-18 18:37:15 -07:00
kwargs = {
"run_time" : 20,
"rate_func" : quad_smooth,
}
v_line_anim = self.get_v_line_change_anim(
v_line, sin_copy, 2*np.pi,
**kwargs
)
self.animate_secant_slope_group_change(
ss_group,
target_x = 2*np.pi,
added_anims = [
ShowCreation(sin_copy, **kwargs),
v_line_anim
],
**kwargs
)
self.play(
2018-08-09 17:56:05 -07:00
*list(map(FadeOut, [ss_group, v_line, sin_copy]))
2017-04-18 18:37:15 -07:00
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 18:37:15 -07:00
2017-04-18 23:22:20 -07:00
self.ss_group = ss_group
2017-04-18 18:37:15 -07:00
def apply_ftoc(self):
deriv = self.deriv
2017-04-18 23:22:20 -07:00
integral = TexMobject(
"\\int", "^\\pi", "_0", "\\sin(x)", "\\,dx"
)
rhs = TexMobject(
"=", "\\big(", "-\\cos", "(", "\\pi", ")", "\\big)",
"-", "\\big(", "-\\cos", "(", "0", ")", "\\big)",
)
rhs.next_to(integral, RIGHT)
equation = VGroup(integral, rhs)
equation.to_corner(UP+RIGHT, buff = MED_SMALL_BUFF)
(start_pi, end_pi), (start_zero, end_zero) = start_end_pairs = [
[
m.get_part_by_tex(tex)
for m in (integral, rhs)
2017-04-18 23:22:20 -07:00
]
for tex in ("\\pi", "0")
2017-04-18 23:22:20 -07:00
]
2017-04-18 18:37:15 -07:00
2017-04-18 23:22:20 -07:00
for tex_mob in integral, rhs:
2018-03-30 11:51:31 -07:00
tex_mob.set_color_by_tex("sin", self.deriv_color)
tex_mob.set_color_by_tex("cos", self.antideriv_color)
tex_mob.set_color_by_tex("0", YELLOW)
tex_mob.set_color_by_tex("\\pi", YELLOW)
2017-04-18 23:22:20 -07:00
self.play(
Write(integral),
self.deriv.scale, 0.5,
self.deriv.center,
self.deriv.to_edge, LEFT, MED_SMALL_BUFF,
self.deriv.shift, UP,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
self.play(FadeIn(
2018-08-09 17:56:05 -07:00
VGroup(*[part for part in rhs if part not in [end_pi, end_zero]]),
2017-04-18 23:22:20 -07:00
submobject_mode = "lagged_start",
run_time = 2,
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
for start, end in start_end_pairs:
self.play(ReplacementTransform(
start.copy(), end,
path_arc = np.pi/6,
run_time = 2
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
self.integral = integral
self.rhs = rhs
2017-04-18 18:37:15 -07:00
def show_difference_in_antiderivative(self):
2017-04-18 23:22:20 -07:00
pi_point, zero_point = points = [
self.input_to_graph_point(x, self.neg_cos)
for x in reversed(self.bounds)
]
interim_point = pi_point[0]*RIGHT + zero_point[1]*UP
pi_dot, zero_dot = dots = [
Dot(point, color = YELLOW)
for point in points
]
v_line = DashedLine(pi_point, interim_point)
h_line = DashedLine(interim_point, zero_point)
v_line_brace = Brace(v_line, RIGHT)
two_height_label = v_line_brace.get_text(
"$2$", buff = SMALL_BUFF
)
two_height_label.add_background_rectangle()
pi = self.x_axis_labels[1]
#Horrible hack
2018-03-30 11:51:31 -07:00
black_pi = pi.copy().set_color(BLACK)
2017-04-18 23:22:20 -07:00
self.add(black_pi, pi)
cos_tex = self.rhs.get_part_by_tex("cos")
self.play(ReplacementTransform(
cos_tex.copy(), pi_dot
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
moving_dot = pi_dot.copy()
self.play(
ShowCreation(v_line),
# Animation(pi),
pi.shift, 0.8*pi.get_width()*(LEFT+UP),
moving_dot.move_to, interim_point,
)
self.play(
ShowCreation(h_line),
ReplacementTransform(moving_dot, zero_dot)
)
self.play(GrowFromCenter(v_line_brace))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 23:22:20 -07:00
self.play(Write(two_height_label))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 23:22:20 -07:00
self.v_line = v_line
self.h_line = h_line
self.pi_dot = pi_dot
self.zero_dot = zero_dot
self.v_line_brace = v_line_brace
self.two_height_label = two_height_label
2017-04-18 18:37:15 -07:00
def comment_on_area(self):
2017-04-18 23:22:20 -07:00
rects = self.get_riemann_rectangles(
self.sin,
dx = self.riemann_rect_dx,
stroke_width = 0,
fill_opacity = 0.7,
x_min = self.bounds[0],
x_max = self.bounds[1],
)
area_two = TexMobject("2").replace(
self.two_height_label
)
self.play(Write(rects))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
self.play(area_two.move_to, rects)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 23:22:20 -07:00
self.rects = rects
self.area_two = area_two
def divide_by_pi(self):
integral = self.integral
rhs = self.rhs
equals = rhs[0]
rhs_without_eq = VGroup(*rhs[1:])
frac_lines = VGroup(*[
TexMobject("\\over\\,").stretch_to_fit_width(
mob.get_width()
).move_to(mob)
for mob in (integral, rhs_without_eq)
2017-04-18 23:22:20 -07:00
])
frac_lines.shift(
(integral.get_height()/2 + SMALL_BUFF)*DOWN
)
pi_minus_zeros = VGroup(*[
TexMobject("\\pi", "-", "0").next_to(line, DOWN)
for line in frac_lines
])
for tex_mob in pi_minus_zeros:
for tex in "pi", "0":
2018-03-30 11:51:31 -07:00
tex_mob.set_color_by_tex(tex, YELLOW)
2017-04-18 23:22:20 -07:00
answer = TexMobject(" = \\frac{2}{\\pi}")
answer.next_to(
frac_lines, RIGHT,
align_using_submobjects = True
)
answer.shift_onto_screen()
self.play(
equals.next_to, frac_lines[0].copy(), RIGHT,
rhs_without_eq.next_to, frac_lines[1].copy(), UP,
2018-08-09 17:56:05 -07:00
*list(map(Write, frac_lines))
2017-04-18 23:22:20 -07:00
)
self.play(*[
ReplacementTransform(
integral.get_part_by_tex(tex).copy(),
pi_minus_zeros[0].get_part_by_tex(tex)
)
for tex in ("\\pi","0")
2017-04-18 23:22:20 -07:00
] + [
Write(pi_minus_zeros[0].get_part_by_tex("-"))
])
self.play(*[
ReplacementTransform(
rhs.get_part_by_tex(
tex, substring = False
).copy(),
pi_minus_zeros[1].get_part_by_tex(tex)
)
for tex in ("\\pi", "-", "0")
2017-04-18 23:22:20 -07:00
])
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 23:22:20 -07:00
full_equation = VGroup(
integral, frac_lines, rhs, pi_minus_zeros
)
background_rect = BackgroundRectangle(full_equation, fill_opacity = 1)
background_rect.stretch_in_place(1.2, dim = 1)
full_equation.add_to_back(background_rect)
self.play(
full_equation.shift,
(answer.get_width()+MED_LARGE_BUFF)*LEFT
)
self.play(Write(answer))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
self.antiderivative_fraction = VGroup(
rhs_without_eq,
frac_lines[1],
pi_minus_zeros[1]
)
self.integral_fraction = VGroup(
integral,
frac_lines[0],
pi_minus_zeros[0],
equals
)
2018-03-30 11:51:31 -07:00
def set_color_antiderivative_fraction(self):
2017-04-18 23:22:20 -07:00
fraction = self.antiderivative_fraction
big_rect = Rectangle(
stroke_width = 0,
fill_color = BLACK,
2017-04-20 13:30:51 -07:00
fill_opacity = 0.75,
2017-04-18 23:22:20 -07:00
)
big_rect.set_width(FRAME_WIDTH)
big_rect.set_height(FRAME_HEIGHT)
2017-04-18 23:22:20 -07:00
morty = Mortimer()
morty.to_corner(DOWN+RIGHT)
self.play(
FadeIn(big_rect),
FadeIn(morty),
Animation(fraction)
)
self.play(morty.change, "raise_right_hand", fraction)
self.play(Blink(morty))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-18 23:22:20 -07:00
self.play(
FadeOut(big_rect),
FadeOut(morty),
Animation(fraction)
)
def show_slope(self):
line = Line(
self.zero_dot.get_center(),
self.pi_dot.get_center(),
)
2018-03-30 11:51:31 -07:00
line.set_color(RED)
2017-04-18 23:22:20 -07:00
line.scale_in_place(1.2)
2018-03-30 11:51:31 -07:00
new_v_line = self.v_line.copy().set_color(RED)
new_h_line = self.h_line.copy().set_color(RED)
2017-04-20 13:30:51 -07:00
2017-04-18 23:22:20 -07:00
pi = TexMobject("\\pi")
pi.next_to(self.h_line, DOWN)
self.play(
FadeOut(self.rects),
FadeOut(self.area_two)
)
2017-04-20 13:30:51 -07:00
self.play(ShowCreation(new_v_line))
self.play(
ShowCreation(new_h_line),
Write(pi)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
self.play(ShowCreation(line, run_time = 2))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
def bring_back_derivative(self):
self.play(
FadeOut(self.integral_fraction),
self.deriv.scale, 1.7,
self.deriv.to_corner, UP+LEFT, MED_LARGE_BUFF,
self.deriv.shift, MED_SMALL_BUFF*DOWN,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
def show_tangent_slope(self):
ss_group = self.get_secant_slope_group(
0, self.neg_cos,
dx = 0.001,
secant_line_color = YELLOW,
secant_line_length = 4,
)
2018-08-09 17:56:05 -07:00
self.play(*list(map(ShowCreation, ss_group)), run_time = 2)
2017-04-18 23:22:20 -07:00
for count in range(2):
for x in reversed(self.bounds):
self.animate_secant_slope_group_change(
ss_group,
target_x = x,
run_time = 6,
)
2017-04-20 13:30:51 -07:00
class GeneralAverage(AverageOfContinuousVariable):
CONFIG = {
"bounds" : [1, 6],
"bound_colors" : [GREEN, RED],
"graph_origin" : 5*LEFT + 2*DOWN,
"num_rect_iterations" : 4,
"max_dx" : 0.25,
}
def construct(self):
self.setup_axes()
self.add_graph()
self.ask_about_average()
self.show_signed_area()
self.put_area_away()
self.show_finite_sample()
self.show_improving_samples()
def add_graph(self):
graph = self.get_graph(self.func)
graph_label = self.get_graph_label(graph, "f(x)")
v_lines = VGroup(*[
self.get_vertical_line_to_graph(
x, graph, line_class = DashedLine
)
for x in self.bounds
])
for line, color in zip(v_lines, self.bound_colors):
2018-03-30 11:51:31 -07:00
line.set_color(color)
2018-08-09 17:56:05 -07:00
labels = list(map(TexMobject, "ab"))
2017-04-20 13:30:51 -07:00
for line, label in zip(v_lines, labels):
vect = line.get_start()-line.get_end()
2018-08-15 17:30:24 -07:00
label.next_to(line, vect/get_norm(vect))
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-04-20 13:30:51 -07:00
self.y_axis_label_mob.shift(0.7*LEFT)
self.play(
ShowCreation(graph),
Write(
graph_label,
rate_func = squish_rate_func(smooth, 0.5, 1)
),
run_time = 2
)
for line, label in zip(v_lines, labels):
self.play(
Write(label),
ShowCreation(line)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.graph = graph
self.graph_label = graph_label
self.bounds_labels = labels
self.bound_lines = v_lines
def ask_about_average(self):
v_line = self.get_vertical_line_to_graph(
self.bounds[0], self.graph,
line_class = DashedLine,
color = WHITE
)
average = TextMobject("Average = ")
fraction = TexMobject(
"{\\displaystyle \\int", "^b", "_a", "f(x)", "\\,dx",
"\\over", "b", "-", "a}"
)
for color, tex in zip(self.bound_colors, "ab"):
2018-03-30 11:51:31 -07:00
fraction.set_color_by_tex(tex, color)
fraction.set_color_by_tex("displaystyle", WHITE)
2017-04-20 13:30:51 -07:00
integral = VGroup(*fraction[:5])
denominator = VGroup(*fraction[5:])
average.next_to(fraction.get_part_by_tex("over"), LEFT)
group = VGroup(average, fraction)
group.center().to_edge(UP).shift(LEFT)
self.count = 0
def next_v_line_anim():
target = self.bounds[0] if self.count%2 == 1 else self.bounds[1]
self.count += 1
return self.get_v_line_change_anim(
v_line, self.graph, target,
run_time = 4,
)
self.play(
next_v_line_anim(),
Write(average, run_time = 2),
)
self.play(
next_v_line_anim(),
Write(
VGroup(*[
fraction.get_part_by_tex(tex)
for tex in ("int", "f(x)", "dx", "over")
2017-04-20 13:30:51 -07:00
]),
rate_func = squish_rate_func(smooth, 0.25, 0.75),
run_time = 4
),
*[
ReplacementTransform(
label.copy(),
fraction.get_part_by_tex(tex, substring = False),
run_time = 2
)
for label, tex in zip(
self.bounds_labels,
["_a", "^b"]
)
]
)
self.play(
next_v_line_anim(),
Write(
fraction.get_part_by_tex("-"),
run_time = 4,
rate_func = squish_rate_func(smooth, 0.5, 0.75),
),
*[
ReplacementTransform(
label.copy(),
fraction.get_part_by_tex(tex, substring = False),
run_time = 4,
rate_func = squish_rate_func(smooth, 0.25, 0.75)
)
for label, tex in zip(
self.bounds_labels,
["a}", "b"]
)
]
)
self.play(next_v_line_anim())
self.play(FadeOut(v_line))
self.average_expression = VGroup(average, fraction)
def show_signed_area(self):
rect_list = self.get_riemann_rectangles_list(
self.graph,
self.num_rect_iterations,
max_dx = self.max_dx,
x_min = self.bounds[0],
x_max = self.bounds[1],
end_color = BLUE,
fill_opacity = 0.75,
stroke_width = 0.25,
)
rects = rect_list[0]
plus = TexMobject("+")
plus.move_to(self.coords_to_point(2, 2))
minus = TexMobject("-")
minus.move_to(self.coords_to_point(5.24, -1))
self.play(FadeIn(
rects,
run_time = 2,
submobject_mode = "lagged_start"
))
for new_rects in rect_list[1:]:
self.transform_between_riemann_rects(rects, new_rects)
self.play(Write(plus))
self.play(Write(minus))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
self.area = VGroup(rects, plus, minus)
def put_area_away(self):
self.play(
FadeOut(self.area),
self.average_expression.scale, 0.75,
self.average_expression.to_corner, DOWN+RIGHT,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
def show_finite_sample(self):
v_lines = self.get_vertical_lines_to_graph(
self.graph,
x_min = self.bounds[0],
x_max = self.bounds[1],
color = GREEN
)
for line in v_lines:
if self.y_axis.point_to_number(line.get_end()) < 0:
2018-03-30 11:51:31 -07:00
line.set_color(RED)
2017-04-20 13:30:51 -07:00
line.save_state()
line_pair = VGroup(*v_lines[6:8])
brace = Brace(line_pair, DOWN)
dx = brace.get_text("$dx$")
num_samples = TextMobject("Num. samples")
approx = TexMobject("\\approx")
rhs = TexMobject("{b", "-", "a", "\\over", "dx}")
for tex, color in zip("ab", self.bound_colors):
2018-03-30 11:51:31 -07:00
rhs.set_color_by_tex(tex, color)
2017-04-20 13:30:51 -07:00
expression = VGroup(num_samples, approx, rhs)
expression.arrange_submobjects(RIGHT)
expression.next_to(self.y_axis, RIGHT)
rhs_copy = rhs.copy()
f_brace = Brace(line_pair, LEFT, buff = 0)
f_x = f_brace.get_text("$f(x)$")
add_up_f_over = TexMobject("\\text{Add up $f(x)$}", "\\over")
add_up_f_over.next_to(num_samples, UP)
add_up_f_over.to_edge(UP)
self.play(ShowCreation(v_lines, run_time = 2))
2018-08-09 17:56:05 -07:00
self.play(*list(map(Write, [brace, dx])))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.play(Write(VGroup(num_samples, approx, *rhs[:-1])))
self.play(ReplacementTransform(
dx.copy(), rhs.get_part_by_tex("dx")
))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
self.play(
FadeIn(add_up_f_over),
*[
ApplyFunction(
lambda m : m.fade().set_stroke(width = 2),
v_line
)
for v_line in v_lines
]
)
self.play(*[
ApplyFunction(
lambda m : m.restore().set_stroke(width = 5),
v_line,
run_time = 3,
rate_func = squish_rate_func(
there_and_back, a, a+0.2
)
)
for v_line, a in zip(v_lines, np.linspace(0, 0.8, len(v_lines)))
])
self.play(*[vl.restore for vl in v_lines])
self.play(rhs_copy.next_to, add_up_f_over, DOWN)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
frac_line = add_up_f_over[1]
self.play(
FadeOut(rhs_copy.get_part_by_tex("over")),
rhs_copy.get_part_by_tex("dx").next_to,
add_up_f_over[0], RIGHT, SMALL_BUFF,
frac_line.scale_about_point, 1.2, frac_line.get_left(),
frac_line.stretch_to_fit_height, frac_line.get_height(),
)
rhs_copy.remove(rhs_copy.get_part_by_tex("over"))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
int_fraction = self.average_expression[1].copy()
int_fraction.generate_target()
int_fraction.target.next_to(add_up_f_over, RIGHT, LARGE_BUFF)
int_fraction.target.shift_onto_screen()
double_arrow = TexMobject("\\Leftrightarrow")
double_arrow.next_to(
int_fraction.target.get_part_by_tex("over"), LEFT
)
self.play(
MoveToTarget(int_fraction),
VGroup(add_up_f_over, rhs_copy).shift, 0.4*DOWN
)
self.play(Write(double_arrow))
2018-08-09 17:56:05 -07:00
self.play(*list(map(FadeOut, [
2017-04-20 13:30:51 -07:00
dx, brace, num_samples, approx, rhs
2018-08-09 17:56:05 -07:00
])))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.v_lines = v_lines
def show_improving_samples(self):
stroke_width = self.v_lines[0].get_stroke_width()
new_v_lines_list = [
self.get_vertical_lines_to_graph(
self.graph,
x_min = self.bounds[0],
x_max = self.bounds[1],
num_lines = len(self.v_lines)*(2**n),
color = GREEN,
stroke_width = float(stroke_width)/n
)
for n in range(1, 4)
]
for new_v_lines in new_v_lines_list:
for line in new_v_lines:
if self.y_axis.point_to_number(line.get_end()) < 0:
2018-03-30 11:51:31 -07:00
line.set_color(RED)
2017-04-20 13:30:51 -07:00
for new_v_lines in new_v_lines_list:
self.play(Transform(
self.v_lines, new_v_lines,
run_time = 2,
submobject_mode = "lagged_start"
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
####
def func(self, x):
return 0.09*(x+1)*(x-4)*(x-8)
class GeneralAntiderivative(GeneralAverage):
def construct(self):
self.force_skipping()
self.setup_axes()
self.add_graph()
self.revert_to_original_skipping_status()
self.fade_existing_graph()
self.add_fraction()
self.add_antiderivative_graph()
self.show_average_in_terms_of_F()
self.draw_slope()
self.show_tangent_line_slopes()
def fade_existing_graph(self):
self.graph.fade(0.3)
self.graph_label.fade(0.3)
self.bound_lines.fade(0.3)
def add_fraction(self):
fraction = TexMobject(
"{\\displaystyle \\int", "^b", "_a", "f(x)", "\\,dx",
"\\over", "b", "-", "a}"
)
for tex, color in zip("ab", self.bound_colors):
2018-03-30 11:51:31 -07:00
fraction.set_color_by_tex(tex, color)
fraction.set_color_by_tex("display", WHITE)
2017-04-20 13:30:51 -07:00
fraction.scale(0.8)
fraction.next_to(self.y_axis, RIGHT)
fraction.to_edge(UP, buff = MED_SMALL_BUFF)
self.add(fraction)
self.fraction = fraction
def add_antiderivative_graph(self):
x_max = 9.7
antideriv_graph = self.get_graph(
lambda x : scipy.integrate.quad(
self.graph.underlying_function,
1, x
)[0],
color = YELLOW,
x_max = x_max,
)
antideriv_graph_label = self.get_graph_label(
antideriv_graph, "F(x)",
x_val = x_max
)
deriv = TexMobject(
"{dF", "\\over", "dx}", "(x)", "=", "f(x)"
)
2018-03-30 11:51:31 -07:00
deriv.set_color_by_tex("dF", antideriv_graph.get_color())
deriv.set_color_by_tex("f(x)", BLUE)
2017-04-20 13:30:51 -07:00
deriv.next_to(
antideriv_graph_label, DOWN, MED_LARGE_BUFF, LEFT
)
self.play(
ShowCreation(antideriv_graph),
Write(
antideriv_graph_label,
rate_func = squish_rate_func(smooth, 0.5, 1)
),
run_time = 2,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.play(Write(deriv))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.antideriv_graph = antideriv_graph
def show_average_in_terms_of_F(self):
new_fraction = TexMobject(
"=",
"{F", "(", "b", ")", "-", "F", "(", "a", ")",
"\\over",
"b", "-", "a}"
)
for tex, color in zip("abF", self.bound_colors+[YELLOW]):
2018-03-30 11:51:31 -07:00
new_fraction.set_color_by_tex(tex, color)
2017-04-20 13:30:51 -07:00
new_fraction.next_to(
self.fraction.get_part_by_tex("over"), RIGHT,
align_using_submobjects = True
)
to_write = VGroup(*it.chain(*[
new_fraction.get_parts_by_tex(tex)
for tex in "=F()-"
]))
to_write.remove(new_fraction.get_parts_by_tex("-")[-1])
numerator = VGroup(*new_fraction[1:10])
denominator = VGroup(*new_fraction[-3:])
self.play(Write(to_write))
self.play(*[
ReplacementTransform(
label.copy(),
new_fraction.get_part_by_tex(tex),
run_time = 2,
rate_func = squish_rate_func(smooth, a, a+0.7)
)
for label, tex, a in zip(
self.bounds_labels, "ab", [0, 0.3]
)
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.show_change_in_height(numerator.copy())
self.shift_antideriv_graph_up_and_down()
self.play(Write(VGroup(*new_fraction[-4:])))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
h_line_brace = Brace(self.h_line, DOWN)
denominator_copy = denominator.copy()
a_label = self.bounds_labels[0]
self.play(
GrowFromCenter(h_line_brace),
a_label.shift, 0.7*a_label.get_width()*LEFT,
a_label.shift, 2.2*a_label.get_height()*UP,
)
self.play(
denominator_copy.next_to, h_line_brace,
DOWN, SMALL_BUFF
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-04-20 13:30:51 -07:00
def show_change_in_height(self, numerator):
numerator.add_to_back(BackgroundRectangle(numerator))
a_point, b_point = points = [
self.input_to_graph_point(x, self.antideriv_graph)
for x in self.bounds
]
interim_point = b_point[0]*RIGHT + a_point[1]*UP
v_line = Line(b_point, interim_point)
h_line = Line(interim_point, a_point)
2018-03-30 11:51:31 -07:00
VGroup(v_line, h_line).set_color(WHITE)
2017-04-20 13:30:51 -07:00
brace = Brace(v_line, RIGHT, buff = SMALL_BUFF)
graph_within_bounds = self.get_graph(
self.antideriv_graph.underlying_function,
x_min = self.bounds[0],
x_max = self.bounds[1],
color = self.antideriv_graph.get_color()
)
2017-04-18 23:22:20 -07:00
2017-04-20 13:30:51 -07:00
b_label = self.bounds_labels[1]
self.play(
self.antideriv_graph.fade, 0.7,
Animation(graph_within_bounds)
)
self.play(
ShowCreation(v_line),
b_label.shift, b_label.get_width()*RIGHT,
b_label.shift, 1.75*b_label.get_height()*DOWN,
)
self.play(ShowCreation(h_line))
self.play(
numerator.scale, 0.75,
numerator.next_to, brace.copy(), RIGHT, SMALL_BUFF,
GrowFromCenter(brace),
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
self.antideriv_graph.add(
graph_within_bounds, v_line, h_line, numerator, brace
)
self.h_line = h_line
self.graph_points_at_bounds = points
2017-04-18 23:22:20 -07:00
2017-04-20 13:30:51 -07:00
def shift_antideriv_graph_up_and_down(self):
for vect in 2*UP, 3*DOWN, UP:
self.play(
self.antideriv_graph.shift, vect,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
2017-04-20 13:30:51 -07:00
def draw_slope(self):
line = Line(*self.graph_points_at_bounds)
2018-03-30 11:51:31 -07:00
line.set_color(PINK)
2017-04-20 13:30:51 -07:00
line.scale_in_place(1.3)
2017-04-18 23:22:20 -07:00
2017-04-20 13:30:51 -07:00
self.play(ShowCreation(line, run_time = 2))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-18 23:22:20 -07:00
2017-04-20 13:30:51 -07:00
def show_tangent_line_slopes(self):
ss_group = self.get_secant_slope_group(
x = self.bounds[0],
graph = self.antideriv_graph,
dx = 0.001,
secant_line_color = BLUE,
secant_line_length = 2,
)
2017-04-18 23:22:20 -07:00
2018-08-09 17:56:05 -07:00
self.play(*list(map(ShowCreation, ss_group)))
2017-04-20 13:30:51 -07:00
for x in range(2):
for bound in reversed(self.bounds):
self.animate_secant_slope_group_change(
ss_group,
target_x = bound,
run_time = 5,
)
2017-04-18 18:37:15 -07:00
2017-04-20 13:30:51 -07:00
class LastVideoWrapper(Scene):
def construct(self):
title = TextMobject("Chapter 8: Integrals")
title.to_edge(UP)
rect = Rectangle(height = 9, width = 16)
rect.set_stroke(WHITE)
rect.set_height(1.5*FRAME_Y_RADIUS)
2017-04-20 13:30:51 -07:00
rect.next_to(title, DOWN)
2017-04-17 10:19:30 -07:00
2017-04-20 13:30:51 -07:00
self.play(Write(title), ShowCreation(rect))
2018-01-15 19:15:05 -08:00
self.wait(5)
2017-04-17 10:19:30 -07:00
2017-04-20 13:30:51 -07:00
class ASecondIntegralSensation(TeacherStudentsScene):
def construct(self):
finite_average = TexMobject("{1+5+4+2 \\over 4}")
numbers = VGroup(*finite_average[0:7:2])
plusses = VGroup(*finite_average[1:7:2])
denominator = VGroup(*finite_average[7:])
finite_average.to_corner(UP+LEFT)
finite_average.to_edge(LEFT)
2017-04-17 10:19:30 -07:00
2017-04-20 13:30:51 -07:00
continuum = UnitInterval(
color = GREY,
unit_size = 6
2017-04-20 13:30:51 -07:00
)
continuum.next_to(finite_average, RIGHT, 2)
line = Line(continuum.get_left(), continuum.get_right())
2018-03-30 11:51:31 -07:00
line.set_color(YELLOW)
2017-04-20 13:30:51 -07:00
arrow = Arrow(DOWN+RIGHT, ORIGIN)
arrow.next_to(line.get_start(), DOWN+RIGHT, SMALL_BUFF)
sigma_to_integral = TexMobject(
"\\sum \\Leftrightarrow \\int"
)
sigma_to_integral.next_to(
self.teacher.get_corner(UP+LEFT), UP, MED_LARGE_BUFF
)
self.teacher_says(
"A second integral \\\\ sensation"
)
self.change_student_modes(*["erm"]*3)
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.play(
Write(numbers),
RemovePiCreatureBubble(self.teacher),
)
self.change_student_modes(
*["pondering"]*3,
look_at_arg = numbers
)
self.play(Write(plusses))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.play(Write(denominator))
2018-01-15 19:15:05 -08:00
self.wait()
2017-04-20 13:30:51 -07:00
self.change_student_modes(
*["confused"]*3,
look_at_arg = continuum,
added_anims = [Write(continuum, run_time = 2)]
)
self.play(ShowCreation(arrow))
arrow.save_state()
self.play(
arrow.next_to, line.copy().get_end(), DOWN+RIGHT, SMALL_BUFF,
ShowCreation(line),
run_time = 2
)
2018-08-09 17:56:05 -07:00
self.play(*list(map(FadeOut, [arrow])))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-04-20 13:30:51 -07:00
self.change_student_modes(
*["pondering"]*3,
look_at_arg = sigma_to_integral,
added_anims = [
Write(sigma_to_integral),
self.teacher.change_mode, "raise_right_hand"
]
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-04-20 13:30:51 -07:00
class Chapter9PatreonThanks(PatreonThanks):
CONFIG = {
"specific_patrons" : [
"Ali Yahya",
"CrypticSwarm",
"Kaustuv DeBiswas",
"Kathryn Schmiedicke",
"Karan Bhargava",
"Ankit Agarwal",
"Yu Jun",
"Dave Nicponski",
"Damion Kistler",
"Juan Benet",
"Othman Alikhan",
"Markus Persson",
"Dan Buchoff",
"Derek Dai",
"Joseph John Cox",
"Luc Ritchie",
"Zac Wentzell",
"Robert Teed",
"Jason Hise",
"Meshal Alshammari",
"Bernd Sing",
"Nils Schneider",
"James Thornton",
"Mustafa Mahdi",
"Jonathan Eppele",
"Mathew Bramson",
"Jerry Ling",
"Mark Govea",
"Vecht",
"Shimin Kuang",
"Rish Kundalia",
"Achille Brighton",
"Ripta Pasay",
],
}
2017-05-02 21:09:56 -07:00
class Thumbnail(GraphScene):
CONFIG = {
"x_min" : -0.2,
"x_max" : 3.5,
"x_leftmost_tick" : 0,
"x_tick_frequency" : np.pi/4,
"x_axis_label" : "",
"y_min" : -0.75,
"y_max" : 0.75,
"y_axis_height" : 4.5,
"y_tick_frequency" : 0.25,
"y_axis_label" : ""
}
2017-04-20 13:30:51 -07:00
def construct(self):
2017-05-02 21:09:56 -07:00
self.setup_axes()
self.remove(self.axes)
sine = self.get_graph(np.sin)
rects = self.get_riemann_rectangles(
sine,
x_min = 0,
x_max = np.pi,
dx = 0.01,
stroke_width = 0,
)
sine.add_to_back(rects)
sine.add(self.axes.copy())
sine.to_corner(UP+LEFT, buff = SMALL_BUFF)
sine.scale(0.9)
area = TextMobject("Area")
area.scale(3)
area.move_to(rects)
cosine = self.get_graph(lambda x : -np.cos(x))
cosine.set_stroke(GREEN, 8)
line = self.get_secant_slope_group(
0.75*np.pi, cosine,
dx = 0.01
).secant_line
line.set_stroke(PINK, 7)
cosine.add(line)
cosine.add(self.axes.copy())
cosine.scale(0.7)
cosine.to_corner(DOWN+RIGHT, buff = MED_SMALL_BUFF)
slope = TextMobject("Slope")
slope.scale(3)
# slope.next_to(cosine, LEFT, buff = 0)
# slope.to_edge(DOWN)
slope.to_corner(DOWN+RIGHT)
double_arrow = DoubleArrow(
area.get_bottom(),
slope.get_left(),
color = YELLOW,
tip_length = 0.75,
buff = MED_LARGE_BUFF
)
double_arrow.set_stroke(width = 18)
triangle = Polygon(
ORIGIN, UP, UP+RIGHT,
stroke_width = 0,
fill_color = BLUE_E,
fill_opacity = 0.5,
)
triangle.stretch_to_fit_width(FRAME_WIDTH)
triangle.stretch_to_fit_height(FRAME_HEIGHT)
2017-05-02 21:09:56 -07:00
triangle.to_corner(UP+LEFT, buff = 0)
alt_triangle = triangle.copy()
alt_triangle.rotate(np.pi)
alt_triangle.set_fill(BLACK, 1)
self.add(
triangle, sine, area,
alt_triangle, cosine, slope,
double_arrow,
)
2017-04-17 10:19:30 -07:00