mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 05:24:22 +08:00
Pattern for power rule in eoc3
This commit is contained in:
@ -124,6 +124,7 @@ class ApplyMethod(Transform):
|
||||
target = copy.deepcopy(method)(*args)
|
||||
Transform.__init__(self, method.im_self, target, **kwargs)
|
||||
|
||||
|
||||
class FadeOut(Transform):
|
||||
CONFIG = {
|
||||
"remover" : True,
|
||||
|
234
eoc/chapter3.py
234
eoc/chapter3.py
@ -1008,10 +1008,236 @@ class ShowCubeDVIn3D(Scene):
|
||||
def construct(self):
|
||||
raise Exception("This scene is only here for the stage_scenes script.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class GraphOfXCubed(GraphScene):
|
||||
CONFIG = {
|
||||
"x_min" : -6,
|
||||
"x_max" : 6,
|
||||
"x_axis_width" : 2*SPACE_WIDTH,
|
||||
"x_labeled_nums" : range(-6, 7),
|
||||
"y_min" : -35,
|
||||
"y_max" : 35,
|
||||
"y_axis_height" : 2*SPACE_HEIGHT,
|
||||
"y_tick_frequency" : 5,
|
||||
"y_labeled_nums" : range(-30, 40, 10),
|
||||
"graph_origin" : ORIGIN,
|
||||
"dx" : 0.2,
|
||||
"deriv_x_min" : -3,
|
||||
"deriv_x_max" : 3,
|
||||
}
|
||||
def construct(self):
|
||||
self.setup_axes(animate = False)
|
||||
graph = self.get_graph(lambda x : x**3)
|
||||
label = self.get_graph_label(
|
||||
graph, "f(x) = x^3",
|
||||
direction = LEFT,
|
||||
)
|
||||
|
||||
|
||||
deriv_graph, full_deriv_graph = [
|
||||
self.get_derivative_graph(
|
||||
graph,
|
||||
color = DERIVATIVE_COLOR,
|
||||
x_min = low_x,
|
||||
x_max = high_x,
|
||||
)
|
||||
for low_x, high_x in [
|
||||
(self.deriv_x_min, self.deriv_x_max),
|
||||
(self.x_min, self.x_max),
|
||||
]
|
||||
]
|
||||
deriv_label = self.get_graph_label(
|
||||
deriv_graph,
|
||||
"\\frac{df}{dx}(x) = 3x^2",
|
||||
x_val = -3,
|
||||
direction = LEFT
|
||||
)
|
||||
deriv_label.shift(0.5*DOWN)
|
||||
|
||||
ss_group = self.get_secant_slope_group(
|
||||
self.deriv_x_min, graph,
|
||||
dx = self.dx,
|
||||
dx_line_color = WHITE,
|
||||
df_line_color = WHITE,
|
||||
secant_line_color = YELLOW,
|
||||
)
|
||||
|
||||
self.play(ShowCreation(graph))
|
||||
self.play(Write(label, run_time = 1))
|
||||
self.dither()
|
||||
self.play(Write(deriv_label, run_time = 1))
|
||||
self.play(ShowCreation(ss_group, submobject_mode = "all_at_once"))
|
||||
self.animate_secant_slope_group_change(
|
||||
ss_group,
|
||||
target_x = self.deriv_x_max,
|
||||
run_time = 10,
|
||||
added_anims = [
|
||||
ShowCreation(deriv_graph, run_time = 10)
|
||||
]
|
||||
)
|
||||
self.play(FadeIn(full_deriv_graph))
|
||||
self.dither()
|
||||
for x_val in -2, -self.dx/2, 2:
|
||||
self.animate_secant_slope_group_change(
|
||||
ss_group,
|
||||
target_x = x_val,
|
||||
run_time = 2
|
||||
)
|
||||
if x_val != -self.dx/2:
|
||||
v_line = self.get_vertical_line_to_graph(
|
||||
x_val, deriv_graph,
|
||||
line_class = DashedLine
|
||||
)
|
||||
self.play(ShowCreation(v_line))
|
||||
self.play(FadeOut(v_line))
|
||||
|
||||
class PatternForPowerRule(PiCreatureScene):
|
||||
CONFIG = {
|
||||
"num_exponents" : 5,
|
||||
}
|
||||
def construct(self):
|
||||
self.introduce_pattern()
|
||||
self.generalize_pattern()
|
||||
self.show_hopping()
|
||||
|
||||
def introduce_pattern(self):
|
||||
exp_range = range(1, 1+self.num_exponents)
|
||||
colors = color_gradient([BLUE_D, YELLOW], self.num_exponents)
|
||||
derivatives = VGroup()
|
||||
for exponent, color in zip(exp_range, colors):
|
||||
derivative = TexMobject(
|
||||
"\\frac{d(x^%d)}{dx} = "%exponent,
|
||||
"%d x^{%d}"%(exponent, exponent-1)
|
||||
)
|
||||
VGroup(*derivative[0][2:4]).highlight(color)
|
||||
derivatives.add(derivative)
|
||||
derivatives.arrange_submobjects(
|
||||
DOWN, aligned_edge = LEFT,
|
||||
buff = MED_LARGE_BUFF
|
||||
)
|
||||
derivatives.scale_to_fit_height(2*SPACE_HEIGHT-1)
|
||||
derivatives.to_edge(LEFT)
|
||||
|
||||
self.play(FadeIn(derivatives[0]))
|
||||
for d1, d2 in zip(derivatives, derivatives[1:]):
|
||||
self.play(Transform(
|
||||
d1.copy(), d2,
|
||||
replace_mobject_with_target_in_scene = True
|
||||
))
|
||||
self.change_mode("thinking")
|
||||
self.dither()
|
||||
for derivative in derivatives[-2:]:
|
||||
derivative.save_state()
|
||||
self.play(
|
||||
derivative.scale, 2,
|
||||
derivative.next_to, derivative,
|
||||
RIGHT, SMALL_BUFF, DOWN,
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(derivative.restore)
|
||||
self.remove(derivative)
|
||||
derivative.restore()
|
||||
self.add(derivative)
|
||||
|
||||
self.derivatives = derivatives
|
||||
self.colors = colors
|
||||
|
||||
def generalize_pattern(self):
|
||||
derivatives = self.derivatives
|
||||
|
||||
|
||||
power_rule = TexMobject(
|
||||
"\\frac{d (x^n)}{dx} = ",
|
||||
"nx^{n-1}"
|
||||
)
|
||||
title = TextMobject("``Power rule''")
|
||||
title.next_to(power_rule, UP, MED_LARGE_BUFF)
|
||||
lines = VGroup(*[
|
||||
Line(
|
||||
deriv.get_right(), power_rule.get_left(),
|
||||
buff = MED_SMALL_BUFF,
|
||||
color = deriv[0][2].get_color()
|
||||
)
|
||||
for deriv in derivatives
|
||||
])
|
||||
|
||||
self.play(
|
||||
Transform(
|
||||
VGroup(*[d[0].copy() for d in derivatives]),
|
||||
VGroup(power_rule[0]),
|
||||
replace_mobject_with_target_in_scene = True
|
||||
),
|
||||
ShowCreation(lines),
|
||||
submobject_mode = "lagged_start",
|
||||
run_time = 2,
|
||||
)
|
||||
self.dither()
|
||||
self.play(Write(power_rule[1]))
|
||||
self.dither()
|
||||
self.play(
|
||||
Write(title),
|
||||
self.pi_creature.change_mode, "speaking"
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def show_hopping(self):
|
||||
exp_range = range(2, 2+self.num_exponents-1)
|
||||
self.change_mode("tired")
|
||||
for exp, color in zip(exp_range, self.colors[1:]):
|
||||
form = TexMobject(
|
||||
"x^",
|
||||
str(exp),
|
||||
"\\rightarrow",
|
||||
str(exp),
|
||||
"x^",
|
||||
str(exp-1)
|
||||
)
|
||||
form.highlight(color)
|
||||
form.to_corner(UP+RIGHT, buff = LARGE_BUFF)
|
||||
lhs = VGroup(*form[:2])
|
||||
lhs_copy = lhs.copy()
|
||||
rhs = VGroup(*form[-2:])
|
||||
arrow = form[2]
|
||||
|
||||
self.play(Write(lhs))
|
||||
self.play(
|
||||
lhs_copy.move_to, rhs, DOWN+LEFT,
|
||||
Write(arrow)
|
||||
)
|
||||
self.dither()
|
||||
self.play(Transform(
|
||||
lhs_copy[1], form[3],
|
||||
path_arc = np.pi,
|
||||
rate_func = running_start,
|
||||
replace_mobject_with_target_in_scene = True
|
||||
))
|
||||
self.play(FadeIn(form[5]))
|
||||
self.dither()
|
||||
self.play(
|
||||
self.pi_creature.change_mode, "hesitant",
|
||||
self.pi_creature.look_at, lhs_copy
|
||||
)
|
||||
self.play(*map(FadeOut, [form, lhs_copy]))
|
||||
|
||||
# class PowerRuleAlgebra(Scene):
|
||||
# CONFIG = {
|
||||
# "dx_color" : YELLOW,
|
||||
# }
|
||||
# def construct(self):
|
||||
# value = TextMobject("Value:")
|
||||
# x_to_n = TexMobject("x^n")
|
||||
# nudged = TextMobject("Nudged Value:")
|
||||
# x_dx_to_n = TexMobject("(x+dx)^n")
|
||||
# equals = TexMobject("equals")
|
||||
# full_product = TexMobject("(x+dx)(x+dx)(x+dx)\\cdots(x+dx)")
|
||||
|
||||
# value.to_corner(UP+LEFT)
|
||||
# x_to_n.next_to(value, RIGHT)
|
||||
# nudged.next_to(value, DOWN, aligned_edge = LEFT)
|
||||
# x_dx_group = VGroup(x_dx_to_n, equals, full_product)
|
||||
# x_dx_group.arrange_submobjects(RIGHT)
|
||||
|
||||
|
||||
# self.add(value, nudged_value)
|
||||
|
||||
|
||||
|
||||
|
@ -28,7 +28,7 @@ class GraphScene(Scene):
|
||||
"y_axis_label" : "$y$",
|
||||
"axes_color" : GREY,
|
||||
"graph_origin" : 2.5*DOWN + 4*LEFT,
|
||||
"y_axis_numbers_nudge" : 0.4*UP+0.5*LEFT,
|
||||
"y_axis_numbers_nudge" : 0.4*UP,
|
||||
"num_graph_anchor_points" : 25,
|
||||
"default_graph_colors" : [BLUE, GREEN, YELLOW],
|
||||
"default_derivative_color" : GREEN,
|
||||
@ -48,9 +48,16 @@ class GraphScene(Scene):
|
||||
)
|
||||
x_axis.shift(self.graph_origin - x_axis.number_to_point(0))
|
||||
if self.x_labeled_nums:
|
||||
x_axis.add_numbers(*self.x_labeled_nums)
|
||||
x_axis.add_numbers(*filter(
|
||||
lambda x : x != 0,
|
||||
self.x_labeled_nums
|
||||
))
|
||||
x_label = TextMobject(self.x_axis_label)
|
||||
x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF)
|
||||
x_label.next_to(
|
||||
x_axis.get_tick_marks(), UP,
|
||||
aligned_edge = RIGHT,
|
||||
buff = SMALL_BUFF
|
||||
)
|
||||
x_label.shift_onto_screen()
|
||||
x_axis.add(x_label)
|
||||
self.x_axis_label_mob = x_label
|
||||
@ -69,10 +76,19 @@ class GraphScene(Scene):
|
||||
y_axis.shift(self.graph_origin-y_axis.number_to_point(0))
|
||||
y_axis.rotate(np.pi/2, about_point = y_axis.number_to_point(0))
|
||||
if self.y_labeled_nums:
|
||||
y_axis.add_numbers(*self.y_labeled_nums)
|
||||
y_axis.numbers.shift(self.y_axis_numbers_nudge)
|
||||
y_axis.add_numbers(*filter(
|
||||
lambda y : y != 0,
|
||||
self.y_labeled_nums
|
||||
))
|
||||
for mob in y_axis.numbers:
|
||||
mob.next_to(mob.get_center(), LEFT, MED_SMALL_BUFF)
|
||||
mob.shift(self.y_axis_numbers_nudge)
|
||||
y_label = TextMobject(self.y_axis_label)
|
||||
y_label.next_to(y_axis.get_top(), RIGHT, buff = MED_LARGE_BUFF)
|
||||
y_label.next_to(
|
||||
y_axis.get_tick_marks(), RIGHT,
|
||||
aligned_edge = UP,
|
||||
buff = SMALL_BUFF
|
||||
)
|
||||
y_label.shift_onto_screen()
|
||||
y_axis.add(y_label)
|
||||
self.y_axis_label_mob = y_label
|
||||
@ -90,12 +106,21 @@ class GraphScene(Scene):
|
||||
result += self.y_axis.number_to_point(y)[1]*UP
|
||||
return result
|
||||
|
||||
def get_graph(self, func, color = None):
|
||||
def get_graph(
|
||||
self, func,
|
||||
color = None,
|
||||
x_min = None,
|
||||
x_max = None,
|
||||
):
|
||||
if color is None:
|
||||
color = self.default_graph_colors.next()
|
||||
if x_min is None:
|
||||
x_min = self.x_min
|
||||
if x_max is None:
|
||||
x_max = self.x_max
|
||||
|
||||
def parameterized_function(alpha):
|
||||
x = interpolate(self.x_min, self.x_max, alpha)
|
||||
x = interpolate(x_min, x_max, alpha)
|
||||
return self.coords_to_point(x, func(x))
|
||||
|
||||
graph = ParametricFunction(
|
||||
@ -116,13 +141,12 @@ class GraphScene(Scene):
|
||||
def slope_of_tangent(self, *args, **kwargs):
|
||||
return np.tan(self.angle_of_tangent(*args, **kwargs))
|
||||
|
||||
def get_derivative_graph(self, graph, dx = 0.01, color = None):
|
||||
if color is None:
|
||||
color = self.default_derivative_color
|
||||
return self.get_graph(
|
||||
lambda x : self.slope_of_tangent(x, graph, dx) / self.space_unit_to_y,
|
||||
color = color,
|
||||
)
|
||||
def get_derivative_graph(self, graph, dx = 0.01, **kwargs):
|
||||
if "color" not in kwargs:
|
||||
kwargs["color"] = self.default_derivative_color
|
||||
def deriv(x):
|
||||
return self.slope_of_tangent(x, graph, dx) / self.space_unit_to_y
|
||||
return self.get_graph(deriv, **kwargs)
|
||||
|
||||
def get_graph_label(
|
||||
self,
|
||||
|
@ -268,7 +268,8 @@ class Mobject(object):
|
||||
dim = np.argmax(np.abs(vect))
|
||||
buff = kwargs.get("buff", DEFAULT_MOBJECT_TO_EDGE_BUFFER)
|
||||
max_val = space_lengths[dim] - buff
|
||||
if abs(self.get_edge_center(vect)[dim]) > max_val:
|
||||
edge_center = self.get_edge_center(vect)
|
||||
if np.dot(edge_center, vect) > max_val:
|
||||
self.to_edge(vect, **kwargs)
|
||||
return self
|
||||
|
||||
|
@ -135,7 +135,7 @@ class Line(VMobject):
|
||||
|
||||
class DashedLine(Line):
|
||||
CONFIG = {
|
||||
"dashed_segment_length" : 0.15
|
||||
"dashed_segment_length" : 0.05
|
||||
}
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.init_kwargs = kwargs
|
||||
|
Reference in New Issue
Block a user