mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Preliminary end to chapter 3 animations
This commit is contained in:
parent
fe218ec593
commit
983f895f11
7 changed files with 733 additions and 172 deletions
|
@ -50,7 +50,6 @@ class ShowCreation(ShowPartial):
|
||||||
|
|
||||||
class Write(ShowCreation):
|
class Write(ShowCreation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"run_time" : 3,
|
|
||||||
"rate_func" : None,
|
"rate_func" : None,
|
||||||
"submobject_mode" : "lagged_start",
|
"submobject_mode" : "lagged_start",
|
||||||
}
|
}
|
||||||
|
@ -59,8 +58,20 @@ class Write(ShowCreation):
|
||||||
mobject = TextMobject(mob_or_text)
|
mobject = TextMobject(mob_or_text)
|
||||||
else:
|
else:
|
||||||
mobject = mob_or_text
|
mobject = mob_or_text
|
||||||
|
if "run_time" not in kwargs:
|
||||||
|
self.establish_run_time(mobject)
|
||||||
ShowCreation.__init__(self, mobject, **kwargs)
|
ShowCreation.__init__(self, mobject, **kwargs)
|
||||||
|
|
||||||
|
def establish_run_time(self, mobject):
|
||||||
|
num_subs = len(mobject.family_members_with_points())
|
||||||
|
if num_subs < 5:
|
||||||
|
self.run_time = 1
|
||||||
|
elif num_subs < 15:
|
||||||
|
self.run_time = 2
|
||||||
|
else:
|
||||||
|
self.run_time = 3
|
||||||
|
|
||||||
|
|
||||||
class ShowPassingFlash(ShowPartial):
|
class ShowPassingFlash(ShowPartial):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"time_width" : 0.1
|
"time_width" : 0.1
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Transform(Animation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"path_arc" : 0,
|
"path_arc" : 0,
|
||||||
"path_func" : None,
|
"path_func" : None,
|
||||||
|
"submobject_mode" : "all_at_once",
|
||||||
}
|
}
|
||||||
def __init__(self, mobject, ending_mobject, **kwargs):
|
def __init__(self, mobject, ending_mobject, **kwargs):
|
||||||
#Copy ending_mobject so as to not mess with caller
|
#Copy ending_mobject so as to not mess with caller
|
||||||
|
|
843
eola/chapter3.py
843
eola/chapter3.py
|
@ -80,43 +80,324 @@ class Introduction(TeacherStudentsScene):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
class ThreePerspectives(Scene):
|
class MatrixVectorMechanicalMultiplication(NumericalMatrixMultiplication):
|
||||||
|
CONFIG = {
|
||||||
|
"left_matrix" : [[1, -3], [2, 4]],
|
||||||
|
"right_matrix" : [[5], [7]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class PostponeHigherDimensions(TeacherStudentsScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
title = TextMobject("Linear transformations")
|
self.setup()
|
||||||
|
self.student_says("What about 3 dimensions?")
|
||||||
|
self.random_blink()
|
||||||
|
self.teacher_says("All in due time,\\\\ young padawan")
|
||||||
|
self.random_blink()
|
||||||
|
|
||||||
|
class DescribeTransformation(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add_title()
|
||||||
|
self.show_function()
|
||||||
|
|
||||||
|
def add_title(self):
|
||||||
|
title = TextMobject(["Linear", "transformation"])
|
||||||
title.to_edge(UP)
|
title.to_edge(UP)
|
||||||
title.highlight(YELLOW)
|
linear, transformation = title.split()
|
||||||
self.add(title)
|
brace = Brace(transformation, DOWN)
|
||||||
|
function = TextMobject("function").next_to(brace, DOWN)
|
||||||
|
function.highlight(YELLOW)
|
||||||
|
|
||||||
words = VMobject(*map(TextMobject, [
|
self.play(Write(title))
|
||||||
"1. Geometric perspective",
|
|
||||||
"2. Numerical computations",
|
|
||||||
"3. Abstract definition"
|
|
||||||
]))
|
|
||||||
words.arrange_submobjects(DOWN, buff = 0.5, aligned_edge = LEFT)
|
|
||||||
words.to_edge(LEFT, buff = 2)
|
|
||||||
for word in words.split():
|
|
||||||
self.play(Write(word), run_time = 2)
|
|
||||||
self.dither()
|
self.dither()
|
||||||
for word in words.split():
|
self.play(
|
||||||
all_else = self.get_mobjects()
|
GrowFromCenter(brace),
|
||||||
all_else.remove(word)
|
Write(function),
|
||||||
all_else_copies = [mob.copy() for mob in all_else]
|
ApplyMethod(linear.fade)
|
||||||
self.play(*[ApplyMethod(mob.fade, 0.7) for mob in all_else])
|
)
|
||||||
self.dither()
|
|
||||||
self.play(*[Transform(*pair) for pair in zip(all_else, all_else_copies)])
|
|
||||||
|
|
||||||
class ShowGridCreation(Scene):
|
def show_function(self):
|
||||||
|
f_of_x = TexMobject("f(x)")
|
||||||
|
L_of_v = TexMobject("L(\\vec{\\textbf{v}})")
|
||||||
|
nums = [5, 2, -3]
|
||||||
|
num_inputs = VMobject(*map(TexMobject, map(str, nums)))
|
||||||
|
num_outputs = VMobject(*[
|
||||||
|
TexMobject(str(num**2))
|
||||||
|
for num in nums
|
||||||
|
])
|
||||||
|
for mob in num_inputs, num_outputs:
|
||||||
|
mob.arrange_submobjects(DOWN, buff = 1)
|
||||||
|
num_inputs.next_to(f_of_x, LEFT, buff = 1)
|
||||||
|
num_outputs.next_to(f_of_x, RIGHT, buff = 1)
|
||||||
|
f_point = VectorizedPoint(f_of_x.get_center())
|
||||||
|
|
||||||
|
input_vect = Matrix([5, 7])
|
||||||
|
input_vect.next_to(L_of_v, LEFT, buff = 1)
|
||||||
|
output_vect = Matrix([2, -3])
|
||||||
|
output_vect.next_to(L_of_v, RIGHT, buff = 1)
|
||||||
|
|
||||||
|
vector_input_words = TextMobject("Vector input")
|
||||||
|
vector_input_words.highlight(MAROON_C)
|
||||||
|
vector_input_words.next_to(input_vect, DOWN)
|
||||||
|
vector_output_words = TextMobject("Vector output")
|
||||||
|
vector_output_words.highlight(BLUE)
|
||||||
|
vector_output_words.next_to(output_vect, DOWN)
|
||||||
|
|
||||||
|
self.play(Write(f_of_x, run_time = 1))
|
||||||
|
self.play(Write(num_inputs, run_time = 2))
|
||||||
|
self.dither()
|
||||||
|
for mob in f_point, num_outputs:
|
||||||
|
self.play(Transform(
|
||||||
|
num_inputs, mob,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
FadeOut(num_inputs),
|
||||||
|
Transform(f_of_x, L_of_v)
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Write(input_vect),
|
||||||
|
Write(vector_input_words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
for mob in f_point, output_vect:
|
||||||
|
self.play(Transform(
|
||||||
|
input_vect, mob,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.play(Write(vector_output_words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class WhyConfuseWithTerminology(TeacherStudentsScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
plane = NumberPlane()
|
self.setup()
|
||||||
coords = VMobject(*plane.get_coordinate_labels())
|
self.student_says("Why confuse us with \\\\ redundant terminology?")
|
||||||
self.play(ShowCreation(plane, run_time = 3))
|
self.play(*[
|
||||||
self.play(Write(coords, run_time = 3))
|
ApplyMethod(self.get_students()[i].change_mode, "confused")
|
||||||
|
for i in 0, 2
|
||||||
|
])
|
||||||
|
self.random_blink()
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThinkinfOfFunctionsAsGraphs(VectorScene):
|
||||||
|
def construct(self):
|
||||||
|
axes = self.add_axes()
|
||||||
|
graph = FunctionGraph(lambda x : x**2, x_min = -2, x_max = 2)
|
||||||
|
name = TexMobject("f(x) = x^2")
|
||||||
|
name.next_to(graph, RIGHT).to_edge(UP)
|
||||||
|
point = Dot(graph.point_from_proportion(0.8))
|
||||||
|
point_label = TexMobject("(2, f(2))")
|
||||||
|
point_label.next_to(point.get_center(), DOWN+RIGHT, buff = 0.1)
|
||||||
|
|
||||||
|
self.play(ShowCreation(graph))
|
||||||
|
self.play(Write(name, run_time = 1))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(point),
|
||||||
|
Write(point_label),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def collapse_func(p):
|
||||||
|
return np.dot(p, [RIGHT, RIGHT, OUT]) + (SPACE_HEIGHT+1)*DOWN
|
||||||
|
self.play(
|
||||||
|
ApplyPointwiseFunction(collapse_func, axes),
|
||||||
|
ApplyPointwiseFunction(collapse_func, graph),
|
||||||
|
ApplyMethod(point.shift, 10*DOWN),
|
||||||
|
ApplyMethod(point_label.shift, 10*DOWN),
|
||||||
|
ApplyPointwiseFunction(collapse_func, name),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.clear()
|
||||||
|
words = TextMobject(["Instead think about", "\\emph{movement}"])
|
||||||
|
words.split()[-1].highlight(YELLOW)
|
||||||
|
self.play(Write(words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TransformJustOneVector(VectorScene):
|
||||||
|
def construct(self):
|
||||||
|
self.lock_in_faded_grid()
|
||||||
|
v1_coords = [-3, 1]
|
||||||
|
t_matrix = [[0, -1], [2, -1]]
|
||||||
|
v1 = Vector(v1_coords)
|
||||||
|
v2 = Vector(
|
||||||
|
np.dot(np.array(t_matrix).transpose(), v1_coords),
|
||||||
|
color = PINK
|
||||||
|
)
|
||||||
|
for v, word in (v1, "Input"), (v2, "Output"):
|
||||||
|
v.label = TextMobject("%s vector"%word)
|
||||||
|
v.label.next_to(v.get_end(), UP)
|
||||||
|
v.label.highlight(v.get_color())
|
||||||
|
self.play(ShowCreation(v))
|
||||||
|
self.play(Write(v.label))
|
||||||
|
self.dither()
|
||||||
|
self.remove(v2)
|
||||||
|
self.play(
|
||||||
|
Transform(
|
||||||
|
v1.copy(), v2,
|
||||||
|
path_arc = -np.pi/2, run_time = 3
|
||||||
|
),
|
||||||
|
ApplyMethod(v1.fade)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TransformManyVectors(VectorScene):
|
||||||
|
CONFIG = {
|
||||||
|
"transposed_matrix" : [[2, 1], [1, 2]],
|
||||||
|
"use_dots" : False,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.lock_in_faded_grid()
|
||||||
|
vectors = VMobject(*[
|
||||||
|
Vector([x, y])
|
||||||
|
for x in np.arange(-int(SPACE_WIDTH)+0.5, int(SPACE_WIDTH)+0.5)
|
||||||
|
for y in np.arange(-int(SPACE_HEIGHT)+0.5, int(SPACE_HEIGHT)+0.5)
|
||||||
|
])
|
||||||
|
vectors.submobject_gradient_highlight(PINK, YELLOW)
|
||||||
|
t_matrix = self.transposed_matrix
|
||||||
|
transformed_vectors = VMobject(*[
|
||||||
|
Vector(
|
||||||
|
np.dot(np.array(t_matrix).transpose(), v.get_end()[:2]),
|
||||||
|
color = v.get_color()
|
||||||
|
)
|
||||||
|
for v in vectors.split()
|
||||||
|
])
|
||||||
|
|
||||||
|
self.play(ShowCreation(vectors, submobject_mode = "lagged_start"))
|
||||||
|
self.dither()
|
||||||
|
if self.use_dots:
|
||||||
|
self.play(Transform(
|
||||||
|
vectors, self.vectors_to_dots(vectors),
|
||||||
|
run_time = 3,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
transformed_vectors = self.vectors_to_dots(transformed_vectors)
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(
|
||||||
|
vectors, transformed_vectors,
|
||||||
|
run_time = 3,
|
||||||
|
path_arc = -np.pi/2
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
if self.use_dots:
|
||||||
|
self.play(Transform(
|
||||||
|
vectors, self.dots_to_vectors(vectors),
|
||||||
|
run_time = 2,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def vectors_to_dots(self, vectors):
|
||||||
|
return VMobject(*[
|
||||||
|
Dot(v.get_end(), color = v.get_color())
|
||||||
|
for v in vectors.split()
|
||||||
|
])
|
||||||
|
|
||||||
|
def dots_to_vectors(self, dots):
|
||||||
|
return VMobject(*[
|
||||||
|
Vector(dot.get_center(), color = dot.get_color())
|
||||||
|
for dot in dots.split()
|
||||||
|
])
|
||||||
|
|
||||||
|
class TransformManyVectorsAsPoints(TransformManyVectors):
|
||||||
|
CONFIG = {
|
||||||
|
"use_dots" : True
|
||||||
|
}
|
||||||
|
|
||||||
|
class TransformInfiniteGrid(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"include_background_plane" : False,
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : 2*SPACE_WIDTH,
|
||||||
|
"y_radius" : 2*SPACE_HEIGHT,
|
||||||
|
},
|
||||||
|
"show_basis_vectors" : False
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.play(ShowCreation(
|
||||||
|
self.plane, run_time = 3, submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([[2, 1], [1, 2]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TransformInfiniteGridWithBackground(TransformInfiniteGrid):
|
||||||
|
CONFIG = {
|
||||||
|
"include_background_plane" : True,
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : 2*SPACE_WIDTH,
|
||||||
|
"y_radius" : 2*SPACE_HEIGHT,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApplyComplexFunction(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"function" : lambda z : 0.5*z**2,
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : SPACE_WIDTH,
|
||||||
|
"y_radius" : SPACE_HEIGHT,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.plane.prepare_for_nonlinear_transform(100)
|
||||||
|
self.dither()
|
||||||
|
self.play(ApplyMethod(
|
||||||
|
self.plane.apply_complex_function, self.function,
|
||||||
|
run_time = 5,
|
||||||
|
path_arc = np.pi/2
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ExponentialTransformation(ApplyComplexFunction):
|
||||||
|
CONFIG = {
|
||||||
|
"function" : np.exp,
|
||||||
|
}
|
||||||
|
|
||||||
|
class CrazyTransformation(ApplyComplexFunction):
|
||||||
|
CONFIG = {
|
||||||
|
"function" : lambda z : np.sin(z)**2 + np.sinh(z)
|
||||||
|
}
|
||||||
|
|
||||||
|
class LookToWordLinear(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject(["Linear ", "transformations"])
|
||||||
|
title.to_edge(UP)
|
||||||
|
faded_title = title.copy().fade()
|
||||||
|
linear, transformation = title.split()
|
||||||
|
faded_linear, faded_transformation = faded_title.split()
|
||||||
|
linear_brace = Brace(linear, DOWN)
|
||||||
|
transformation_brace = Brace(transformation, DOWN)
|
||||||
|
function = TextMobject("function")
|
||||||
|
function.highlight(YELLOW)
|
||||||
|
function.next_to(transformation_brace, DOWN)
|
||||||
|
new_sub_word = TextMobject("What does this mean?")
|
||||||
|
new_sub_word.highlight(BLUE)
|
||||||
|
new_sub_word.next_to(linear_brace, DOWN)
|
||||||
|
|
||||||
|
self.add(
|
||||||
|
faded_linear, transformation,
|
||||||
|
transformation_brace, function
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(faded_linear, linear),
|
||||||
|
Transform(transformation, faded_transformation),
|
||||||
|
Transform(transformation_brace, linear_brace),
|
||||||
|
Transform(function, new_sub_word),
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
class IntroduceLinearTransformations(LinearTransformationScene):
|
class IntroduceLinearTransformations(LinearTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"show_basis_vectors" : False,
|
"show_basis_vectors" : False,
|
||||||
"include_background_plane" : False
|
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.setup()
|
self.setup()
|
||||||
|
@ -135,12 +416,10 @@ class IntroduceLinearTransformations(LinearTransformationScene):
|
||||||
rule.add_background_rectangle()
|
rule.add_background_rectangle()
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
# FadeIn(lines_rule_rect),
|
|
||||||
Write(lines_rule, run_time = 2),
|
Write(lines_rule, run_time = 2),
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(
|
self.play(
|
||||||
# FadeIn(origin_rule_rect),
|
|
||||||
Write(origin_rule, run_time = 2),
|
Write(origin_rule, run_time = 2),
|
||||||
ShowCreation(arrow),
|
ShowCreation(arrow),
|
||||||
GrowFromCenter(dot)
|
GrowFromCenter(dot)
|
||||||
|
@ -216,7 +495,7 @@ class SneakyNonlinearTransformationExplained(SneakyNonlinearTransformation):
|
||||||
self.play(ShowCreation(diag))
|
self.play(ShowCreation(diag))
|
||||||
self.add_transformable_mobject(diag)
|
self.add_transformable_mobject(diag)
|
||||||
|
|
||||||
class AnotherLinearTransformation(SimpleLinearTransformationScene):
|
class GridLinesRemainParallel(SimpleLinearTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"transposed_matrix" : [
|
"transposed_matrix" : [
|
||||||
[3, 0],
|
[3, 0],
|
||||||
|
@ -257,123 +536,31 @@ class YetAnotherLinearTransformation(SimpleLinearTransformationScene):
|
||||||
[3, 2],
|
[3, 2],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoveAroundAllVectors(LinearTransformationScene):
|
|
||||||
CONFIG = {
|
|
||||||
"show_basis_vectors" : False,
|
|
||||||
"focus_on_one_vector" : False,
|
|
||||||
"include_background_plane" : False,
|
|
||||||
}
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.setup()
|
SimpleLinearTransformationScene.construct(self)
|
||||||
vectors = VMobject(*[
|
words = TextMobject("""
|
||||||
Vector([x, y])
|
How would you describe
|
||||||
for x in np.arange(-int(SPACE_WIDTH)+0.5, int(SPACE_WIDTH)+0.5)
|
one of these numerically?
|
||||||
for y in np.arange(-int(SPACE_HEIGHT)+0.5, int(SPACE_HEIGHT)+0.5)
|
"""
|
||||||
])
|
|
||||||
vectors.submobject_gradient_highlight(PINK, YELLOW)
|
|
||||||
dots = self.get_dots(vectors)
|
|
||||||
|
|
||||||
self.dither()
|
|
||||||
self.play(ShowCreation(dots))
|
|
||||||
self.dither()
|
|
||||||
self.play(Transform(dots, vectors))
|
|
||||||
self.dither()
|
|
||||||
self.remove(dots)
|
|
||||||
if self.focus_on_one_vector:
|
|
||||||
vector = vectors.split()[43]#yeah, great coding Grant
|
|
||||||
self.remove(vectors)
|
|
||||||
self.add_vector(vector)
|
|
||||||
self.play(*[
|
|
||||||
FadeOut(v)
|
|
||||||
for v in vectors.split()
|
|
||||||
if v is not vector
|
|
||||||
])
|
|
||||||
self.dither()
|
|
||||||
self.add(vector.copy().highlight(DARK_GREY))
|
|
||||||
else:
|
|
||||||
for vector in vectors.split():
|
|
||||||
self.add_vector(vector, animate = False)
|
|
||||||
self.apply_transposed_matrix([[3, 0], [1, 2]])
|
|
||||||
self.dither()
|
|
||||||
dots = self.get_dots(vectors)
|
|
||||||
self.play(Transform(vectors, dots))
|
|
||||||
self.dither()
|
|
||||||
|
|
||||||
def get_dots(self, vectors):
|
|
||||||
return VMobject(*[
|
|
||||||
Dot(v.get_end(), color = v.get_color())
|
|
||||||
for v in vectors.split()
|
|
||||||
])
|
|
||||||
|
|
||||||
# class MoveAroundJustOneVector(MoveAroundAllVectors):
|
|
||||||
# CONFIG = {
|
|
||||||
# "focus_on_one_vector" : True,
|
|
||||||
# }
|
|
||||||
|
|
||||||
class ReasonForThinkingAboutArrows(LinearTransformationScene):
|
|
||||||
CONFIG = {
|
|
||||||
"show_basis_vectors" : False
|
|
||||||
}
|
|
||||||
def construct(self):
|
|
||||||
self.setup()
|
|
||||||
self.plane.fade()
|
|
||||||
v_color = MAROON_C
|
|
||||||
w_color = BLUE
|
|
||||||
|
|
||||||
v = self.add_vector([3, 1], color = v_color)
|
|
||||||
w = self.add_vector([1, -2], color = w_color)
|
|
||||||
vectors = VMobject(v, w)
|
|
||||||
|
|
||||||
self.to_and_from_dots(vectors)
|
|
||||||
self.scale_and_add(vectors)
|
|
||||||
self.apply_transposed_matrix([[1, 1], [-1, 0]])
|
|
||||||
self.scale_and_add(vectors)
|
|
||||||
|
|
||||||
def to_and_from_dots(self, vectors):
|
|
||||||
vectors_copy = vectors.copy()
|
|
||||||
dots = VMobject(*[
|
|
||||||
Dot(v.get_end(), color = v.get_color())
|
|
||||||
for v in vectors.split()
|
|
||||||
])
|
|
||||||
|
|
||||||
self.dither()
|
|
||||||
self.play(Transform(vectors, dots))
|
|
||||||
self.dither()
|
|
||||||
self.play(Transform(vectors, vectors_copy))
|
|
||||||
self.dither()
|
|
||||||
|
|
||||||
def scale_and_add(self, vectors):
|
|
||||||
vectors_copy = vectors.copy()
|
|
||||||
v, w, = vectors.split()
|
|
||||||
scaled_v = Vector(0.5*v.get_end(), color = v.get_color())
|
|
||||||
scaled_w = Vector(1.5*w.get_end(), color = w.get_color())
|
|
||||||
shifted_w = scaled_w.copy().shift(scaled_v.get_end())
|
|
||||||
sum_vect = Vector(shifted_w.get_end(), color = PINK)
|
|
||||||
|
|
||||||
self.play(
|
|
||||||
ApplyMethod(v.scale, 0.5),
|
|
||||||
ApplyMethod(w.scale, 1.5),
|
|
||||||
)
|
)
|
||||||
self.play(ApplyMethod(w.shift, v.get_end()))
|
words.add_background_rectangle()
|
||||||
self.add_vector(sum_vect)
|
words.to_edge(UP)
|
||||||
self.dither()
|
words.highlight(GREEN)
|
||||||
self.play(Transform(
|
formula = TexMobject(
|
||||||
vectors, vectors_copy,
|
matrix_to_tex_string(["x", "y"]) + "\\rightarrow" + \
|
||||||
submobject_mode = "all_at_once"
|
matrix_to_tex_string(["-1x+3y", "1x + 2y"])
|
||||||
))
|
)
|
||||||
self.dither()
|
formula.add_background_rectangle()
|
||||||
|
|
||||||
class LinearTransformationWithOneVector(LinearTransformationScene):
|
self.play(Write(words))
|
||||||
CONFIG = {
|
self.dither()
|
||||||
"show_basis_vectors" : False,
|
self.play(
|
||||||
}
|
ApplyMethod(self.plane.fade, 0.7),
|
||||||
def construct(self):
|
ApplyMethod(self.background_plane.fade, 0.7),
|
||||||
self.setup()
|
Write(formula, run_time = 2),
|
||||||
v = self.add_vector([3, 1])
|
Animation(words)
|
||||||
self.vector_to_coords(v)
|
)
|
||||||
self.apply_transposed_matrix([[-1, 1], [-2, -1]])
|
self.dither()
|
||||||
self.vector_to_coords(v)
|
|
||||||
|
|
||||||
class FollowIHatJHat(LinearTransformationScene):
|
class FollowIHatJHat(LinearTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -596,12 +783,7 @@ class MatrixVectorMultiplication(LinearTransformationScene):
|
||||||
i_brackets = i_coords.get_brackets()
|
i_brackets = i_coords.get_brackets()
|
||||||
j_brackets = j_coords.get_brackets()
|
j_brackets = j_coords.get_brackets()
|
||||||
for coords in i_coords, j_coords:
|
for coords in i_coords, j_coords:
|
||||||
rect = Rectangle(
|
rect = BackgroundRectangle(coords)
|
||||||
color = BLACK,
|
|
||||||
stroke_width = 0,
|
|
||||||
fill_opacity = 0.75
|
|
||||||
)
|
|
||||||
rect.replace(coords, stretch = True)
|
|
||||||
coords.rect = rect
|
coords.rect = rect
|
||||||
|
|
||||||
abstract_matrix = np.append(
|
abstract_matrix = np.append(
|
||||||
|
@ -616,8 +798,8 @@ class MatrixVectorMultiplication(LinearTransformationScene):
|
||||||
concrete_matrix.to_edge(UP)
|
concrete_matrix.to_edge(UP)
|
||||||
matrix_brackets = concrete_matrix.get_brackets()
|
matrix_brackets = concrete_matrix.get_brackets()
|
||||||
|
|
||||||
self.play(FadeIn(i_coords.rect), Write(i_coords))
|
self.play(ShowCreation(i_coords.rect), Write(i_coords))
|
||||||
self.play(FadeIn(j_coords.rect), Write(j_coords))
|
self.play(ShowCreation(j_coords.rect), Write(j_coords))
|
||||||
self.dither()
|
self.dither()
|
||||||
self.remove(i_coords.rect, j_coords.rect)
|
self.remove(i_coords.rect, j_coords.rect)
|
||||||
self.play(
|
self.play(
|
||||||
|
@ -773,6 +955,243 @@ class MatrixVectorMultiplicationAbstract(MatrixVectorMultiplication):
|
||||||
"abstract" : True,
|
"abstract" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ColumnsToBasisVectors(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
transposed_matrix = [[3, 1], [1, 2]]
|
||||||
|
vector_coords = [-1, 2]
|
||||||
|
|
||||||
|
vector = self.move_matrix_columns(transposed_matrix, vector_coords)
|
||||||
|
self.scale_and_add(vector, vector_coords)
|
||||||
|
|
||||||
|
def move_matrix_columns(self, transposed_matrix, vector_coords = None):
|
||||||
|
matrix = np.array(transposed_matrix).transpose()
|
||||||
|
matrix_mob = Matrix(matrix)
|
||||||
|
matrix_mob.to_corner(UP+LEFT)
|
||||||
|
col1 = VMobject(*matrix_mob.get_mob_matrix()[:,0])
|
||||||
|
col1.highlight(X_COLOR)
|
||||||
|
col2 = VMobject(*matrix_mob.get_mob_matrix()[:,1])
|
||||||
|
col2.highlight(Y_COLOR)
|
||||||
|
matrix_brackets = matrix_mob.get_brackets()
|
||||||
|
matrix_background = BackgroundRectangle(matrix_mob)
|
||||||
|
self.add_foreground_mobject(matrix_background, matrix_mob)
|
||||||
|
|
||||||
|
if vector_coords is not None:
|
||||||
|
vector = Matrix(vector_coords)
|
||||||
|
VMobject(*vector.get_mob_matrix().flatten()).highlight(YELLOW)
|
||||||
|
vector.scale_to_fit_height(matrix_mob.get_height())
|
||||||
|
vector.next_to(matrix_mob, RIGHT)
|
||||||
|
vector_background = BackgroundRectangle(vector)
|
||||||
|
self.add_foreground_mobject(vector_background, vector)
|
||||||
|
|
||||||
|
new_i = Vector(matrix[:,0])
|
||||||
|
new_j = Vector(matrix[:,1])
|
||||||
|
i_label = vector_coordinate_label(new_i).highlight(X_COLOR)
|
||||||
|
j_label = vector_coordinate_label(new_j).highlight(Y_COLOR)
|
||||||
|
i_coords = VMobject(*i_label.get_mob_matrix().flatten())
|
||||||
|
j_coords = VMobject(*j_label.get_mob_matrix().flatten())
|
||||||
|
i_brackets = i_label.get_brackets()
|
||||||
|
j_brackets = j_label.get_brackets()
|
||||||
|
i_label_background = BackgroundRectangle(i_label)
|
||||||
|
j_label_background = BackgroundRectangle(j_label)
|
||||||
|
i_coords_start = VMobject(
|
||||||
|
matrix_background.copy(),
|
||||||
|
col1.copy(),
|
||||||
|
matrix_brackets.copy()
|
||||||
|
)
|
||||||
|
i_coords_end = VMobject(
|
||||||
|
i_label_background,
|
||||||
|
i_coords,
|
||||||
|
i_brackets,
|
||||||
|
)
|
||||||
|
j_coords_start = VMobject(
|
||||||
|
matrix_background.copy(),
|
||||||
|
col2.copy(),
|
||||||
|
matrix_brackets.copy()
|
||||||
|
)
|
||||||
|
j_coords_end = VMobject(
|
||||||
|
j_label_background,
|
||||||
|
j_coords,
|
||||||
|
j_brackets,
|
||||||
|
)
|
||||||
|
|
||||||
|
transform_matrix1 = np.array(matrix)
|
||||||
|
transform_matrix1[:,1] = [0, 1]
|
||||||
|
transform_matrix2 = np.dot(
|
||||||
|
matrix,
|
||||||
|
np.linalg.inv(transform_matrix1)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
transform_matrix1.transpose(),
|
||||||
|
added_anims = [Transform(i_coords_start, i_coords_end)],
|
||||||
|
path_arc = np.pi/2
|
||||||
|
)
|
||||||
|
self.add_foreground_mobject(i_coords_start)
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
transform_matrix2.transpose(),
|
||||||
|
added_anims = [Transform(j_coords_start, j_coords_end) ],
|
||||||
|
path_arc = np.pi/2
|
||||||
|
)
|
||||||
|
self.add_foreground_mobject(j_coords_start)
|
||||||
|
self.dither()
|
||||||
|
return vector if vector_coords is not None else None
|
||||||
|
|
||||||
|
|
||||||
|
def scale_and_add(self, vector, vector_coords):
|
||||||
|
i_copy = self.i_hat.copy()
|
||||||
|
j_copy = self.j_hat.copy()
|
||||||
|
i_target = i_copy.copy().scale(vector_coords[0]).fade(0.3)
|
||||||
|
j_target = j_copy.copy().scale(vector_coords[1]).fade(0.3)
|
||||||
|
|
||||||
|
coord1, coord2 = vector.copy().get_mob_matrix().flatten()
|
||||||
|
coord1.add_background_rectangle()
|
||||||
|
coord2.add_background_rectangle()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Transform(i_copy, i_target),
|
||||||
|
ApplyMethod(coord1.next_to, i_target.get_center(), DOWN)
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Transform(j_copy, j_target),
|
||||||
|
ApplyMethod(coord2.next_to, j_target.get_center(), LEFT)
|
||||||
|
)
|
||||||
|
j_copy.add(coord2)
|
||||||
|
self.play(ApplyMethod(j_copy.shift, i_copy.get_end()))
|
||||||
|
self.add_vector(j_copy.get_end())
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class Describe90DegreeRotation(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"transposed_matrix" : [[0, 1], [-1, 0]],
|
||||||
|
"title" : "$90^\\circ$ rotation counterclockwise",
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
title = TextMobject(self.title)
|
||||||
|
title.shift(DOWN)
|
||||||
|
title.add_background_rectangle()
|
||||||
|
matrix = Matrix(np.array(self.transposed_matrix).transpose())
|
||||||
|
matrix.to_corner(UP+LEFT)
|
||||||
|
matrix_background = BackgroundRectangle(matrix)
|
||||||
|
col1 = VMobject(*matrix.get_mob_matrix()[:,0])
|
||||||
|
col2 = VMobject(*matrix.get_mob_matrix()[:,1])
|
||||||
|
col1.highlight(X_COLOR)
|
||||||
|
col2.highlight(Y_COLOR)
|
||||||
|
self.add_foreground_mobject(matrix_background, matrix.get_brackets())
|
||||||
|
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(self.transposed_matrix)
|
||||||
|
self.dither()
|
||||||
|
self.play(Write(title))
|
||||||
|
self.add_foreground_mobject(title)
|
||||||
|
|
||||||
|
for vect, color, col in [(self.i_hat, X_COLOR, col1), (self.j_hat, Y_COLOR, col2)]:
|
||||||
|
label = vector_coordinate_label(vect)
|
||||||
|
label.highlight(color)
|
||||||
|
background = BackgroundRectangle(label)
|
||||||
|
coords = VMobject(*label.get_mob_matrix().flatten())
|
||||||
|
brackets = label.get_brackets()
|
||||||
|
|
||||||
|
self.play(ShowCreation(background), Write(label))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(background, rate_func = lambda t : smooth(1-t)),
|
||||||
|
ApplyMethod(coords.replace, col),
|
||||||
|
FadeOut(brackets),
|
||||||
|
)
|
||||||
|
self.remove(label)
|
||||||
|
self.add_foreground_mobject(coords)
|
||||||
|
self.dither()
|
||||||
|
self.show_vector(matrix)
|
||||||
|
|
||||||
|
def show_vector(self, matrix):
|
||||||
|
vector = Matrix(["x", "y"])
|
||||||
|
VMobject(*vector.get_mob_matrix().flatten()).highlight(YELLOW)
|
||||||
|
vector.scale_to_fit_height(matrix.get_height())
|
||||||
|
vector.next_to(matrix, RIGHT)
|
||||||
|
v_background = BackgroundRectangle(vector)
|
||||||
|
|
||||||
|
matrix = np.array(self.transposed_matrix).transpose()
|
||||||
|
inv = np.linalg.inv(matrix)
|
||||||
|
self.apply_transposed_matrix(inv.transpose(), run_time = 0.5)
|
||||||
|
self.add_vector([1, 2])
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(self.transposed_matrix)
|
||||||
|
self.play(ShowCreation(v_background), Write(vector))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class DescribeShear(Describe90DegreeRotation):
|
||||||
|
CONFIG = {
|
||||||
|
"transposed_matrix" : [[1, 0], [1, 1]],
|
||||||
|
"title" : "``Shear''",
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeduceTransformationFromMatrix(ColumnsToBasisVectors):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.move_matrix_columns([[1, 2], [3, 1]])
|
||||||
|
|
||||||
|
class LinearlyDependentColumns(ColumnsToBasisVectors):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
title = TextMobject("Linearly dependent")
|
||||||
|
subtitle = TextMobject("columns")
|
||||||
|
title.add_background_rectangle()
|
||||||
|
subtitle.add_background_rectangle()
|
||||||
|
subtitle.next_to(title, DOWN)
|
||||||
|
title.add(subtitle)
|
||||||
|
title.shift(UP).to_edge(LEFT)
|
||||||
|
title.highlight(YELLOW)
|
||||||
|
self.add_foreground_mobject(title)
|
||||||
|
self.move_matrix_columns([[2, 1], [-2, -1]])
|
||||||
|
|
||||||
|
class NextVideo(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Next video: Matrix multiplication as composition")
|
||||||
|
title.to_edge(UP)
|
||||||
|
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
||||||
|
rect.scale_to_fit_height(6)
|
||||||
|
rect.next_to(title, DOWN)
|
||||||
|
|
||||||
|
self.add(title)
|
||||||
|
self.play(ShowCreation(rect))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
class FinalSlide(Scene):
|
||||||
|
def construct(self):
|
||||||
|
text = TextMobject("""
|
||||||
|
\\footnotesize
|
||||||
|
Technically, the definition of ``linear'' is as follows:
|
||||||
|
A transformation L is linear if it satisfies these
|
||||||
|
two properties:
|
||||||
|
|
||||||
|
\\begin{align*}
|
||||||
|
L(\\vec{\\textbf{v}} + \\vec{\\textbf{w}})
|
||||||
|
&= L(\\vec{\\textbf{v}}) + L(\\vec{\\textbf{w}})
|
||||||
|
& & \\text{``Additivity''} \\\\
|
||||||
|
L(c\\vec{\\textbf{v}}) &= c L(\\vec{\\textbf{v}})
|
||||||
|
& & \\text{``Scaling''}
|
||||||
|
\\end{align*}
|
||||||
|
|
||||||
|
I'll talk about these properties later on, but I'm a big
|
||||||
|
believer in first understanding things visually.
|
||||||
|
Once you do, it becomes much more intuitive why these
|
||||||
|
two properties make sense. So for now, you can
|
||||||
|
feel fine thinking of linear transformations as those
|
||||||
|
which keep grid lines parallel and evenly spaced
|
||||||
|
(and which fix the origin in place), since this visual
|
||||||
|
definition is actually equivalent to the two properties
|
||||||
|
above.
|
||||||
|
""", enforce_new_line_structure = False)
|
||||||
|
text.scale_to_fit_height(2*SPACE_HEIGHT - 2)
|
||||||
|
text.to_edge(UP)
|
||||||
|
self.add(text)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
### Old scenes
|
||||||
|
|
||||||
class RotateIHat(LinearTransformationScene):
|
class RotateIHat(LinearTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -1070,9 +1489,125 @@ class SecondAdditivityExample(AdditivityProperty):
|
||||||
"proclaim_sum" : False,
|
"proclaim_sum" : False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ShowGridCreation(Scene):
|
||||||
|
def construct(self):
|
||||||
|
plane = NumberPlane()
|
||||||
|
coords = VMobject(*plane.get_coordinate_labels())
|
||||||
|
self.play(ShowCreation(plane, run_time = 3))
|
||||||
|
self.play(Write(coords, run_time = 3))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class MoveAroundAllVectors(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
"focus_on_one_vector" : False,
|
||||||
|
"include_background_plane" : False,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
vectors = VMobject(*[
|
||||||
|
Vector([x, y])
|
||||||
|
for x in np.arange(-int(SPACE_WIDTH)+0.5, int(SPACE_WIDTH)+0.5)
|
||||||
|
for y in np.arange(-int(SPACE_HEIGHT)+0.5, int(SPACE_HEIGHT)+0.5)
|
||||||
|
])
|
||||||
|
vectors.submobject_gradient_highlight(PINK, YELLOW)
|
||||||
|
dots = self.get_dots(vectors)
|
||||||
|
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(dots))
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(dots, vectors))
|
||||||
|
self.dither()
|
||||||
|
self.remove(dots)
|
||||||
|
if self.focus_on_one_vector:
|
||||||
|
vector = vectors.split()[43]#yeah, great coding Grant
|
||||||
|
self.remove(vectors)
|
||||||
|
self.add_vector(vector)
|
||||||
|
self.play(*[
|
||||||
|
FadeOut(v)
|
||||||
|
for v in vectors.split()
|
||||||
|
if v is not vector
|
||||||
|
])
|
||||||
|
self.dither()
|
||||||
|
self.add(vector.copy().highlight(DARK_GREY))
|
||||||
|
else:
|
||||||
|
for vector in vectors.split():
|
||||||
|
self.add_vector(vector, animate = False)
|
||||||
|
self.apply_transposed_matrix([[3, 0], [1, 2]])
|
||||||
|
self.dither()
|
||||||
|
dots = self.get_dots(vectors)
|
||||||
|
self.play(Transform(vectors, dots))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def get_dots(self, vectors):
|
||||||
|
return VMobject(*[
|
||||||
|
Dot(v.get_end(), color = v.get_color())
|
||||||
|
for v in vectors.split()
|
||||||
|
])
|
||||||
|
|
||||||
|
class ReasonForThinkingAboutArrows(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.plane.fade()
|
||||||
|
v_color = MAROON_C
|
||||||
|
w_color = BLUE
|
||||||
|
|
||||||
|
v = self.add_vector([3, 1], color = v_color)
|
||||||
|
w = self.add_vector([1, -2], color = w_color)
|
||||||
|
vectors = VMobject(v, w)
|
||||||
|
|
||||||
|
self.to_and_from_dots(vectors)
|
||||||
|
self.scale_and_add(vectors)
|
||||||
|
self.apply_transposed_matrix([[1, 1], [-1, 0]])
|
||||||
|
self.scale_and_add(vectors)
|
||||||
|
|
||||||
|
def to_and_from_dots(self, vectors):
|
||||||
|
vectors_copy = vectors.copy()
|
||||||
|
dots = VMobject(*[
|
||||||
|
Dot(v.get_end(), color = v.get_color())
|
||||||
|
for v in vectors.split()
|
||||||
|
])
|
||||||
|
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(vectors, dots))
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(vectors, vectors_copy))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def scale_and_add(self, vectors):
|
||||||
|
vectors_copy = vectors.copy()
|
||||||
|
v, w, = vectors.split()
|
||||||
|
scaled_v = Vector(0.5*v.get_end(), color = v.get_color())
|
||||||
|
scaled_w = Vector(1.5*w.get_end(), color = w.get_color())
|
||||||
|
shifted_w = scaled_w.copy().shift(scaled_v.get_end())
|
||||||
|
sum_vect = Vector(shifted_w.get_end(), color = PINK)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ApplyMethod(v.scale, 0.5),
|
||||||
|
ApplyMethod(w.scale, 1.5),
|
||||||
|
)
|
||||||
|
self.play(ApplyMethod(w.shift, v.get_end()))
|
||||||
|
self.add_vector(sum_vect)
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(
|
||||||
|
vectors, vectors_copy,
|
||||||
|
submobject_mode = "all_at_once"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class LinearTransformationWithOneVector(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
v = self.add_vector([3, 1])
|
||||||
|
self.vector_to_coords(v)
|
||||||
|
self.apply_transposed_matrix([[-1, 1], [-2, -1]])
|
||||||
|
self.vector_to_coords(v)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,8 @@ class NumericalMatrixMultiplication(Scene):
|
||||||
Transform(
|
Transform(
|
||||||
start_parts,
|
start_parts,
|
||||||
result_entry.copy().highlight(YELLOW),
|
result_entry.copy().highlight(YELLOW),
|
||||||
path_arc = -np.pi/2
|
path_arc = -np.pi/2,
|
||||||
|
submobject_mode = "all_at_once",
|
||||||
),
|
),
|
||||||
*lagging_anims
|
*lagging_anims
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from vectorized_mobject import VMobject
|
from vectorized_mobject import VMobject
|
||||||
from svg_mobject import SVGMobject, VMobjectFromSVGPathstring
|
from svg_mobject import SVGMobject, VMobjectFromSVGPathstring
|
||||||
from topics.geometry import Rectangle
|
from topics.geometry import BackgroundRectangle
|
||||||
from helpers import *
|
from helpers import *
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
@ -103,21 +103,9 @@ class TexMobject(SVGMobject):
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_background_rectangle(self, color = BLACK, opacity = 0.75):
|
def add_background_rectangle(self, color = BLACK, opacity = 0.75):
|
||||||
self.rectangle = Rectangle(
|
rect = BackgroundRectangle(self)
|
||||||
color = color,
|
|
||||||
stroke_width = 0,
|
|
||||||
fill_opacity = opacity
|
|
||||||
)
|
|
||||||
self.rectangle.replace(self, stretch = True)
|
|
||||||
letters = VMobject(*self.submobjects)
|
letters = VMobject(*self.submobjects)
|
||||||
self.submobjects = [self.rectangle, letters]
|
self.submobjects = [rect, letters]
|
||||||
##Hacky stuff to fix later ...TODO
|
|
||||||
def rect_become_partial(mob, a, b):
|
|
||||||
return self.rectangle.set_fill(opacity = b*opacity)
|
|
||||||
self.rectangle.pointwise_become_partial = rect_become_partial
|
|
||||||
def rect_set_style_data(*args, **kwargs):
|
|
||||||
return self.rectangle #Do nothing
|
|
||||||
self.rectangle.set_style_data = rect_set_style_data
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
class TextMobject(TexMobject):
|
class TextMobject(TexMobject):
|
||||||
|
|
|
@ -346,6 +346,7 @@ class VMobject(Mobject):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class VectorizedPoint(VMobject):
|
class VectorizedPoint(VMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"color" : BLACK,
|
"color" : BLACK,
|
||||||
|
|
|
@ -267,6 +267,30 @@ class Square(Rectangle):
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class BackgroundRectangle(Rectangle):
|
||||||
|
CONFIG = {
|
||||||
|
"color" : BLACK,
|
||||||
|
"stroke_width" : 0,
|
||||||
|
"fill_opacity" : 0.75,
|
||||||
|
}
|
||||||
|
def __init__(self, mobject, **kwargs):
|
||||||
|
self.lock_style = False
|
||||||
|
Rectangle.__init__(self, **kwargs)
|
||||||
|
self.lock_style = True
|
||||||
|
self.replace(mobject, stretch = True)
|
||||||
|
self.original_fill_opacity = self.fill_opacity
|
||||||
|
|
||||||
|
def pointwise_become_partial(self, mobject, a, b):
|
||||||
|
self.lock_style = False
|
||||||
|
self.set_fill(opacity = b*self.original_fill_opacity)
|
||||||
|
self.lock_style = True
|
||||||
|
return self
|
||||||
|
|
||||||
|
def set_style_data(self, *args, **kwargs):
|
||||||
|
if self.lock_style:
|
||||||
|
return self #Do nothing
|
||||||
|
return Rectangle.set_style_data(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Grid(VMobject):
|
class Grid(VMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue