mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 08:54:38 +08:00
Starting chapter 7
This commit is contained in:
@ -29,8 +29,12 @@ SPACE_HEIGHT = 4.0
|
|||||||
SPACE_WIDTH = SPACE_HEIGHT * DEFAULT_WIDTH / DEFAULT_HEIGHT
|
SPACE_WIDTH = SPACE_HEIGHT * DEFAULT_WIDTH / DEFAULT_HEIGHT
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_MOBJECT_TO_EDGE_BUFFER = 0.5
|
SMALL_BUFF = 0.1
|
||||||
DEFAULT_MOBJECT_TO_MOBJECT_BUFFER = 0.2
|
MED_BUFF = 0.5
|
||||||
|
LARGE_BUFF = 1
|
||||||
|
|
||||||
|
DEFAULT_MOBJECT_TO_EDGE_BUFFER = MED_BUFF
|
||||||
|
DEFAULT_MOBJECT_TO_MOBJECT_BUFFER = MED_BUFF
|
||||||
|
|
||||||
|
|
||||||
#All in seconds
|
#All in seconds
|
||||||
|
69
eola/chapter7.py
Normal file
69
eola/chapter7.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from mobject.tex_mobject import TexMobject
|
||||||
|
from mobject import Mobject
|
||||||
|
from mobject.image_mobject import ImageMobject
|
||||||
|
from mobject.vectorized_mobject import VMobject
|
||||||
|
|
||||||
|
from animation.animation import Animation
|
||||||
|
from animation.transform import *
|
||||||
|
from animation.simple_animations import *
|
||||||
|
from topics.geometry import *
|
||||||
|
from topics.characters import *
|
||||||
|
from topics.functions import *
|
||||||
|
from topics.number_line import *
|
||||||
|
from topics.numerals import *
|
||||||
|
from scene import Scene
|
||||||
|
from camera import Camera
|
||||||
|
from mobject.svg_mobject import *
|
||||||
|
from mobject.tex_mobject import *
|
||||||
|
from mobject.vectorized_mobject import *
|
||||||
|
|
||||||
|
from eola.matrix import *
|
||||||
|
from eola.two_d_space import *
|
||||||
|
|
||||||
|
from ka_playgrounds.circuits import Resistor, Source, LongResistor
|
||||||
|
|
||||||
|
class OpeningQuote(Scene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject(
|
||||||
|
"\\small Calvin:",
|
||||||
|
"You know, I don't think math is a science, I think it's a religion.",
|
||||||
|
"\\\\Hobbes:",
|
||||||
|
"A religion?",
|
||||||
|
"\\\\Calvin:" ,
|
||||||
|
"Yeah. All these equations are like miracles."
|
||||||
|
"You take two numbers and when you add them, "
|
||||||
|
"they magically become one NEW number!"
|
||||||
|
)
|
||||||
|
words.scale_to_fit_width(2*SPACE_WIDTH - 1)
|
||||||
|
words.to_edge(UP)
|
||||||
|
words[0].highlight(YELLOW)
|
||||||
|
words[2].highlight("#fd9c2b")
|
||||||
|
words[4].highlight(YELLOW)
|
||||||
|
|
||||||
|
self.play(FadeIn(words))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class TraditionalOrdering(RandolphScene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Traditional ordering:")
|
||||||
|
title.highlight(YELLOW).to_edge(UP)
|
||||||
|
topics = VMobject(*map(TextMobject, [
|
||||||
|
"Topic 1: Vectors",
|
||||||
|
"Topic 2: Dot product",
|
||||||
|
"\\vdots",
|
||||||
|
"(everything else)",
|
||||||
|
"\\vdots",
|
||||||
|
]))
|
||||||
|
topics.arrange_submobjects(DOWN)
|
||||||
|
topics.next_to(title, DOWN)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(title),
|
||||||
|
FadeIn(topics, submobject_mode = "lagged_start")
|
||||||
|
)
|
||||||
|
self.play(topics[1].highlight, PINK)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThisSeriesOrdering(RandolphScene):
|
||||||
|
def construct(self):
|
||||||
|
pass
|
@ -63,9 +63,14 @@ class ColumnsRepresentBasisVectors(Scene):
|
|||||||
i_hat_words.next_to(ORIGIN, LEFT).to_edge(UP)
|
i_hat_words.next_to(ORIGIN, LEFT).to_edge(UP)
|
||||||
j_hat_words.highlight(Y_COLOR)
|
j_hat_words.highlight(Y_COLOR)
|
||||||
j_hat_words.next_to(ORIGIN, RIGHT).to_edge(UP)
|
j_hat_words.next_to(ORIGIN, RIGHT).to_edge(UP)
|
||||||
|
question = TextMobject("How to interpret?")
|
||||||
|
question.next_to(matrix, UP)
|
||||||
|
question.highlight(YELLOW)
|
||||||
|
|
||||||
self.add(matrix)
|
self.add(matrix)
|
||||||
|
self.play(Write(question, run_time = 2))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
self.play(FadeOut(question))
|
||||||
for i, words in enumerate([i_hat_words, j_hat_words]):
|
for i, words in enumerate([i_hat_words, j_hat_words]):
|
||||||
arrow = Arrow(
|
arrow = Arrow(
|
||||||
words.get_bottom(),
|
words.get_bottom(),
|
||||||
@ -80,6 +85,557 @@ class ColumnsRepresentBasisVectors(Scene):
|
|||||||
for m in matrix.get_mob_matrix()[:,i]
|
for m in matrix.get_mob_matrix()[:,i]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.put_in_thought_bubble()
|
||||||
|
|
||||||
|
def put_in_thought_bubble(self):
|
||||||
|
everything = VMobject(*self.get_mobjects())
|
||||||
|
randy = Randolph().to_corner()
|
||||||
|
bubble = randy.get_bubble()
|
||||||
|
|
||||||
|
self.play(FadeIn(randy))
|
||||||
|
self.play(
|
||||||
|
ApplyFunction(
|
||||||
|
lambda m : bubble.position_mobject_inside(
|
||||||
|
m.scale_to_fit_height(2.5)
|
||||||
|
),
|
||||||
|
everything
|
||||||
|
),
|
||||||
|
ShowCreation(bubble),
|
||||||
|
randy.change_mode, "pondering"
|
||||||
|
)
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither()
|
||||||
|
self.play(randy.change_mode, "surprised")
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class Symbolic2To3DTransform(Scene):
|
||||||
|
def construct(self):
|
||||||
|
func = TexMobject("L(", "\\vec{\\textbf{v}}", ")")
|
||||||
|
input_array = Matrix([2, 7])
|
||||||
|
input_array.highlight(YELLOW)
|
||||||
|
in_arrow = Arrow(LEFT, RIGHT, color = input_array.get_color())
|
||||||
|
func[1].highlight(input_array.get_color())
|
||||||
|
output_array = Matrix([1, 8, 2])
|
||||||
|
output_array.highlight(PINK)
|
||||||
|
out_arrow = Arrow(LEFT, RIGHT, color = output_array.get_color())
|
||||||
|
VMobject(
|
||||||
|
input_array, in_arrow, func, out_arrow, output_array
|
||||||
|
).arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||||
|
|
||||||
|
input_brace = Brace(input_array, DOWN)
|
||||||
|
input_words = input_brace.get_text("2d input")
|
||||||
|
output_brace = Brace(output_array, UP)
|
||||||
|
output_words = output_brace.get_text("3d output")
|
||||||
|
input_words.highlight(input_array.get_color())
|
||||||
|
output_words.highlight(output_array.get_color())
|
||||||
|
|
||||||
|
|
||||||
|
self.add(func, input_array)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(input_brace),
|
||||||
|
Write(input_words)
|
||||||
|
)
|
||||||
|
mover = input_array.copy()
|
||||||
|
self.play(
|
||||||
|
Transform(mover, Dot().move_to(func)),
|
||||||
|
ShowCreation(in_arrow),
|
||||||
|
rate_func = rush_into
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Transform(mover, output_array),
|
||||||
|
ShowCreation(out_arrow),
|
||||||
|
rate_func = rush_from
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(output_brace),
|
||||||
|
Write(output_words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class PlaneStartState(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.add_title("Input space")
|
||||||
|
labels = self.get_basis_vector_labels()
|
||||||
|
self.play(*map(Write, labels))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class OutputIn3dWords(Scene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject("Output in 3d")
|
||||||
|
words.scale(1.5)
|
||||||
|
self.play(Write(words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class OutputIn3d(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ShowSideBySide2dTo3d(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AnimationLaziness(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(TextMobject("But there is some animation laziness..."))
|
||||||
|
|
||||||
|
class DescribeColumnsInSpecificTransformation(Scene):
|
||||||
|
def construct(self):
|
||||||
|
matrix = Matrix([
|
||||||
|
[2, 0],
|
||||||
|
[-1, 1],
|
||||||
|
[-2, 1],
|
||||||
|
])
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR)
|
||||||
|
mob_matrix = matrix.get_mob_matrix()
|
||||||
|
i_col, j_col = [VMobject(*mob_matrix[:,i]) for i in 0, 1]
|
||||||
|
for col, char, vect in zip([i_col, j_col], ["i", "j"], [UP, DOWN]):
|
||||||
|
color = col[0].get_color()
|
||||||
|
col.words = TextMobject("Where $\\hat\\%smath$ lands"%char)
|
||||||
|
col.words.next_to(matrix, vect, buff = LARGE_BUFF)
|
||||||
|
col.words.highlight(color)
|
||||||
|
col.arrow = Arrow(
|
||||||
|
col.words.get_edge_center(-vect),
|
||||||
|
col.get_edge_center(vect),
|
||||||
|
color = color
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(Write(matrix.get_brackets()))
|
||||||
|
self.dither()
|
||||||
|
for col in i_col, j_col:
|
||||||
|
self.play(
|
||||||
|
Write(col),
|
||||||
|
ShowCreation(col.arrow),
|
||||||
|
Write(col.words, run_time = 1)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class CountRowsAndColumns(Scene):
|
||||||
|
def construct(self):
|
||||||
|
matrix = Matrix([
|
||||||
|
[2, 0],
|
||||||
|
[-1, 1],
|
||||||
|
[-2, 1],
|
||||||
|
])
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR)
|
||||||
|
rows_brace = Brace(matrix, LEFT)
|
||||||
|
rows_words = rows_brace.get_text("3", "rows")
|
||||||
|
rows_words.highlight(PINK)
|
||||||
|
cols_brace = Brace(matrix, UP)
|
||||||
|
cols_words = cols_brace.get_text("2", "columns")
|
||||||
|
cols_words.highlight(TEAL)
|
||||||
|
title = TexMobject("3", "\\times", "2", "\\text{ matrix}")
|
||||||
|
title.to_edge(UP)
|
||||||
|
|
||||||
|
self.add(matrix)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(rows_brace),
|
||||||
|
Write(rows_words, run_time = 2)
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(cols_brace),
|
||||||
|
Write(cols_words, run_time = 2)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
rows_words[0].copy().move_to, title[0],
|
||||||
|
cols_words[0].copy().move_to, title[2],
|
||||||
|
Write(VMobject(title[1], title[3]))
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class WriteColumnSpaceDefinition(Scene):
|
||||||
|
def construct(self):
|
||||||
|
matrix = Matrix([
|
||||||
|
[2, 0],
|
||||||
|
[-1, 1],
|
||||||
|
[-2, 1],
|
||||||
|
])
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR)
|
||||||
|
|
||||||
|
brace = Brace(matrix)
|
||||||
|
words = VMobject(
|
||||||
|
TextMobject("Span", "of columns"),
|
||||||
|
TexMobject("\\Updownarrow"),
|
||||||
|
TextMobject("``Column space''")
|
||||||
|
)
|
||||||
|
words.arrange_submobjects(DOWN, buff = 0.1)
|
||||||
|
words.next_to(brace, DOWN)
|
||||||
|
words[0][0].highlight(PINK)
|
||||||
|
words[2].highlight(TEAL)
|
||||||
|
words[0].add_background_rectangle()
|
||||||
|
words[2].add_background_rectangle()
|
||||||
|
VMobject(matrix, brace, words).center()
|
||||||
|
|
||||||
|
self.add(matrix)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(words, run_time = 2)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class MatrixInTheWild(Scene):
|
||||||
|
def construct(self):
|
||||||
|
randy = Randolph(color = PINK)
|
||||||
|
randy.look(LEFT)
|
||||||
|
randy.to_corner()
|
||||||
|
matrix = Matrix([
|
||||||
|
[3, 1],
|
||||||
|
[4, 1],
|
||||||
|
[5, 9],
|
||||||
|
])
|
||||||
|
matrix.next_to(randy, RIGHT, buff = LARGE_BUFF, aligned_edge = DOWN)
|
||||||
|
bubble = randy.get_bubble(height = 4)
|
||||||
|
bubble.make_green_screen()
|
||||||
|
VMobject(randy, bubble, matrix).to_corner(UP+LEFT, buff = MED_BUFF)
|
||||||
|
|
||||||
|
self.add(randy)
|
||||||
|
self.play(Write(matrix))
|
||||||
|
self.play(randy.look, RIGHT, run_time = 0.5)
|
||||||
|
self.play(randy.change_mode, "sassy")
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(bubble),
|
||||||
|
randy.change_mode, "pondering"
|
||||||
|
)
|
||||||
|
# self.play(matrix.highlight_columns, X_COLOR, Y_COLOR)
|
||||||
|
self.dither()
|
||||||
|
for x in range(3):
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither(2)
|
||||||
|
new_matrix = Matrix([[3, 1, 4], [1, 5, 9]])
|
||||||
|
new_matrix.move_to(matrix, side_to_align = UP+LEFT)
|
||||||
|
self.play(
|
||||||
|
Transform(matrix, new_matrix),
|
||||||
|
FadeOut(bubble)
|
||||||
|
)
|
||||||
|
self.remove(matrix)
|
||||||
|
matrix = new_matrix
|
||||||
|
self.add(matrix)
|
||||||
|
self.play(randy.look, DOWN+RIGHT, run_time = 0.5)
|
||||||
|
self.play(randy.change_mode, "confused")
|
||||||
|
self.dither()
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
top_brace = Brace(matrix, UP)
|
||||||
|
top_words = top_brace.get_text("3 basis vectors")
|
||||||
|
top_words.submobject_gradient_highlight(GREEN, RED, BLUE)
|
||||||
|
side_brace = Brace(matrix, RIGHT)
|
||||||
|
side_words = side_brace.get_text("""
|
||||||
|
2 coordinates for
|
||||||
|
each landing spots
|
||||||
|
""")
|
||||||
|
side_words.highlight(YELLOW)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(top_brace),
|
||||||
|
Write(top_words),
|
||||||
|
matrix.highlight_columns, X_COLOR, Y_COLOR, Z_COLOR
|
||||||
|
)
|
||||||
|
self.play(randy.change_mode, "happy")
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(side_brace),
|
||||||
|
Write(side_words, run_time = 2)
|
||||||
|
)
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThreeDToTwoDInput(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ThreeDToTwoDInputWords(Scene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject("3d input")
|
||||||
|
words.scale(2)
|
||||||
|
self.play(Write(words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThreeDToTwoDOutput(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"color" : GREY,
|
||||||
|
"x_radius" : SPACE_WIDTH,
|
||||||
|
"y_radius" : SPACE_HEIGHT,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Output in 2d")
|
||||||
|
title.to_edge(UP, buff = SMALL_BUFF)
|
||||||
|
subwords = TextMobject("""
|
||||||
|
(only showing basis vectors,
|
||||||
|
full 3d grid would be a mess)
|
||||||
|
""")
|
||||||
|
subwords.scale(0.75)
|
||||||
|
subwords.next_to(title, DOWN)
|
||||||
|
for words in title, subwords:
|
||||||
|
words.add_background_rectangle()
|
||||||
|
|
||||||
|
self.add(title)
|
||||||
|
i, j, k = it.starmap(self.add_vector, [
|
||||||
|
([3, 1], X_COLOR),
|
||||||
|
([1, 2], Y_COLOR),
|
||||||
|
([-2, -2], Z_COLOR)
|
||||||
|
])
|
||||||
|
pairs = [
|
||||||
|
(i, "L(\\hat\\imath)"),
|
||||||
|
(j, "L(\\hat\\jmath)"),
|
||||||
|
(k, "L(\\hat k)")
|
||||||
|
]
|
||||||
|
for v, tex in pairs:
|
||||||
|
self.label_vector(v, tex)
|
||||||
|
self.play(Write(subwords))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThreeDToTwoDSideBySide(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Symbolic2To1DTransform(Scene):
|
||||||
|
def construct(self):
|
||||||
|
func = TexMobject("L(", "\\vec{\\textbf{v}}", ")")
|
||||||
|
input_array = Matrix([2, 7])
|
||||||
|
input_array.highlight(YELLOW)
|
||||||
|
in_arrow = Arrow(LEFT, RIGHT, color = input_array.get_color())
|
||||||
|
func[1].highlight(input_array.get_color())
|
||||||
|
output_array = Matrix([1.8])
|
||||||
|
output_array.highlight(PINK)
|
||||||
|
out_arrow = Arrow(LEFT, RIGHT, color = output_array.get_color())
|
||||||
|
VMobject(
|
||||||
|
input_array, in_arrow, func, out_arrow, output_array
|
||||||
|
).arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||||
|
|
||||||
|
input_brace = Brace(input_array, DOWN)
|
||||||
|
input_words = input_brace.get_text("2d input")
|
||||||
|
output_brace = Brace(output_array, UP)
|
||||||
|
output_words = output_brace.get_text("1d output")
|
||||||
|
input_words.highlight(input_array.get_color())
|
||||||
|
output_words.highlight(output_array.get_color())
|
||||||
|
|
||||||
|
|
||||||
|
self.add(func, input_array)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(input_brace),
|
||||||
|
Write(input_words)
|
||||||
|
)
|
||||||
|
mover = input_array.copy()
|
||||||
|
self.play(
|
||||||
|
Transform(mover, Dot().move_to(func)),
|
||||||
|
ShowCreation(in_arrow),
|
||||||
|
rate_func = rush_into,
|
||||||
|
run_time = 0.5
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Transform(mover, output_array),
|
||||||
|
ShowCreation(out_arrow),
|
||||||
|
rate_func = rush_from,
|
||||||
|
run_time = 0.5
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(output_brace),
|
||||||
|
Write(output_words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TwoDTo1DTransform(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"include_background_plane" : False,
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : SPACE_WIDTH,
|
||||||
|
"y_radius" : SPACE_HEIGHT,
|
||||||
|
"secondary_line_ratio" : 1
|
||||||
|
},
|
||||||
|
"t_matrix" : [[1, 0], [2, 0]],
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
line = NumberLine()
|
||||||
|
plane_words = TextMobject("2d space")
|
||||||
|
plane_words.next_to(self.j_hat, UP, buff = MED_BUFF)
|
||||||
|
plane_words.add_background_rectangle()
|
||||||
|
line_words = TextMobject("1d space (number line)")
|
||||||
|
line_words.next_to(line, UP)
|
||||||
|
|
||||||
|
|
||||||
|
self.play(Write(plane_words))
|
||||||
|
self.dither()
|
||||||
|
self.remove(plane_words)
|
||||||
|
mobjects = self.get_mobjects()
|
||||||
|
self.play(
|
||||||
|
*map(FadeOut, mobjects) + [ShowCreation(line)]
|
||||||
|
)
|
||||||
|
self.play(Write(line_words))
|
||||||
|
self.dither()
|
||||||
|
self.remove(line_words)
|
||||||
|
self.play(*map(FadeIn, mobjects))
|
||||||
|
self.apply_transposed_matrix(self.t_matrix)
|
||||||
|
self.play(Write(VMobject(*line.get_number_mobjects())))
|
||||||
|
self.dither()
|
||||||
|
self.show_matrix()
|
||||||
|
|
||||||
|
def show_matrix(self):
|
||||||
|
for vect, char in zip([self.i_hat, self.j_hat], ["i", "j"]):
|
||||||
|
vect.words = TextMobject(
|
||||||
|
"$\\hat\\%smath$ lands on"%char,
|
||||||
|
str(int(vect.get_end()[0]))
|
||||||
|
)
|
||||||
|
direction = UP if vect is self.i_hat else DOWN
|
||||||
|
vect.words.next_to(vect.get_end(), direction, buff = LARGE_BUFF)
|
||||||
|
vect.words.highlight(vect.get_color())
|
||||||
|
matrix = Matrix([[1, 2]])
|
||||||
|
matrix_words = TextMobject("Transformation matrix: ")
|
||||||
|
matrix_group = VMobject(matrix_words, matrix)
|
||||||
|
matrix_group.arrange_submobjects(buff = MED_BUFF)
|
||||||
|
matrix_group.to_edge(UP)
|
||||||
|
entries = matrix.get_entries()
|
||||||
|
|
||||||
|
self.play(Write(matrix_words), Write(matrix.get_brackets()))
|
||||||
|
for i, vect in enumerate([self.i_hat, self.j_hat]):
|
||||||
|
self.play(vect.rotate, np.pi/12, rate_func = wiggle)
|
||||||
|
self.play(Write(vect.words))
|
||||||
|
self.dither()
|
||||||
|
self.play(vect.words[1].copy().move_to, entries[i])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TwoDTo1DTransformWithDots(TwoDTo1DTransform):
|
||||||
|
def construct(self):
|
||||||
|
line = NumberLine()
|
||||||
|
self.add(line, *self.get_mobjects())
|
||||||
|
offset = LEFT+DOWN
|
||||||
|
vect = 2*RIGHT+UP
|
||||||
|
dots = VMobject(*[
|
||||||
|
Dot(offset + a*vect, radius = 0.075)
|
||||||
|
for a in np.linspace(-2, 3, 18)
|
||||||
|
])
|
||||||
|
dots.submobject_gradient_highlight(YELLOW_B, YELLOW_C)
|
||||||
|
func = self.get_matrix_transformation(self.t_matrix)
|
||||||
|
new_dots = VMobject(*[
|
||||||
|
Dot(
|
||||||
|
func(dot.get_center()),
|
||||||
|
color = dot.get_color(),
|
||||||
|
radius = dot.radius
|
||||||
|
)
|
||||||
|
for dot in dots
|
||||||
|
])
|
||||||
|
|
||||||
|
self.play(Write(dots))
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [Transform(dots, new_dots)]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class NextVideo(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("""
|
||||||
|
Next video: Dot products and duality
|
||||||
|
""")
|
||||||
|
title.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
||||||
|
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 DotProductPreview(VectorScene):
|
||||||
|
CONFIG = {
|
||||||
|
"v_coords" : [3, 1],
|
||||||
|
"w_coords" : [2, -1],
|
||||||
|
"v_color" : YELLOW,
|
||||||
|
"w_color" : MAROON_C,
|
||||||
|
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.lock_in_faded_grid()
|
||||||
|
self.add_symbols()
|
||||||
|
self.add_vectors()
|
||||||
|
self.grow_number_line()
|
||||||
|
self.project_w()
|
||||||
|
self.show_scaling()
|
||||||
|
|
||||||
|
|
||||||
|
def add_symbols(self):
|
||||||
|
v = matrix_to_mobject(self.v_coords).highlight(self.v_color)
|
||||||
|
w = matrix_to_mobject(self.w_coords).highlight(self.w_color)
|
||||||
|
v.add_background_rectangle()
|
||||||
|
w.add_background_rectangle()
|
||||||
|
dot = TexMobject("\\cdot")
|
||||||
|
eq = VMobject(v, dot, w)
|
||||||
|
eq.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||||
|
eq.to_corner(UP+LEFT)
|
||||||
|
self.play(Write(eq), run_time = 1)
|
||||||
|
|
||||||
|
def add_vectors(self):
|
||||||
|
self.v = Vector(self.v_coords, color = self.v_color)
|
||||||
|
self.w = Vector(self.w_coords, color = self.w_color)
|
||||||
|
self.play(ShowCreation(self.v))
|
||||||
|
self.play(ShowCreation(self.w))
|
||||||
|
|
||||||
|
def grow_number_line(self):
|
||||||
|
line = NumberLine(stroke_width = 2).add_numbers()
|
||||||
|
line.rotate(self.v.get_angle())
|
||||||
|
self.play(Write(line), Animation(self.v))
|
||||||
|
self.play(
|
||||||
|
line.highlight, self.v.get_color(),
|
||||||
|
Animation(self.v),
|
||||||
|
rate_func = there_and_back
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def project_w(self):
|
||||||
|
dot_product = np.dot(self.v.get_end(), self.w.get_end())
|
||||||
|
v_norm, w_norm = [
|
||||||
|
np.linalg.norm(vect.get_end())
|
||||||
|
for vect in self.v, self.w
|
||||||
|
]
|
||||||
|
projected_w = Vector(
|
||||||
|
self.v.get_end()*dot_product/(v_norm**2),
|
||||||
|
color = self.w.get_color()
|
||||||
|
)
|
||||||
|
projection_line = Line(
|
||||||
|
self.w.get_end(), projected_w.get_end(),
|
||||||
|
color = GREY
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(ShowCreation(projection_line))
|
||||||
|
self.add(self.w.copy().fade())
|
||||||
|
self.play(Transform(self.w, projected_w))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def show_scaling(self):
|
||||||
|
dot_product = np.dot(self.v.get_end(), self.w.get_end())
|
||||||
|
start_brace, interim_brace, final_brace = braces = [
|
||||||
|
Brace(
|
||||||
|
Line(ORIGIN, norm*RIGHT),
|
||||||
|
UP
|
||||||
|
)
|
||||||
|
for norm in 1, self.v.get_length(), dot_product
|
||||||
|
]
|
||||||
|
length_texs = list(it.starmap(TexMobject, [
|
||||||
|
("1",),
|
||||||
|
("\\text{Scale by }", "||\\vec{\\textbf{v}}||",),
|
||||||
|
("\\text{Length of}", "\\text{ scaled projection}",),
|
||||||
|
]))
|
||||||
|
length_texs[1][1].highlight(self.v_color)
|
||||||
|
length_texs[2][1].highlight(self.w_color)
|
||||||
|
for brace, tex_mob in zip(braces, length_texs):
|
||||||
|
tex_mob.add_background_rectangle()
|
||||||
|
brace.put_at_tip(tex_mob, buff = SMALL_BUFF)
|
||||||
|
brace.add(tex_mob)
|
||||||
|
brace.rotate(self.v.get_angle())
|
||||||
|
new_w = self.w.copy().scale(self.v.get_length())
|
||||||
|
|
||||||
|
self.play(Write(start_brace))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(start_brace, interim_brace),
|
||||||
|
Transform(self.w, new_w)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(start_brace, final_brace)
|
||||||
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
@ -92,3 +648,10 @@ class ColumnsRepresentBasisVectors(Scene):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,12 +90,14 @@ class VectorScene(Scene):
|
|||||||
def get_vector_label(self, vector, label,
|
def get_vector_label(self, vector, label,
|
||||||
direction = "left",
|
direction = "left",
|
||||||
rotate = False,
|
rotate = False,
|
||||||
color = WHITE,
|
color = None,
|
||||||
label_scale_factor = VECTOR_LABEL_SCALE_FACTOR):
|
label_scale_factor = VECTOR_LABEL_SCALE_FACTOR):
|
||||||
if not isinstance(label, TexMobject):
|
if not isinstance(label, TexMobject):
|
||||||
if len(label) == 1:
|
if len(label) == 1:
|
||||||
label = "\\vec{\\textbf{%s}}"%label
|
label = "\\vec{\\textbf{%s}}"%label
|
||||||
label = TexMobject(label)
|
label = TexMobject(label)
|
||||||
|
if color is None:
|
||||||
|
color = vector.get_color()
|
||||||
label.highlight(color)
|
label.highlight(color)
|
||||||
label.scale(label_scale_factor)
|
label.scale(label_scale_factor)
|
||||||
label.add_background_rectangle()
|
label.add_background_rectangle()
|
||||||
@ -257,7 +259,7 @@ class LinearTransformationScene(VectorScene):
|
|||||||
"i_hat_color" : X_COLOR,
|
"i_hat_color" : X_COLOR,
|
||||||
"j_hat_color" : Y_COLOR,
|
"j_hat_color" : Y_COLOR,
|
||||||
"leave_ghost_vectors" : False,
|
"leave_ghost_vectors" : False,
|
||||||
"t_matrix" : np.array([[3, 0], [1, 2]]),
|
"t_matrix" : [[3, 0], [1, 2]],
|
||||||
}
|
}
|
||||||
def setup(self):
|
def setup(self):
|
||||||
if hasattr(self, "has_setup"):
|
if hasattr(self, "has_setup"):
|
||||||
|
@ -294,6 +294,22 @@ class ThoughtBubble(Bubble):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
class RandolphScene(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"randy_mode" : "plain"
|
||||||
|
}
|
||||||
|
def setup(self):
|
||||||
|
self.randy = Randolph(mode = self.randy_mode)
|
||||||
|
self.randy.to_corner()
|
||||||
|
self.add(self.randy)
|
||||||
|
|
||||||
|
def dither(self, blink = True):
|
||||||
|
if blink:
|
||||||
|
self.play(Blink(self.randy))
|
||||||
|
else:
|
||||||
|
Scene.dither(self)
|
||||||
|
return self
|
||||||
|
|
||||||
class TeacherStudentsScene(Scene):
|
class TeacherStudentsScene(Scene):
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.teacher = Mortimer()
|
self.teacher = Mortimer()
|
||||||
|
@ -13,7 +13,7 @@ class NumberLine(VMobject):
|
|||||||
"x_max" : SPACE_WIDTH,
|
"x_max" : SPACE_WIDTH,
|
||||||
"space_unit_to_num" : 1,
|
"space_unit_to_num" : 1,
|
||||||
"tick_size" : 0.1,
|
"tick_size" : 0.1,
|
||||||
"tick_frequency" : 0.5,
|
"tick_frequency" : 1,
|
||||||
"leftmost_tick" : None, #Defaults to ceil(x_min)
|
"leftmost_tick" : None, #Defaults to ceil(x_min)
|
||||||
"numbers_with_elongated_ticks" : [0],
|
"numbers_with_elongated_ticks" : [0],
|
||||||
"longer_tick_multiple" : 2,
|
"longer_tick_multiple" : 2,
|
||||||
@ -63,7 +63,7 @@ class NumberLine(VMobject):
|
|||||||
return self.x_min + dist_from_left
|
return self.x_min + dist_from_left
|
||||||
|
|
||||||
def default_numbers_to_display(self):
|
def default_numbers_to_display(self):
|
||||||
return self.get_tick_numbers()[::2]
|
return np.arange(self.leftmost_tick, self.x_max, 1)
|
||||||
|
|
||||||
def get_vertical_number_offset(self, direction = DOWN):
|
def get_vertical_number_offset(self, direction = DOWN):
|
||||||
return 4*direction*self.tick_size
|
return 4*direction*self.tick_size
|
||||||
@ -75,7 +75,7 @@ class NumberLine(VMobject):
|
|||||||
result = []
|
result = []
|
||||||
for number in numbers:
|
for number in numbers:
|
||||||
mob = TexMobject(str(int(number)))
|
mob = TexMobject(str(int(number)))
|
||||||
mob.scale_to_fit_height(2*self.tick_size)
|
mob.scale_to_fit_height(3*self.tick_size)
|
||||||
mob.shift(
|
mob.shift(
|
||||||
self.number_to_point(number),
|
self.number_to_point(number),
|
||||||
self.get_vertical_number_offset(**kwargs)
|
self.get_vertical_number_offset(**kwargs)
|
||||||
@ -128,7 +128,6 @@ class NumberPlane(VMobject):
|
|||||||
"written_coordinate_nudge" : 0.1*(DOWN+RIGHT),
|
"written_coordinate_nudge" : 0.1*(DOWN+RIGHT),
|
||||||
"num_pair_at_center" : (0, 0),
|
"num_pair_at_center" : (0, 0),
|
||||||
"propogate_style_to_family" : False,
|
"propogate_style_to_family" : False,
|
||||||
"submobject_partial_creation_mode" : "smoothed_lagged_start",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
|
Reference in New Issue
Block a user