Footnote about 3d transformations

This commit is contained in:
Grant Sanderson
2016-07-30 13:17:01 -07:00
parent 8e48140961
commit a9c7babdcd
4 changed files with 533 additions and 15 deletions

View File

@ -48,11 +48,17 @@ class MatrixToBlank(Scene):
matrix = Matrix([[3, 1], [0, 2]])
arrow = Arrow(LEFT, RIGHT)
matrix.to_edge(LEFT)
arrow.next_to(matrix, LEFT)
arrow.next_to(matrix, RIGHT)
matrix.add(arrow)
self.play(Write(matrix))
self.dither()
class ExampleTransformation(LinearTransformationScene):
def construct(self):
self.setup()
self.apply_transposed_matrix([[3, 0], [1, 2]])
self.dither(2)
class RecapTime(TeacherStudentsScene):
def construct(self):
self.setup()
@ -226,6 +232,13 @@ class RecapOver(TeacherStudentsScene):
self.teacher_says("Recap over!")
class TwoSuccessiveTransformations(LinearTransformationScene):
CONFIG = {
"foreground_plane_kwargs" : {
"x_radius" : 2*SPACE_WIDTH,
"y_radius" : 2*SPACE_WIDTH,
"secondary_line_ratio" : 0
},
}
def construct(self):
self.setup()
self.apply_transposed_matrix([[2, 1],[1, 2]])
@ -1007,13 +1020,72 @@ class ThreeSuccessiveTransformationsAltParens(ThreeSuccessiveTransformations):
"symbols_str" : "(AB)C"
}
class ThreeSuccessiveTransformationsSimple(ThreeSuccessiveTransformations):
CONFIG = {
"symbols_str" : "ABC"
}
class ExplanationTrumpsProof(Scene):
def construct(self):
greater = TexMobject(">")
greater.shift(RIGHT)
explanation = TextMobject("Good explanation")
explanation.highlight(BLUE)
proof = TextMobject("Symbolic proof")
proof.highlight(LIGHT_BROWN)
explanation.next_to(greater, LEFT)
proof.next_to(greater, RIGHT)
explanation.get_center = lambda : explanation.get_right()
proof.get_center = lambda : proof.get_left()
self.play(
Write(explanation),
Write(greater),
Write(proof),
run_time = 1
)
self.play(
explanation.scale_in_place, 1.5,
proof.scale_in_place, 0.7
)
self.dither()
class GoPlay(TeacherStudentsScene):
def construct(self):
self.setup()
self.teacher_says("Go play!", height = 3, width = 5)
self.play(*[
ApplyMethod(student.change_mode, "happy")
for student in self.get_students()
])
self.random_blink()
student = self.get_students()[-1]
bubble = ThoughtBubble(direction = RIGHT, width = 6, height = 5)
bubble.pin_to(student, allow_flipping = False)
bubble.make_green_screen()
self.play(
ShowCreation(bubble),
student.look, UP+LEFT,
)
self.play(student.change_mode, "pondering")
for x in range(3):
self.random_blink()
self.dither(2)
class NextVideo(Scene):
def construct(self):
title = TextMobject("""
Next video: Linear transformations in three dimensions
""")
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()

447
eola/footnote.py Normal file
View File

@ -0,0 +1,447 @@
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 *
class OpeningQuote(Scene):
def construct(self):
words = TextMobject([
"Lisa:",
"Well, where's my dad?\\\\ \\\\",
"Frink:",
"""Well, it should be obvious to even the most
dimwitted individual who holds an advanced degree
in hyperbolic topology that Homer Simpson has stumbled
into...(dramatic pause)...""",
"the third dimension."
])
words.scale_to_fit_width(2*SPACE_WIDTH - 2)
words.to_edge(UP)
words.split()[0].highlight(YELLOW)
words.split()[2].highlight(YELLOW)
three_d = words.submobjects.pop()
three_d.highlight(BLUE)
self.play(FadeIn(words))
self.play(Write(three_d))
self.dither(2)
class QuickFootnote(TeacherStudentsScene):
def construct(self):
self.setup()
self.teacher_says("Quick footnote here...")
self.random_blink()
self.play(
random.choice(self.get_students()).change_mode, "happy"
)
self.random_blink()
class PeakOutsideFlatland(TeacherStudentsScene):
def construct(self):
self.setup()
self.teacher_says("Peak outside flatland")
self.dither()
student = self.get_students()[0]
self.student_thinks(student_index = 0)
student.bubble.make_green_screen()
self.dither()
class SymbolicThreeDTransform(Scene):
CONFIG = {
"input_coords" : [2, 6, -1],
"output_coords" : [3, 2, 0],
"title" : "Three-dimensional transformation",
}
def construct(self):
in_vect = Matrix(self.input_coords)
out_vect = Matrix(self.output_coords)
in_vect.highlight(BLUE)
out_vect.highlight(GREEN)
func = TexMobject("L(\\vec{\\textbf{v}})")
point = VectorizedPoint(func.get_center())
in_vect.next_to(func, LEFT, buff = 1)
out_vect.next_to(func, RIGHT, buff = 1)
in_words = TextMobject("Input")
in_words.next_to(in_vect, DOWN)
in_words.highlight(BLUE_C)
out_words = TextMobject("Output")
out_words.next_to(out_vect, DOWN)
out_words.highlight(GREEN_C)
title = TextMobject(self.title)
title.to_edge(UP)
self.add(title)
self.play(Write(func))
self.play(Write(in_vect), Write(in_words))
self.dither()
self.add(in_vect.copy())
self.play(Transform(in_vect, point, submobject_mode = "lagged_start"))
self.play(Transform(in_vect, out_vect, submobject_mode = "lagged_start"))
self.add(out_words)
self.dither()
class ThreeDLinearTransformExample(Scene):
pass
class SingleVectorToOutput(Scene):
pass
class InputWordOutputWord(Scene):
def construct(self):
self.add(TextMobject("Input").scale(2))
self.dither()
self.clear()
self.add(TextMobject("Output").scale(2))
self.dither()
class TransformOnlyBasisVectors(Scene):
pass
class IHatJHatKHatWritten(Scene):
def construct(self):
for char, color in zip(["\\imath", "\\jmath", "k"], [X_COLOR, Y_COLOR, Z_COLOR]):
sym = TexMobject("{\\hat{%s}}"%char)
sym.scale(3)
sym.highlight(color)
self.play(Write(sym))
self.dither()
self.clear()
class PutTogether3x3Matrix(Scene):
CONFIG = {
"col1" : [1, 0, -1],
"col2" : [1, 1, 0],
"col3" : [1, 0, 1],
}
def construct(self):
i_to = TexMobject("\\hat{\\imath} \\to").highlight(X_COLOR)
j_to = TexMobject("\\hat{\\jmath} \\to").highlight(Y_COLOR)
k_to = TexMobject("\\hat{k} \\to").highlight(Z_COLOR)
i_array = Matrix(self.col1)
j_array = Matrix(self.col2)
k_array = Matrix(self.col3)
everything = VMobject(
i_to, i_array, TexMobject("=").highlight(BLACK),
j_to, j_array, TexMobject("=").highlight(BLACK),
k_to, k_array, TexMobject("=").highlight(BLACK),
)
everything.arrange_submobjects(RIGHT, buff = 0.1)
everything.scale_to_fit_width(2*SPACE_WIDTH-1)
everything.to_edge(DOWN)
i_array.highlight(X_COLOR)
j_array.highlight(Y_COLOR)
k_array.highlight(Z_COLOR)
arrays = [i_array, j_array, k_array]
matrix = Matrix(reduce(
lambda a1, a2 : np.append(a1, a2, axis = 1),
[m.copy().get_mob_matrix() for m in arrays]
))
matrix.to_edge(DOWN)
start_entries = reduce(op.add, map(
lambda a : a.get_entries().split(),
arrays
))
target_entries = matrix.get_mob_matrix().transpose().flatten()
start_l_bracket = i_array.get_brackets().split()[0]
start_r_bracket = k_array.get_brackets().split()[1]
start_brackets = VMobject(start_l_bracket, start_r_bracket)
target_bracketes = matrix.get_brackets()
for mob in everything.split():
self.play(Write(mob, run_time = 1))
self.dither()
self.play(
FadeOut(everything),
Transform(VMobject(*start_entries), VMobject(*target_entries)),
Transform(start_brackets, target_bracketes)
)
self.dither()
class RotateSpaceAboutYAxis(Scene):
pass
class RotateOnlyBasisVectorsAboutYAxis(Scene):
pass
class PutTogetherRotationMatrix(PutTogether3x3Matrix):
CONFIG = {
"col1" : [0, 0, -1],
"col2" : [0, 1, 0],
"col3" : [1, 0, 0]
}
class ScaleAndAddBeforeTransformation(Scene):
pass
class ShowVCoordinateMeaning(Scene):
CONFIG = {
"v_str" : "\\vec{\\textbf{v}}",
"i_str" : "\\hat{\\imath}",
"j_str" : "\\hat{\\jmath}",
"k_str" : "\\hat{k}",
"post_transform" : False,
}
def construct(self):
v = TexMobject(self.v_str)
v.highlight(YELLOW)
eq = TexMobject("=")
coords = Matrix(["x", "y", "z"])
eq2 = eq.copy()
if self.post_transform:
L, l_paren, r_paren = map(TexMobject, "L()")
parens = VMobject(l_paren, r_paren)
parens.scale(2)
parens.stretch_to_fit_height(
coords.get_height()
)
VMobject(L, l_paren, coords, r_paren).arrange_submobjects(buff = 0.1)
coords.submobjects = [L, l_paren] + coords.submobjects + [r_paren]
lin_comb = VMobject(*map(TexMobject, [
"x", self.i_str, "+",
"y", self.j_str, "+",
"z", self.k_str,
]))
lin_comb.arrange_submobjects(
RIGHT, buff = 0.1,
aligned_edge = ORIGIN if self.post_transform else DOWN
)
lin_comb_parts = np.array(lin_comb.split())
new_x, new_y, new_z = lin_comb_parts[[0, 3, 6]]
i, j, k = lin_comb_parts[[1, 4, 7]]
plusses = lin_comb_parts[[2, 5]]
i.highlight(X_COLOR)
j.highlight(Y_COLOR)
k.highlight(Z_COLOR)
everything = VMobject(v, eq, coords, eq2, lin_comb)
everything.arrange_submobjects(buff = 0.2)
everything.scale_to_fit_width(2*SPACE_WIDTH - 1)
everything.to_edge(DOWN)
if not self.post_transform:
lin_comb.shift(0.35*UP)
self.play(*map(Write, [v, eq, coords]))
self.dither()
self.play(
Transform(
coords.get_entries().copy(),
VMobject(new_x, new_y, new_z),
path_arc = -np.pi,
submobject_mode = "lagged_start"
),
Write(VMobject(*[eq2, i, j, k] + list(plusses))),
run_time = 3
)
self.dither()
class ScaleAndAddAfterTransformation(Scene):
pass
class ShowVCoordinateMeaningAfterTransform(ShowVCoordinateMeaning):
CONFIG = {
"v_str" : "L(\\vec{\\textbf{v}})",
"i_str" : "L(\\hat{\\imath})",
"j_str" : "L(\\hat{\\jmath})",
"k_str" : "L(\\hat{k})",
"post_transform" : True,
}
class ShowMatrixVectorMultiplication(Scene):
def construct(self):
matrix = Matrix(np.arange(9).reshape((3, 3)))
vect = Matrix(list("xyz"))
vect.scale_to_fit_height(matrix.get_height())
col1, col2, col3 = columns = [
Matrix(col)
for col in matrix.copy().get_mob_matrix().transpose()
]
coords = x, y, z = [m.copy() for m in vect.get_entries().split()]
eq, plus1, plus2 = map(TexMobject, list("=++"))
everything = VMobject(
matrix, vect, eq,
x, col1, plus1,
y, col2, plus2,
z, col3
)
everything.arrange_submobjects(buff = 0.1)
everything.scale_to_fit_width(2*SPACE_WIDTH-1)
result = VMobject(x, col1, plus1, y, col2, plus2, z, col3)
trips = [
(matrix, DOWN, "Transformation"),
(vect, UP, "Input vector"),
(result, DOWN, "Output vector"),
]
braces = []
for mob, direction, text in trips:
brace = Brace(mob, direction)
words = TextMobject(text)
words.next_to(brace, direction)
brace.add(words)
braces.append(brace)
matrix_brace, vect_brace, result_brace = braces
self.play(*map(Write, [matrix, vect]), run_time = 2)
self.play(Write(matrix_brace, run_time = 1))
self.play(Write(vect_brace, run_time = 1))
sexts = zip(
matrix.get_mob_matrix().transpose(),
columns,
vect.get_entries().split(),
coords,
[eq, plus1, plus2],
[X_COLOR, Y_COLOR, Z_COLOR]
)
for o_col, col, start_coord, coord, sym, color in sexts:
o_col = VMobject(*o_col)
self.play(
start_coord.highlight, YELLOW,
o_col.highlight, color
)
coord.highlight(YELLOW)
col.highlight(color)
self.play(
Write(col.get_brackets()),
Transform(
o_col.copy(), col.get_entries(),
path_arc = -np.pi
),
Transform(
start_coord.copy(), coord,
path_arc = -np.pi
),
Write(sym)
)
self.dither()
self.play(Write(result_brace, run_time = 1))
self.dither()
class ShowMatrixMultiplication(Scene):
def construct(self):
right = Matrix(np.arange(9).reshape((3, 3)))
left = Matrix(np.random.random_integers(-5, 5, (3, 3)))
VMobject(left, right).arrange_submobjects(buff = 0.1)
right.highlight_columns(X_COLOR, Y_COLOR, Z_COLOR)
left.highlight(PINK)
trips = [
(right, DOWN, "First transformation"),
(left, UP, "Second transformation"),
]
braces = []
for mob, direction, text in trips:
brace = Brace(mob, direction)
words = TextMobject(text)
words.next_to(brace, direction)
brace.add(words)
braces.append(brace)
right_brace, left_brace = braces
VMobject(*self.get_mobjects()).scale_to_fit_width(2*SPACE_WIDTH-1)
self.add(right, left)
self.play(Write(right_brace))
self.play(Write(left_brace))
self.dither()
class ApplyTwoSuccessiveTransforms(Scene):
pass
class ThreeDRotation(Scene):
pass
class ThreeDRotationBrokenUp(Scene):
pass
class SymbolicTwoDToThreeDTransform(SymbolicThreeDTransform):
CONFIG = {
"input_coords" : [2, 6],
"output_coords" : [3, 2, 0],
"title" : "Two dimensions to three dimensions",
}
class SymbolicThreeDToTwoDTransform(SymbolicThreeDTransform):
CONFIG = {
"input_coords" : [4, -3, 1],
"output_coords" : [8, 4],
"title" : "Three dimensions to two dimensions",
}
class QuestionsToPonder(Scene):
def construct(self):
title = TextMobject("Questions to ponder")
title.highlight(YELLOW).to_edge(UP)
self.add(title)
questions = map(TextMobject, [
"Can you visualize these transformations?",
"Can you represent them with matrices?",
"How many rows and columns?",
"When does it make sense to multiply these matrices?",
])
nums = VMobject(*[
TexMobject("%d."%(num+1))
for num in range(len(questions))
])
nums.arrange_submobjects(DOWN, buff = 1, aligned_edge = LEFT)
nums.to_edge(LEFT)
for num, question in zip(nums.split(), questions):
question.scale(0.8)
question.next_to(num)
self.play(Write(num), FadeIn(question))
self.dither()
class NextVideo(Scene):
def construct(self):
title = TextMobject("""
Next video: The determinant
""")
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()

View File

@ -145,7 +145,6 @@ class NumericalMatrixMultiplication(Scene):
)
self.organize_matrices(left, right, result)
# self.add_lines(left, right)
self.animate_product(left, right, result)

View File

@ -207,9 +207,9 @@ class Bubble(SVGMobject):
self.direction = -np.array(self.direction)
return self
def pin_to(self, mobject):
def pin_to(self, mobject, allow_flipping = True):
mob_center = mobject.get_center()
if (mob_center[0] > 0) != (self.direction[0] > 0):
if np.sign(mob_center[0]) != np.sign(self.direction[0]) and allow_flipping:
self.flip()
boundary_point = mobject.get_critical_point(UP-self.direction)
vector_from_center = 1.0*(boundary_point-mob_center)
@ -338,21 +338,21 @@ class TeacherStudentsScene(Scene):
self.play(*anims)
return pi_creature.bubble
def teacher_says(self, content, **kwargs):
def teacher_says(self, content = "", **kwargs):
return self.introduce_bubble(
content, "speech", self.get_teacher(), **kwargs
)
def student_says(self, content, student_index = 1, **kwargs):
def student_says(self, content = "", student_index = 1, **kwargs):
student = self.get_students()[student_index]
return self.introduce_bubble(content, "speech", student, **kwargs)
def teacher_thinks(self, content, **kwargs):
def teacher_thinks(self, content = "", **kwargs):
return self.introduce_bubble(
content, "thought", self.get_teacher(), **kwargs
)
def student_thinks(self, content, student_index = 1, **kwargs):
def student_thinks(self, content = "", student_index = 1, **kwargs):
student = self.get_students()[student_index]
return self.introduce_bubble(content, "thought", student, **kwargs)