mirror of
https://github.com/3b1b/manim.git
synced 2025-11-15 13:17:44 +00:00
RefreshOnDerivativeDefinition in eoc7
This commit is contained in:
parent
ecdbba3c4b
commit
dea0d4a948
9 changed files with 6433 additions and 6058 deletions
|
|
@ -178,6 +178,26 @@ class SmoothedVectorizedHomotopy(Homotopy):
|
||||||
submob.make_smooth()
|
submob.make_smooth()
|
||||||
|
|
||||||
|
|
||||||
|
class ApplyWave(Homotopy):
|
||||||
|
CONFIG = {
|
||||||
|
"direction" : DOWN,
|
||||||
|
"amplitude" : 0.2,
|
||||||
|
"run_time" : 1,
|
||||||
|
}
|
||||||
|
def __init__(self, mobject, **kwargs):
|
||||||
|
digest_config(self, kwargs, locals())
|
||||||
|
left_x = mobject.get_left()[0]
|
||||||
|
right_x = mobject.get_right()[0]
|
||||||
|
vect = self.amplitude*self.direction
|
||||||
|
def homotopy(x, y, z, t):
|
||||||
|
start_point = np.array([x, y, z])
|
||||||
|
alpha = (x-left_x)/(right_x-left_x)
|
||||||
|
power = np.exp(2*(alpha-0.5))
|
||||||
|
nudge = there_and_back(t**power)
|
||||||
|
return np.array([x, y, z]) + nudge*vect
|
||||||
|
Homotopy.__init__(self, homotopy, mobject, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class PhaseFlow(Animation):
|
class PhaseFlow(Animation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"virtual_time" : 1,
|
"virtual_time" : 1,
|
||||||
|
|
|
||||||
3230
eoc/chapter4.py
3230
eoc/chapter4.py
File diff suppressed because it is too large
Load diff
4839
eoc/chapter5.py
4839
eoc/chapter5.py
File diff suppressed because it is too large
Load diff
2755
eoc/chapter6.py
Normal file
2755
eoc/chapter6.py
Normal file
File diff suppressed because it is too large
Load diff
350
eoc/chapter7.py
Normal file
350
eoc/chapter7.py
Normal file
|
|
@ -0,0 +1,350 @@
|
||||||
|
from helpers import *
|
||||||
|
|
||||||
|
from mobject.tex_mobject import TexMobject
|
||||||
|
from mobject import Mobject
|
||||||
|
from mobject.image_mobject import ImageMobject
|
||||||
|
from mobject.vectorized_mobject import *
|
||||||
|
|
||||||
|
from animation.animation import Animation
|
||||||
|
from animation.transform import *
|
||||||
|
from animation.simple_animations import *
|
||||||
|
from animation.playground import *
|
||||||
|
from topics.geometry import *
|
||||||
|
from topics.characters import *
|
||||||
|
from topics.functions import *
|
||||||
|
from topics.fractals import *
|
||||||
|
from topics.number_line import *
|
||||||
|
from topics.combinatorics import *
|
||||||
|
from topics.numerals import *
|
||||||
|
from topics.three_dimensions import *
|
||||||
|
from topics.objects import *
|
||||||
|
from scene import Scene
|
||||||
|
from scene.zoomed_scene import ZoomedScene
|
||||||
|
from scene.reconfigurable_scene import ReconfigurableScene
|
||||||
|
from camera import Camera
|
||||||
|
from mobject.svg_mobject import *
|
||||||
|
from mobject.tex_mobject import *
|
||||||
|
|
||||||
|
from topics.common_scenes import OpeningQuote, PatreonThanks
|
||||||
|
|
||||||
|
from eoc.graph_scene import *
|
||||||
|
|
||||||
|
class Chapter7OpeningQuote(OpeningQuote):
|
||||||
|
CONFIG = {
|
||||||
|
"quote" : [
|
||||||
|
" Calculus required ",
|
||||||
|
"continuity",
|
||||||
|
", and ",
|
||||||
|
"continuity ",
|
||||||
|
"was supposed to require the ",
|
||||||
|
"infinitely little",
|
||||||
|
"; but nobody could discover what the ",
|
||||||
|
"infinitely little",
|
||||||
|
" might be. ",
|
||||||
|
],
|
||||||
|
"quote_arg_separator" : "",
|
||||||
|
"highlighted_quote_terms" : {
|
||||||
|
"continuity" : BLUE,
|
||||||
|
"infinitely" : GREEN,
|
||||||
|
},
|
||||||
|
"author" : "Bertrand Russell",
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThisVideo(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
series = VideoSeries()
|
||||||
|
series.to_edge(UP)
|
||||||
|
deriv_videos = VGroup(*series[1:6])
|
||||||
|
this_video = series[6]
|
||||||
|
integral_videos = VGroup(*series[7:9])
|
||||||
|
video_groups = [deriv_videos, this_video, integral_videos]
|
||||||
|
|
||||||
|
braces = map(Brace, video_groups)
|
||||||
|
deriv_brace, this_brace, integral_brace = braces
|
||||||
|
|
||||||
|
tex_mobs = [
|
||||||
|
TexMobject(*args)
|
||||||
|
for args in [
|
||||||
|
("{df ", " \\over \\, ", " dx}"),
|
||||||
|
("\\lim_{h \\to 0}",),
|
||||||
|
("\\int ", "f(x)", "\\,dx"),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
deriv_tex, this_tex, integral_tex = tex_mobs
|
||||||
|
for tex_mob, brace in zip(tex_mobs, braces):
|
||||||
|
tex_mob.highlight_by_tex("f", GREEN)
|
||||||
|
tex_mob.highlight_by_tex("dx", YELLOW)
|
||||||
|
tex_mob.next_to(brace, DOWN)
|
||||||
|
integral_tex.shift(LARGE_BUFF*RIGHT)
|
||||||
|
|
||||||
|
lim_to_deriv_arrow = Arrow(this_tex, deriv_tex, color = WHITE)
|
||||||
|
|
||||||
|
self.add(series)
|
||||||
|
for index in 0, 2:
|
||||||
|
videos = video_groups[index]
|
||||||
|
brace = braces[index]
|
||||||
|
tex_mob = tex_mobs[index]
|
||||||
|
self.play(ApplyWave(
|
||||||
|
videos,
|
||||||
|
apply_function_kwargs = {"maintain_smoothness" : False}
|
||||||
|
))
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(tex_mob, run_time = 2)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(self.get_teacher().change_mode, "raise_right_hand")
|
||||||
|
self.play(
|
||||||
|
this_video.highlight, YELLOW,
|
||||||
|
GrowFromCenter(this_brace)
|
||||||
|
)
|
||||||
|
self.play(Write(this_tex))
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(lim_to_deriv_arrow))
|
||||||
|
self.change_student_modes(*["happy"]*3)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class ApproachWordToLim(PiCreatureScene):
|
||||||
|
CONFIG = {
|
||||||
|
"dx_color" : GREEN
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
limit_expression = self.get_limit_expression()
|
||||||
|
limit_expression.next_to(
|
||||||
|
self.pi_creature, LEFT, aligned_edge = UP
|
||||||
|
)
|
||||||
|
|
||||||
|
evaluated_expressions = self.get_evaluated_expressions()
|
||||||
|
evaluated_expressions.to_edge(UP)
|
||||||
|
brace = Brace(evaluated_expressions[0][-1], DOWN)
|
||||||
|
question = TextMobject("What does this ``approach''?")
|
||||||
|
question.next_to(brace, DOWN)
|
||||||
|
|
||||||
|
expression = evaluated_expressions[0]
|
||||||
|
self.add(expression, brace, question)
|
||||||
|
self.change_mode("raise_right_hand")
|
||||||
|
for next_expression in evaluated_expressions[1:]:
|
||||||
|
next_expression.move_to(expression, RIGHT)
|
||||||
|
self.play(Transform(expression, next_expression))
|
||||||
|
self.dither(0.5)
|
||||||
|
self.play(
|
||||||
|
Write(limit_expression),
|
||||||
|
self.pi_creature.change_mode, "pondering"
|
||||||
|
)
|
||||||
|
self.play(Indicate(limit_expression[0]))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
def get_limit_expression(self):
|
||||||
|
lim = TexMobject("\\lim_", "{dx", " \\to 0}")
|
||||||
|
lim.highlight_by_tex("dx", self.dx_color)
|
||||||
|
ratio = self.get_expression("dx")
|
||||||
|
ratio.next_to(lim, RIGHT)
|
||||||
|
limit_expression = VGroup(lim, ratio)
|
||||||
|
return limit_expression
|
||||||
|
|
||||||
|
def get_evaluated_expressions(self):
|
||||||
|
result = VGroup()
|
||||||
|
for num_zeros in range(1, 6):
|
||||||
|
dx_str = "0." + "0"*num_zeros + "1"
|
||||||
|
expression = self.get_expression(dx_str)
|
||||||
|
dx = float(dx_str)
|
||||||
|
ratio = ((2+dx)**3-2**3)/dx
|
||||||
|
ratio_mob = TexMobject("%.6f\\dots"%ratio)
|
||||||
|
group = VGroup(expression, TexMobject("="), ratio_mob)
|
||||||
|
group.arrange_submobjects(RIGHT)
|
||||||
|
result.add(group)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_expression(self, dx):
|
||||||
|
result = TexMobject(
|
||||||
|
"{(2 + ", str(dx), ")^3 - 2^3 \\over", str(dx)
|
||||||
|
)
|
||||||
|
result.highlight_by_tex(dx, self.dx_color)
|
||||||
|
return result
|
||||||
|
|
||||||
|
class RefreshOnDerivativeDefinition(GraphScene):
|
||||||
|
CONFIG = {
|
||||||
|
"start_x" : 2,
|
||||||
|
"dx" : 0.7,
|
||||||
|
"df_color" : YELLOW,
|
||||||
|
"dx_color" : GREEN,
|
||||||
|
"secant_line_color" : MAROON_B,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup_axes()
|
||||||
|
def func(x):
|
||||||
|
u = 0.3*x - 1.5
|
||||||
|
return -u**3 + 5*u + 7
|
||||||
|
graph = self.get_graph(func)
|
||||||
|
graph_label = self.get_graph_label(graph)
|
||||||
|
start_x_v_line, nudged_x_v_line = [
|
||||||
|
self.get_vertical_line_to_graph(
|
||||||
|
self.start_x + nudge, graph,
|
||||||
|
line_class = DashedLine,
|
||||||
|
color = RED
|
||||||
|
)
|
||||||
|
for nudge in 0, self.dx
|
||||||
|
]
|
||||||
|
ss_group = self.get_secant_slope_group(
|
||||||
|
self.start_x, graph,
|
||||||
|
dx = self.dx,
|
||||||
|
dx_label = "dx",
|
||||||
|
df_label = "df",
|
||||||
|
df_line_color = self.df_color,
|
||||||
|
dx_line_color = self.dx_color,
|
||||||
|
secant_line_color = self.secant_line_color,
|
||||||
|
)
|
||||||
|
derivative = TexMobject(
|
||||||
|
"{df", "\\over \\,", "dx}", "(", str(self.start_x), ")"
|
||||||
|
)
|
||||||
|
derivative.highlight_by_tex("df", self.df_color)
|
||||||
|
derivative.highlight_by_tex("dx", self.dx_color)
|
||||||
|
derivative.highlight_by_tex(str(self.start_x), RED)
|
||||||
|
df = derivative.get_part_by_tex("df")
|
||||||
|
dx = derivative.get_part_by_tex("dx")
|
||||||
|
input_x = derivative.get_part_by_tex(str(self.start_x))
|
||||||
|
derivative.move_to(self.coords_to_point(7, 4))
|
||||||
|
deriv_brace = Brace(derivative)
|
||||||
|
dx_to_0 = TexMobject("dx", "\\to 0")
|
||||||
|
dx_to_0.highlight_by_tex("dx", self.dx_color)
|
||||||
|
dx_to_0.next_to(deriv_brace, DOWN)
|
||||||
|
|
||||||
|
#Introduce graph
|
||||||
|
self.play(ShowCreation(graph))
|
||||||
|
self.play(Write(graph_label, run_time = 1))
|
||||||
|
self.play(Write(derivative))
|
||||||
|
self.dither()
|
||||||
|
input_copy = input_x.copy()
|
||||||
|
self.play(
|
||||||
|
input_copy.next_to,
|
||||||
|
self.coords_to_point(self.start_x, 0),
|
||||||
|
DOWN
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(start_x_v_line))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
#ss_group_development
|
||||||
|
self.play(
|
||||||
|
ShowCreation(ss_group.dx_line),
|
||||||
|
ShowCreation(ss_group.dx_label),
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(ss_group.df_line))
|
||||||
|
self.play(Write(ss_group.df_label))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
ReplacementTransform(ss_group.dx_label.copy(), dx),
|
||||||
|
ReplacementTransform(ss_group.df_label.copy(), df),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(ss_group.secant_line))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
#Let dx approach 0
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(deriv_brace),
|
||||||
|
Write(dx_to_0),
|
||||||
|
)
|
||||||
|
self.animate_secant_slope_group_change(
|
||||||
|
ss_group,
|
||||||
|
target_dx = 0.01,
|
||||||
|
run_time = 5,
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
#Write out fuller limit
|
||||||
|
new_deriv = TexMobject(
|
||||||
|
"{f", "(", str(self.start_x), "+", "dx", ")",
|
||||||
|
"-", "f", "(", str(self.start_x), ")",
|
||||||
|
"\\over \\,", "dx"
|
||||||
|
)
|
||||||
|
new_deriv.highlight_by_tex("dx", self.dx_color)
|
||||||
|
new_deriv.highlight_by_tex("f", self.df_color)
|
||||||
|
new_deriv.highlight_by_tex(str(self.start_x), RED)
|
||||||
|
deriv_to_new_deriv = dict([
|
||||||
|
(
|
||||||
|
VGroup(derivative.get_part_by_tex(s)),
|
||||||
|
VGroup(*new_deriv.get_parts_by_tex(s))
|
||||||
|
)
|
||||||
|
for s in ["f", "over", "dx", "(", str(self.start_x), ")"]
|
||||||
|
])
|
||||||
|
covered_new_deriv_parts = list(it.chain(*deriv_to_new_deriv.values()))
|
||||||
|
uncovered_new_deriv_parts = filter(
|
||||||
|
lambda part : part not in covered_new_deriv_parts,
|
||||||
|
new_deriv
|
||||||
|
)
|
||||||
|
new_deriv.move_to(derivative)
|
||||||
|
new_brace = Brace(new_deriv, DOWN)
|
||||||
|
|
||||||
|
self.animate_secant_slope_group_change(
|
||||||
|
ss_group,
|
||||||
|
target_dx = self.dx,
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(nudged_x_v_line))
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
ReplacementTransform(*pair, run_time = 2)
|
||||||
|
for pair in deriv_to_new_deriv.items()
|
||||||
|
]+[
|
||||||
|
Transform(deriv_brace, new_brace),
|
||||||
|
dx_to_0.next_to, new_brace, DOWN
|
||||||
|
])
|
||||||
|
self.play(Write(VGroup(*uncovered_new_deriv_parts), run_time = 2))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
#Introduce limit notation
|
||||||
|
lim = TexMobject("\\lim").scale(1.3)
|
||||||
|
dx_to_0.generate_target()
|
||||||
|
dx_to_0.target.scale(0.7)
|
||||||
|
dx_to_0.target.next_to(lim, DOWN, buff = SMALL_BUFF)
|
||||||
|
lim_group = VGroup(lim, dx_to_0.target)
|
||||||
|
lim_group.move_to(new_deriv, LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ReplacementTransform(deriv_brace, lim),
|
||||||
|
MoveToTarget(dx_to_0),
|
||||||
|
new_deriv.next_to, lim_group, RIGHT,
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
for sf, color in (1.2, YELLOW), (1/1.2, WHITE):
|
||||||
|
self.play(
|
||||||
|
lim.scale_in_place, sf,
|
||||||
|
lim.highlight, color,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.animate_secant_slope_group_change(
|
||||||
|
ss_group, target_dx = 0.01,
|
||||||
|
run_time = 5,
|
||||||
|
added_anims = [
|
||||||
|
Transform(nudged_x_v_line, start_x_v_line, run_time = 5)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1221
eoc/exp_footnote.py
1221
eoc/exp_footnote.py
File diff suppressed because it is too large
Load diff
|
|
@ -251,6 +251,7 @@ class GraphScene(Scene):
|
||||||
df_label, (if applicable)
|
df_label, (if applicable)
|
||||||
secant_line, (if applicable)
|
secant_line, (if applicable)
|
||||||
)
|
)
|
||||||
|
with attributes of those names.
|
||||||
"""
|
"""
|
||||||
kwargs = locals()
|
kwargs = locals()
|
||||||
kwargs.pop("self")
|
kwargs.pop("self")
|
||||||
|
|
|
||||||
|
|
@ -110,28 +110,23 @@ class TexMobject(SVGMobject):
|
||||||
self.submobjects = new_submobjects
|
self.submobjects = new_submobjects
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_part_by_tex(self, tex, substring = True, return_all_parts = False):
|
def get_parts_by_tex(self, tex, substring = True):
|
||||||
def test(tex1, tex2):
|
def test(tex1, tex2):
|
||||||
return tex1 == tex2 or (substring and tex1 in tex2)
|
return tex1 == tex2 or (substring and tex1 in tex2)
|
||||||
|
|
||||||
if not hasattr(self, "expression_parts"):
|
if not hasattr(self, "expression_parts"):
|
||||||
if test(tex, self.get_tex_string()):
|
if test(tex, self.get_tex_string()):
|
||||||
return self
|
return self
|
||||||
return None
|
return []
|
||||||
all_parts = [
|
return [
|
||||||
submob
|
submob
|
||||||
for submob, part_tex in zip(self.split(), self.expression_parts)
|
for submob, part_tex in zip(self.split(), self.expression_parts)
|
||||||
if test(tex, part_tex)
|
if test(tex, part_tex)
|
||||||
]
|
]
|
||||||
if return_all_parts:
|
|
||||||
return all_parts
|
|
||||||
else:
|
|
||||||
if len(all_parts) > 0:
|
|
||||||
return all_parts[0]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_parts_by_tex(self, tex, **kwargs):
|
def get_part_by_tex(self, tex, **kwargs):
|
||||||
return self.get_part_by_tex(tex, return_all_parts = True, **kwargs)
|
all_parts = self.get_parts_by_tex(tex, **kwargs)
|
||||||
|
return all_parts[0] if all_parts else None
|
||||||
|
|
||||||
def highlight_by_tex(self, tex, color, **kwargs):
|
def highlight_by_tex(self, tex, color, **kwargs):
|
||||||
parts_to_color = self.get_parts_by_tex(tex, **kwargs)
|
parts_to_color = self.get_parts_by_tex(tex, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class OpeningQuote(Scene):
|
||||||
"""that contains all the
|
"""that contains all the
|
||||||
germs of generality."""
|
germs of generality."""
|
||||||
],
|
],
|
||||||
|
"quote_arg_separator" : " ",
|
||||||
"highlighted_quote_terms" : {
|
"highlighted_quote_terms" : {
|
||||||
"special case" : BLUE
|
"special case" : BLUE
|
||||||
},
|
},
|
||||||
|
|
@ -25,7 +26,7 @@ class OpeningQuote(Scene):
|
||||||
"fade_in_kwargs" : {
|
"fade_in_kwargs" : {
|
||||||
"submobject_mode" : "lagged_start",
|
"submobject_mode" : "lagged_start",
|
||||||
"rate_func" : None,
|
"rate_func" : None,
|
||||||
"lag_factor" : 3,
|
"lag_factor" : 4,
|
||||||
"run_time" : 5,
|
"run_time" : 5,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -39,14 +40,15 @@ class OpeningQuote(Scene):
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
def get_quote(self, max_width = 2*SPACE_WIDTH-1):
|
def get_quote(self, max_width = 2*SPACE_WIDTH-1):
|
||||||
|
text_mobject_kwargs = {
|
||||||
|
"alignment" : "",
|
||||||
|
"arg_separator" : self.quote_arg_separator,
|
||||||
|
}
|
||||||
if isinstance(self.quote, str):
|
if isinstance(self.quote, str):
|
||||||
quote = TextMobject(
|
quote = TextMobject("``%s''"%self.quote.strip(), **text_mobject_kwargs)
|
||||||
"``%s''"%self.quote.strip(),
|
|
||||||
alignment = "",
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
words = ["``"] + list(self.quote) + ["''"]
|
words = ["``"] + list(self.quote) + ["''"]
|
||||||
quote = TextMobject(*words, alignment = "")
|
quote = TextMobject(*words, **text_mobject_kwargs)
|
||||||
##TODO, make less hacky
|
##TODO, make less hacky
|
||||||
quote[0].shift(0.2*RIGHT)
|
quote[0].shift(0.2*RIGHT)
|
||||||
quote[-1].shift(0.2*LEFT)
|
quote[-1].shift(0.2*LEFT)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue