mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
80% through cube example
This commit is contained in:
parent
25e99ea1bc
commit
b4e93b3376
5 changed files with 693 additions and 25 deletions
|
@ -100,11 +100,16 @@ class DrawBorderThenFill(Animation):
|
|||
Animation.__init__(self, vmobject, **kwargs)
|
||||
|
||||
def update_submobject(self, submobject, starting_submobject, alpha):
|
||||
submobject.pointwise_become_partial(
|
||||
starting_submobject, 0, min(2*alpha, 1)
|
||||
)
|
||||
if alpha < 0.5:
|
||||
submobject.pointwise_become_partial(
|
||||
starting_submobject, 0, 2*alpha
|
||||
)
|
||||
color = self.stroke_color or starting_submobject.get_color()
|
||||
if self.stroke_color:
|
||||
color = self.stroke_color
|
||||
elif starting_submobject.stroke_width > 0:
|
||||
color = starting_submobject.get_stroke_color()
|
||||
else:
|
||||
color = starting_submobject.get_color()
|
||||
submobject.set_stroke(color, width = self.stroke_width)
|
||||
submobject.set_fill(opacity = 0)
|
||||
else:
|
||||
|
|
689
eoc/chapter3.py
689
eoc/chapter3.py
|
@ -195,62 +195,717 @@ class DerivativeOfXSquaredAsGraph(GraphScene, ZoomedScene, PiCreatureScene):
|
|||
class NudgeSideLengthOfSquare(PiCreatureScene):
|
||||
CONFIG = {
|
||||
"square_width" : 3,
|
||||
"dx" : 0.5,
|
||||
"alt_square_width" : 5,
|
||||
"dx" : 0.25,
|
||||
"alt_dx" : 0.01,
|
||||
"square_color" : GREEN,
|
||||
"square_fill_opacity" : 0.75,
|
||||
"three_color" : GREEN,
|
||||
"dx_color" : BLUE_B,
|
||||
"is_recursing_on_dx" : False,
|
||||
"is_recursing_on_square_width" : False,
|
||||
}
|
||||
def construct(self):
|
||||
ApplyMethod(self.pi_creature.change_mode, "speaking").update(1)
|
||||
self.add_function_label()
|
||||
self.introduce_square()
|
||||
self.increase_area()
|
||||
self.write_df_equation()
|
||||
self.highlight_shapes()
|
||||
self.examine_thin_rectangles()
|
||||
self.examine_tiny_square()
|
||||
self.show_smaller_dx()
|
||||
self.rule_of_thumb()
|
||||
self.write_out_derivative()
|
||||
self.shrink_dx()
|
||||
|
||||
def add_function_label(self):
|
||||
label = TexMobject("f(x) = x^2")
|
||||
label.next_to(ORIGIN, RIGHT)
|
||||
label.next_to(ORIGIN, RIGHT, buff = (self.square_width-3)/2.)
|
||||
label.to_edge(UP)
|
||||
self.add(label)
|
||||
self.function_label = label
|
||||
|
||||
def introduce_square(self):
|
||||
square = Square(
|
||||
side_length = self.square_width,
|
||||
stroke_width = 0,
|
||||
fill_opacity = 0.75,
|
||||
fill_color = BLUE,
|
||||
fill_opacity = self.square_fill_opacity,
|
||||
fill_color = self.square_color,
|
||||
)
|
||||
square.to_corner(UP+LEFT, buff = LARGE_BUFF)
|
||||
x_squared = TexMobject("x^2")
|
||||
x_squared.move_to(square)
|
||||
|
||||
braces = VGroup()
|
||||
for vect in DOWN, RIGHT:
|
||||
for vect in RIGHT, DOWN:
|
||||
brace = Brace(square, vect)
|
||||
brace.add(brace.get_text("$x$"))
|
||||
text = brace.get_text("$x$")
|
||||
brace.add(text)
|
||||
braces.add(brace)
|
||||
|
||||
self.play(DrawBorderThenFill(square))
|
||||
self.add(square, x_squared, braces)
|
||||
self.play(
|
||||
DrawBorderThenFill(square),
|
||||
self.pi_creature.change_mode, "plain"
|
||||
)
|
||||
self.play(*map(GrowFromCenter, braces))
|
||||
self.play(Write(x_squared))
|
||||
self.change_mode("pondering")
|
||||
self.dither()
|
||||
|
||||
self.square = square
|
||||
self.side_braces = braces
|
||||
|
||||
def increase_area(self):
|
||||
pass
|
||||
color_kwargs = {
|
||||
"fill_color" : YELLOW,
|
||||
"fill_opacity" : self.square_fill_opacity,
|
||||
"stroke_width" : 0,
|
||||
}
|
||||
right_rect = Rectangle(
|
||||
width = self.dx,
|
||||
height = self.square_width,
|
||||
**color_kwargs
|
||||
)
|
||||
bottom_rect = right_rect.copy().rotate(-np.pi/2)
|
||||
right_rect.next_to(self.square, RIGHT, buff = 0)
|
||||
bottom_rect.next_to(self.square, DOWN, buff = 0)
|
||||
corner_square = Square(
|
||||
side_length = self.dx,
|
||||
**color_kwargs
|
||||
)
|
||||
corner_square.next_to(self.square, DOWN+RIGHT, buff = 0)
|
||||
|
||||
right_line = Line(
|
||||
self.square.get_corner(UP+RIGHT),
|
||||
self.square.get_corner(DOWN+RIGHT),
|
||||
stroke_width = 0
|
||||
)
|
||||
bottom_line = Line(
|
||||
self.square.get_corner(DOWN+RIGHT),
|
||||
self.square.get_corner(DOWN+LEFT),
|
||||
stroke_width = 0
|
||||
)
|
||||
corner_point = VectorizedPoint(
|
||||
self.square.get_corner(DOWN+RIGHT)
|
||||
)
|
||||
|
||||
little_braces = VGroup()
|
||||
for vect in RIGHT, DOWN:
|
||||
brace = Brace(
|
||||
corner_square, vect,
|
||||
buff = SMALL_BUFF,
|
||||
tex_string = "\\underbrace{%s}"%(3*"\\quad"),
|
||||
)
|
||||
text = brace.get_text("$dx$", buff = SMALL_BUFF)
|
||||
text.highlight(self.dx_color)
|
||||
brace.add(text)
|
||||
little_braces.add(brace)
|
||||
|
||||
right_brace, bottom_brace = self.side_braces
|
||||
self.play(
|
||||
Transform(right_line, right_rect),
|
||||
Transform(bottom_line, bottom_rect),
|
||||
Transform(corner_point, corner_square),
|
||||
right_brace.next_to, right_rect, RIGHT, SMALL_BUFF,
|
||||
bottom_brace.next_to, bottom_rect, DOWN, SMALL_BUFF,
|
||||
)
|
||||
self.remove(corner_point, bottom_line, right_line)
|
||||
self.add(corner_square, bottom_rect, right_rect)
|
||||
self.play(*map(GrowFromCenter, little_braces))
|
||||
self.dither()
|
||||
self.play(*it.chain(*[
|
||||
[mob.shift, vect*SMALL_BUFF]
|
||||
for mob, vect in [
|
||||
(right_rect, RIGHT),
|
||||
(bottom_rect, DOWN),
|
||||
(corner_square, DOWN+RIGHT),
|
||||
(right_brace, RIGHT),
|
||||
(bottom_brace, DOWN),
|
||||
(little_braces, DOWN+RIGHT)
|
||||
]
|
||||
]))
|
||||
self.change_mode("thinking")
|
||||
self.dither()
|
||||
self.right_rect = right_rect
|
||||
self.bottom_rect = bottom_rect
|
||||
self.corner_square = corner_square
|
||||
self.little_braces = little_braces
|
||||
|
||||
def write_df_equation(self):
|
||||
right_rect = self.right_rect
|
||||
bottom_rect = self.bottom_rect
|
||||
corner_square = self.corner_square
|
||||
|
||||
df_equation = VGroup(
|
||||
TexMobject("df").highlight(right_rect.get_color()),
|
||||
TexMobject("="),
|
||||
right_rect.copy(),
|
||||
TextMobject("+"),
|
||||
right_rect.copy(),
|
||||
TexMobject("+"),
|
||||
corner_square.copy()
|
||||
)
|
||||
df_equation.arrange_submobjects()
|
||||
df_equation.next_to(
|
||||
self.function_label, DOWN,
|
||||
aligned_edge = LEFT,
|
||||
buff = SMALL_BUFF
|
||||
)
|
||||
df, equals, r1, plus1, r2, plus2, s = df_equation
|
||||
|
||||
pairs = [
|
||||
(df, self.function_label[0]),
|
||||
(r1, right_rect),
|
||||
(r2, bottom_rect),
|
||||
(s, corner_square),
|
||||
]
|
||||
for mover, origin in pairs:
|
||||
mover.save_state()
|
||||
Transform(mover, origin).update(1)
|
||||
self.play(df.restore)
|
||||
self.dither()
|
||||
self.play(
|
||||
*[
|
||||
mob.restore
|
||||
for mob in r1, r2, s
|
||||
]+[
|
||||
Write(symbol)
|
||||
for symbol in equals, plus1, plus2
|
||||
],
|
||||
run_time = 2
|
||||
)
|
||||
self.change_mode("happy")
|
||||
self.dither()
|
||||
|
||||
self.df_equation = df_equation
|
||||
|
||||
def highlight_shapes(self):
|
||||
df, equals, r1, plus1, r2, plus2, s = self.df_equation
|
||||
|
||||
tups = [
|
||||
(self.right_rect, self.bottom_rect, r1, r2),
|
||||
(self.corner_square, s)
|
||||
]
|
||||
for tup in tups:
|
||||
self.play(
|
||||
*it.chain(*[
|
||||
[m.scale_in_place, 1.2, m.highlight, RED]
|
||||
for m in tup
|
||||
]),
|
||||
rate_func = there_and_back
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def examine_thin_rectangles(self):
|
||||
pass
|
||||
df, equals, r1, plus1, r2, plus2, s = self.df_equation
|
||||
|
||||
rects = VGroup(r1, r2)
|
||||
thin_rect_brace = Brace(rects, DOWN)
|
||||
text = thin_rect_brace.get_text("$2x \\, dx$")
|
||||
VGroup(*text[-2:]).highlight(self.dx_color)
|
||||
text.save_state()
|
||||
alt_text = thin_rect_brace.get_text("$2(3)(0.01)$")
|
||||
alt_text[2].highlight(self.three_color)
|
||||
VGroup(*alt_text[-5:-1]).highlight(self.dx_color)
|
||||
|
||||
example_value = TexMobject("=0.06")
|
||||
example_value.next_to(alt_text, DOWN)
|
||||
|
||||
self.play(GrowFromCenter(thin_rect_brace))
|
||||
self.play(
|
||||
Write(text),
|
||||
self.pi_creature.change_mode, "pondering"
|
||||
)
|
||||
self.dither()
|
||||
|
||||
xs = VGroup(*[
|
||||
brace[-1]
|
||||
for brace in self.side_braces
|
||||
])
|
||||
dxs = VGroup(*[
|
||||
brace[-1]
|
||||
for brace in self.little_braces
|
||||
])
|
||||
for group, tex, color in (xs, "3", self.three_color), (dxs, "0.01", self.dx_color):
|
||||
group.save_state()
|
||||
group.generate_target()
|
||||
for submob in group.target:
|
||||
number = TexMobject(tex)
|
||||
number.highlight(color)
|
||||
number.move_to(submob, LEFT)
|
||||
Transform(submob, number).update(1)
|
||||
self.play(MoveToTarget(xs))
|
||||
self.play(MoveToTarget(dxs))
|
||||
self.dither()
|
||||
self.play(Transform(text, alt_text))
|
||||
self.dither()
|
||||
self.play(Write(example_value))
|
||||
self.dither()
|
||||
self.play(
|
||||
FadeOut(example_value),
|
||||
*[
|
||||
mob.restore
|
||||
for mob in xs, dxs, text
|
||||
]
|
||||
)
|
||||
self.remove(text)
|
||||
text.restore()
|
||||
self.add(text)
|
||||
|
||||
self.dither()
|
||||
self.dxs = dxs
|
||||
self.thin_rect_brace = thin_rect_brace
|
||||
self.thin_rect_area = text
|
||||
|
||||
def examine_tiny_square(self):
|
||||
pass
|
||||
text = TexMobject("dx^2")
|
||||
VGroup(*text[:2]).highlight(self.dx_color)
|
||||
text.next_to(self.df_equation[-1], UP)
|
||||
text.save_state()
|
||||
alt_text = TextMobject("0.0001")
|
||||
alt_text.move_to(text)
|
||||
|
||||
self.play(Write(text))
|
||||
self.change_mode("surprised")
|
||||
self.dither()
|
||||
self.play(
|
||||
MoveToTarget(self.dxs),
|
||||
self.pi_creature.change_mode, "plain"
|
||||
)
|
||||
for submob in self.dxs.target:
|
||||
number = TexMobject("0.01")
|
||||
number.highlight(self.dx_color)
|
||||
number.move_to(submob, LEFT)
|
||||
Transform(submob, number).update(1)
|
||||
self.play(MoveToTarget(self.dxs))
|
||||
self.play(
|
||||
Transform(text, alt_text),
|
||||
self.pi_creature.change_mode, "raise_right_hand"
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(*[
|
||||
mob.restore
|
||||
for mob in self.dxs, text
|
||||
] + [
|
||||
self.pi_creature.change_mode, "erm"
|
||||
])
|
||||
self.dx_squared = text
|
||||
|
||||
def show_smaller_dx(self):
|
||||
self.mobjects_at_start_of_show_smaller_dx = [
|
||||
mob.copy() for mob in self.get_mobjects()
|
||||
]
|
||||
if self.is_recursing_on_dx:
|
||||
return
|
||||
|
||||
alt_scene = self.__class__(
|
||||
skip_animations = True,
|
||||
dx = self.alt_dx,
|
||||
is_recursing_on_dx = True
|
||||
)
|
||||
for mob in self.get_mobjects():
|
||||
mob.save_state()
|
||||
self.play(*[
|
||||
Transform(*pair)
|
||||
for pair in zip(
|
||||
self.get_mobjects(),
|
||||
alt_scene.mobjects_at_start_of_show_smaller_dx,
|
||||
)
|
||||
])
|
||||
self.dither()
|
||||
self.play(*[
|
||||
mob.restore
|
||||
for mob in self.get_mobjects()
|
||||
])
|
||||
self.change_mode("happy")
|
||||
self.dither()
|
||||
|
||||
def rule_of_thumb(self):
|
||||
circle = Circle(color = RED)
|
||||
dx_squared_group = VGroup(self.dx_squared, self.df_equation[-1])
|
||||
circle.replace(dx_squared_group, stretch = True)
|
||||
dx_squared_group.add(self.df_equation[-2])
|
||||
circle.scale_in_place(1.5)
|
||||
safe_to_ignore = TextMobject("Safe to ignore")
|
||||
safe_to_ignore.next_to(circle, DOWN, aligned_edge = LEFT)
|
||||
safe_to_ignore.highlight(circle.get_color())
|
||||
|
||||
self.play(ShowCreation(circle))
|
||||
self.play(
|
||||
Write(safe_to_ignore, run_time = 2),
|
||||
self.pi_creature.change_mode, "raise_right_hand"
|
||||
)
|
||||
self.play(
|
||||
FadeOut(circle),
|
||||
FadeOut(safe_to_ignore),
|
||||
dx_squared_group.fade, 0.5,
|
||||
dx_squared_group.to_corner, UP+RIGHT,
|
||||
self.pi_creature.change_mode, "plain"
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def write_out_derivative(self):
|
||||
pass
|
||||
df, equals, r1, plus1, r2, plus2, s = self.df_equation
|
||||
frac_line = TexMobject("-")
|
||||
frac_line.stretch_to_fit_width(df.get_width())
|
||||
frac_line.move_to(df)
|
||||
dx = VGroup(*self.thin_rect_area[-2:])
|
||||
x = self.thin_rect_area[1]
|
||||
|
||||
self.play(
|
||||
Transform(r1, self.right_rect),
|
||||
Transform(r2, self.bottom_rect),
|
||||
FadeOut(plus1),
|
||||
FadeOut(self.thin_rect_brace)
|
||||
)
|
||||
self.play(
|
||||
self.thin_rect_area.next_to, VGroup(df, equals),
|
||||
RIGHT, MED_SMALL_BUFF, UP,
|
||||
self.pi_creature.change_mode, "thinking"
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(
|
||||
ApplyMethod(df.next_to, frac_line, UP, SMALL_BUFF),
|
||||
ApplyMethod(dx.next_to, frac_line, DOWN, SMALL_BUFF),
|
||||
Write(frac_line),
|
||||
path_arc = -np.pi
|
||||
)
|
||||
self.dither()
|
||||
|
||||
brace_xs = [
|
||||
brace[-1]
|
||||
for brace in self.side_braces
|
||||
]
|
||||
xs = list(brace_xs) + [x]
|
||||
for x_mob in xs:
|
||||
number = TexMobject("(%d)"%self.square_width)
|
||||
number.move_to(x_mob, LEFT)
|
||||
number.shift(
|
||||
(x_mob.get_bottom()[1] - number[1].get_bottom()[1])*UP
|
||||
)
|
||||
x_mob.save_state()
|
||||
x_mob.target = number
|
||||
self.play(*map(MoveToTarget, xs))
|
||||
self.dither(2)
|
||||
|
||||
#Recursively transform to what would have happened
|
||||
#with a wider square width
|
||||
self.mobjects_at_end_of_write_out_derivative = self.get_mobjects()
|
||||
if self.is_recursing_on_square_width or self.is_recursing_on_dx:
|
||||
return
|
||||
alt_scene = self.__class__(
|
||||
skip_animations = True,
|
||||
square_width = self.alt_square_width,
|
||||
is_recursing_on_square_width = True,
|
||||
)
|
||||
self.play(*[
|
||||
Transform(*pair)
|
||||
for pair in zip(
|
||||
self.mobjects_at_end_of_write_out_derivative,
|
||||
alt_scene.mobjects_at_end_of_write_out_derivative
|
||||
)
|
||||
])
|
||||
self.change_mode("happy")
|
||||
self.dither(2)
|
||||
|
||||
class NudgeSideLengthOfCube(Scene):
|
||||
CONFIG = {
|
||||
"x_color" : BLUE,
|
||||
"dx_color" : GREEN,
|
||||
"df_color" : YELLOW,
|
||||
"use_morty" : False,
|
||||
"x" : 3,
|
||||
"dx" : 0.2,
|
||||
"alt_dx" : 0.02,
|
||||
"offset_vect" : OUT,
|
||||
"pose_angle" : np.pi/12,
|
||||
"pose_axis" : UP+RIGHT,
|
||||
"small_piece_scaling_factor" : 0.7,
|
||||
"is_recursing" : False,
|
||||
}
|
||||
def construct(self):
|
||||
self.add_title()
|
||||
self.introduce_cube()
|
||||
self.write_df_equation()
|
||||
|
||||
def add_title(self):
|
||||
title = TexMobject("f(x) = x^3")
|
||||
title.shift(SPACE_WIDTH*LEFT/2)
|
||||
title.to_edge(UP)
|
||||
self.play(Write(title))
|
||||
self.dither()
|
||||
|
||||
def introduce_cube(self):
|
||||
cube = self.get_cube()
|
||||
cube.to_edge(LEFT, buff = 2*LARGE_BUFF)
|
||||
cube.shift(DOWN)
|
||||
|
||||
dv_pieces = self.get_dv_pices(cube)
|
||||
original_dx = self.dx
|
||||
self.dx = 0
|
||||
alt_dv_pieces = self.get_dv_pices(cube)
|
||||
self.dx = original_dx
|
||||
alt_dv_pieces.set_fill(opacity = 0)
|
||||
|
||||
x_brace = Brace(cube, LEFT, buff = SMALL_BUFF)
|
||||
dx_brace = Brace(
|
||||
dv_pieces[1], LEFT, buff = SMALL_BUFF,
|
||||
tex_string = "\\underbrace{%s}"%(3*"\\quad"),
|
||||
)
|
||||
dx_brace.stretch_in_place(1.5, 1)
|
||||
for brace, tex in (x_brace, "x"), (dx_brace, "dx"):
|
||||
brace.scale_in_place(0.95)
|
||||
brace.rotate_in_place(-np.pi/96)
|
||||
brace.shift(0.3*(UP+LEFT))
|
||||
brace.add(brace.get_text("$%s$"%tex))
|
||||
|
||||
|
||||
cube_group = VGroup(cube, dv_pieces, alt_dv_pieces)
|
||||
self.pose_3d_mobject(cube_group)
|
||||
|
||||
self.play(DrawBorderThenFill(cube))
|
||||
self.play(GrowFromCenter(x_brace))
|
||||
self.dither()
|
||||
self.play(Transform(alt_dv_pieces, dv_pieces))
|
||||
self.remove(alt_dv_pieces)
|
||||
self.add(dv_pieces)
|
||||
self.play(GrowFromCenter(dx_brace))
|
||||
self.dither()
|
||||
self.play(*[
|
||||
ApplyMethod(
|
||||
piece.shift,
|
||||
0.5*(piece.get_center()-cube.get_center())
|
||||
)
|
||||
for piece in dv_pieces
|
||||
]+[
|
||||
ApplyMethod(dx_brace.shift, 0.7*UP)
|
||||
])
|
||||
self.dither()
|
||||
|
||||
self.cube = cube
|
||||
self.faces, self.bars, self.corner_cube = [
|
||||
VGroup(*[
|
||||
piece
|
||||
for piece in dv_pieces
|
||||
if piece.type == target_type
|
||||
])
|
||||
for target_type in "face", "bar", "corner_cube"
|
||||
]
|
||||
|
||||
def write_df_equation(self):
|
||||
df_equation = VGroup(
|
||||
TexMobject("df"),
|
||||
TexMobject("="),
|
||||
self.organize_faces(self.faces.copy()),
|
||||
TexMobject("+"),
|
||||
self.organize_bars(self.bars.copy()),
|
||||
TexMobject("+"),
|
||||
self.corner_cube.copy()
|
||||
)
|
||||
df, equals, faces, plus1, bars, plus2, corner_cube = df_equation
|
||||
df.highlight(self.df_color)
|
||||
for three_d_mob in faces, bars, corner_cube:
|
||||
three_d_mob.scale(self.small_piece_scaling_factor)
|
||||
# self.pose_3d_mobject(three_d_mob)
|
||||
faces.set_fill(opacity = 0.3)
|
||||
df_equation.arrange_submobjects(RIGHT)
|
||||
df_equation.next_to(ORIGIN, RIGHT)
|
||||
df_equation.to_edge(UP)
|
||||
|
||||
faces_brace = Brace(faces, DOWN)
|
||||
faces_brace_text = faces_brace.get_text("$3x^2", "\\, dx$")
|
||||
extras_brace = Brace(VGroup(bars, corner_cube), DOWN)
|
||||
ignore_text = extras_brace.get_text(
|
||||
"Multiple \\\\ of $dx^2$"
|
||||
)
|
||||
ignore_text.scale_in_place(0.7)
|
||||
x_squared_dx = TexMobject("x^2", "\\, dx")
|
||||
|
||||
|
||||
self.play(*map(Write, [df, equals]))
|
||||
self.grab_pieces(self.faces, faces)
|
||||
self.dither()
|
||||
# self.shrink_dx()
|
||||
face = self.faces[0]
|
||||
face.save_state()
|
||||
self.play(face.shift, SPACE_WIDTH*RIGHT)
|
||||
x_squared_dx.move_to(self.faces[0])
|
||||
self.play(Write(x_squared_dx, run_time = 1))
|
||||
for submob in x_squared_dx:
|
||||
self.play(submob.highlight, RED, rate_func = there_and_back)
|
||||
self.play(submob.highlight, RED, rate_func = there_and_back)
|
||||
self.dither()
|
||||
self.play(
|
||||
face.restore,
|
||||
Transform(x_squared_dx, faces_brace_text),
|
||||
GrowFromCenter(faces_brace)
|
||||
)
|
||||
self.dither()
|
||||
self.grab_pieces(self.bars, bars, plus1)
|
||||
self.grab_pieces(self.corner_cube, corner_cube, plus2)
|
||||
self.play(
|
||||
GrowFromCenter(extras_brace),
|
||||
Write(ignore_text)
|
||||
)
|
||||
self.dither()
|
||||
self.play(*[
|
||||
ApplyMethod(mob.fade, 0.7)
|
||||
for mob in [
|
||||
plus1, bars, plus2, corner_cube,
|
||||
extras_brace, ignore_text
|
||||
]
|
||||
])
|
||||
self.dither()
|
||||
|
||||
def grab_pieces(self, start_pieces, end_pices, to_write = None):
|
||||
for piece in start_pieces:
|
||||
piece.generate_target()
|
||||
piece.target.rotate_in_place(
|
||||
np.pi/12, piece.get_center()-self.cube.get_center()
|
||||
)
|
||||
piece.target.highlight(RED)
|
||||
self.play(*map(MoveToTarget, start_pieces), rate_func = wiggle)
|
||||
self.dither()
|
||||
added_anims = []
|
||||
if to_write is not None:
|
||||
added_anims.append(Write(to_write))
|
||||
self.play(
|
||||
Transform(start_pieces.copy(), end_pices),
|
||||
*added_anims
|
||||
)
|
||||
|
||||
def shrink_dx(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
self.mobjects_at_start_of_shrink_dx = self.get_mobjects()
|
||||
if self.is_recursing:
|
||||
return
|
||||
alt_scene = self.__class__(
|
||||
dx = self.alt_dx,
|
||||
skip_animations = True,
|
||||
is_recursing = True
|
||||
)
|
||||
for mob in self.get_mobjects():
|
||||
mob.save_state()
|
||||
self.play(*[
|
||||
Transform(*pair)
|
||||
for pair in zip(
|
||||
self.get_mobjects(),
|
||||
alt_scene.mobjects_at_start_of_shrink_dx
|
||||
)
|
||||
])
|
||||
self.dither()
|
||||
self.play(*[
|
||||
mob.restore
|
||||
for mob in self.get_mobjects()
|
||||
])
|
||||
|
||||
def get_cube(self):
|
||||
cube = self.get_prism(self.x, self.x, self.x)
|
||||
cube.set_fill(color = BLUE, opacity = 0.3)
|
||||
cube.set_stroke(color = WHITE, width = 1)
|
||||
return cube
|
||||
|
||||
def get_dv_pices(self, cube):
|
||||
pieces = VGroup()
|
||||
for vect in it.product([0, 1], [0, 1], [0, 1]):
|
||||
if np.all(vect == ORIGIN):
|
||||
continue
|
||||
args = [
|
||||
self.x if bit is 0 else self.dx
|
||||
for bit in vect
|
||||
]
|
||||
piece = self.get_prism(*args)
|
||||
piece.next_to(cube, np.array(vect), buff = 0)
|
||||
pieces.add(piece)
|
||||
if sum(vect) == 1:
|
||||
piece.type = "face"
|
||||
elif sum(vect) == 2:
|
||||
piece.type = "bar"
|
||||
else:
|
||||
piece.type = "corner_cube"
|
||||
|
||||
return pieces
|
||||
|
||||
def organize_faces(self, faces):
|
||||
self.unpose_3d_mobject(faces)
|
||||
for face in faces:
|
||||
dimensions = [
|
||||
face.length_over_dim(dim)
|
||||
for dim in range(3)
|
||||
]
|
||||
thin_dim = np.argmin(dimensions)
|
||||
if thin_dim == 0:
|
||||
face.rotate(np.pi/2, DOWN)
|
||||
elif thin_dim == 1:
|
||||
face.rotate(np.pi/2, RIGHT)
|
||||
faces.arrange_submobjects(OUT, buff = LARGE_BUFF)
|
||||
self.pose_3d_mobject(faces)
|
||||
return faces
|
||||
|
||||
def organize_bars(self, bars):
|
||||
self.unpose_3d_mobject(bars)
|
||||
for bar in bars:
|
||||
dimensions = [
|
||||
bar.length_over_dim(dim)
|
||||
for dim in range(3)
|
||||
]
|
||||
thick_dim = np.argmax(dimensions)
|
||||
if thick_dim == 0:
|
||||
bar.rotate(np.pi/2, OUT)
|
||||
elif thick_dim == 2:
|
||||
bar.rotate(np.pi/2, LEFT)
|
||||
bars.arrange_submobjects(OUT, buff = LARGE_BUFF)
|
||||
self.pose_3d_mobject(bars)
|
||||
return bars
|
||||
|
||||
def get_corner_cube(self):
|
||||
return self.get_prism(self.dx, self.dx, self.dx)
|
||||
|
||||
|
||||
def get_prism(self, width, height, depth):
|
||||
color_kwargs = {
|
||||
"fill_color" : YELLOW,
|
||||
"fill_opacity" : 0.4,
|
||||
"stroke_color" : WHITE,
|
||||
"stroke_width" : 0.1,
|
||||
}
|
||||
front = Rectangle(
|
||||
width = width,
|
||||
height = height,
|
||||
**color_kwargs
|
||||
)
|
||||
face = VGroup(front)
|
||||
for vect in LEFT, RIGHT, UP, DOWN:
|
||||
if vect is LEFT or vect is RIGHT:
|
||||
side = Rectangle(
|
||||
height = height,
|
||||
width = depth,
|
||||
**color_kwargs
|
||||
)
|
||||
else:
|
||||
side = Rectangle(
|
||||
height = depth,
|
||||
width = width,
|
||||
**color_kwargs
|
||||
)
|
||||
side.next_to(front, vect, buff = 0)
|
||||
side.rotate(
|
||||
np.pi/2, rotate_vector(vect, -np.pi/2),
|
||||
about_point = front.get_edge_center(vect)
|
||||
)
|
||||
face.add(side)
|
||||
return face
|
||||
|
||||
def pose_3d_mobject(self, mobject):
|
||||
mobject.rotate_in_place(self.pose_angle, self.pose_axis)
|
||||
return mobject
|
||||
|
||||
def unpose_3d_mobject(self, mobject):
|
||||
mobject.rotate_in_place(-self.pose_angle, self.pose_axis)
|
||||
return mobject
|
||||
|
||||
class ShowCubeDVIn3D(Scene):
|
||||
def construct(self):
|
||||
raise Exception("This scene is only here for the stage_scenes script.")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -309,6 +309,12 @@ class Mobject(object):
|
|||
def scale_to_fit_height(self, height):
|
||||
return self.stretch_to_fit(height, 1, stretch = False)
|
||||
|
||||
def space_out_submobjects(self, factor = 1.5):
|
||||
self.scale_in_place(factor)
|
||||
for submob in self.submobjects:
|
||||
submob.scale_in_place(1./factor)
|
||||
return self
|
||||
|
||||
def move_to(self, point_or_mobject, aligned_edge = ORIGIN):
|
||||
if isinstance(point_or_mobject, Mobject):
|
||||
target = point_or_mobject.get_critical_point(aligned_edge)
|
||||
|
@ -450,7 +456,7 @@ class Mobject(object):
|
|||
if use_submobject:
|
||||
return self.get_submobject_critical_point(direction)
|
||||
result = np.zeros(self.dim)
|
||||
for dim in [0, 1]:
|
||||
for dim in range(self.dim):
|
||||
if direction[dim] <= 0:
|
||||
min_point = self.reduce_across_dimension(np.min, np.min, dim)
|
||||
if direction[dim] >= 0:
|
||||
|
|
|
@ -130,11 +130,12 @@ class TextMobject(TexMobject):
|
|||
class Brace(TexMobject):
|
||||
CONFIG = {
|
||||
"buff" : 0.2,
|
||||
"n_quads" : 3,
|
||||
"tex_string" : "\\underbrace{%s}"%(3*"\\qquad"),
|
||||
}
|
||||
TEX_STRING = "\\underbrace{%s}"%(3*"\\qquad")
|
||||
def __init__(self, mobject, direction = DOWN, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
TexMobject.__init__(self, self.TEX_STRING, **kwargs)
|
||||
TexMobject.__init__(self, self.tex_string, **kwargs)
|
||||
angle = -np.arctan2(*direction[:2]) + np.pi
|
||||
mobject.rotate(-angle)
|
||||
left = mobject.get_corner(DOWN+LEFT)
|
||||
|
|
|
@ -268,6 +268,7 @@ class PiCreatureScene(Scene):
|
|||
CONFIG = {
|
||||
"total_dither_time" : 0,
|
||||
"use_morty" : True,
|
||||
"seconds_to_blink" : 3,
|
||||
}
|
||||
def setup(self):
|
||||
self.pi_creature = self.get_pi_creature()
|
||||
|
@ -326,7 +327,7 @@ class PiCreatureScene(Scene):
|
|||
|
||||
def dither(self, time = 1, blink = True):
|
||||
while time > 0:
|
||||
if blink and self.total_dither_time%2 == 1:
|
||||
if blink and self.total_dither_time%self.seconds_to_blink == 1:
|
||||
self.play(Blink(self.pi_creature))
|
||||
else:
|
||||
Scene.dither(self, time)
|
||||
|
|
Loading…
Add table
Reference in a new issue