2016-08-24 10:57:16 -07:00
|
|
|
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 eola.chapter5 import get_det_text
|
|
|
|
|
|
|
|
|
|
|
|
U_COLOR = ORANGE
|
2016-08-25 17:15:48 -07:00
|
|
|
V_COLOR = YELLOW
|
2016-08-24 10:57:16 -07:00
|
|
|
W_COLOR = MAROON_B
|
|
|
|
|
|
|
|
class OpeningQuote(Scene):
|
|
|
|
def construct(self):
|
|
|
|
words = TextMobject(
|
2016-08-25 17:15:48 -07:00
|
|
|
"From [Grothendieck], I have also learned not"
|
|
|
|
"to take glory in the ",
|
|
|
|
"difficulty of a proof:",
|
|
|
|
"difficulty means we have not understood."
|
|
|
|
"The idea is to be able to",
|
|
|
|
"paint a landscape",
|
|
|
|
"in which the proof is obvious.",
|
|
|
|
arg_separator = " "
|
2016-08-24 10:57:16 -07:00
|
|
|
)
|
2016-08-25 17:15:48 -07:00
|
|
|
words.highlight_by_tex("difficulty of a proof:", RED)
|
|
|
|
words.highlight_by_tex("paint a landscape", GREEN)
|
|
|
|
words.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
2016-08-24 10:57:16 -07:00
|
|
|
words.to_edge(UP)
|
2016-08-25 17:15:48 -07:00
|
|
|
author = TextMobject("-Pierre Deligne")
|
2016-08-24 10:57:16 -07:00
|
|
|
author.highlight(YELLOW)
|
|
|
|
author.next_to(words, DOWN, buff = 0.5)
|
|
|
|
|
|
|
|
self.play(FadeIn(words))
|
2016-08-25 17:15:48 -07:00
|
|
|
self.dither(4)
|
2016-08-24 10:57:16 -07:00
|
|
|
self.play(Write(author, run_time = 3))
|
|
|
|
self.dither()
|
|
|
|
|
2016-08-25 17:15:48 -07:00
|
|
|
class DoTheSameForCross(TeacherStudentsScene):
|
2016-08-24 10:57:16 -07:00
|
|
|
def construct(self):
|
2016-08-25 17:15:48 -07:00
|
|
|
words = TextMobject("Let's do the same \\\\ for", "cross products")
|
|
|
|
words.highlight_by_tex("cross products", YELLOW)
|
|
|
|
self.teacher_says(words, pi_creature_target_mode = "surprised")
|
|
|
|
self.random_blink(2)
|
|
|
|
self.change_student_modes("pondering")
|
|
|
|
self.random_blink()
|
|
|
|
|
|
|
|
class ListSteps(RandolphScene):
|
|
|
|
CONFIG = {
|
|
|
|
"randy_corner" : DOWN+RIGHT
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
title = TextMobject("Two parts")
|
|
|
|
title.highlight(YELLOW)
|
|
|
|
title.to_edge(UP)
|
|
|
|
h_line = Line(LEFT, RIGHT).scale(SPACE_WIDTH)
|
|
|
|
h_line.next_to(title, DOWN)
|
|
|
|
|
|
|
|
step_1 = TextMobject("1. Standard introduction")
|
|
|
|
step_2 = TextMobject("2. Deeper understanding with ", "linear transformations")
|
|
|
|
step_2.highlight_by_tex("linear transformations", BLUE)
|
|
|
|
steps = Group(step_1, step_2)
|
|
|
|
steps.arrange_submobjects(DOWN, aligned_edge = LEFT, buff = LARGE_BUFF)
|
|
|
|
steps.next_to(self.randy, UP)
|
|
|
|
steps.to_edge(LEFT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeIn(step_1),
|
|
|
|
self.randy.change_mode, "happy"
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
Write(step_2),
|
|
|
|
self.randy.change_mode, "pondering"
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
class ContrastDotAndCross(Scene):
|
|
|
|
def construct(self):
|
|
|
|
self.add_t_chart()
|
|
|
|
self.add_dot_products()
|
|
|
|
self.add_cross_product()
|
|
|
|
self.add_2d_cross_product()
|
|
|
|
self.emphasize_output_type()
|
|
|
|
|
|
|
|
def add_t_chart(self):
|
|
|
|
for word, vect, color in ("Dot", LEFT, BLUE_C), ("Cross", RIGHT, YELLOW):
|
|
|
|
title = TextMobject("%s product"%word)
|
|
|
|
title.shift(vect*SPACE_WIDTH/2)
|
|
|
|
title.to_edge(UP)
|
|
|
|
title.highlight(color)
|
|
|
|
self.add(title)
|
|
|
|
v_line = Line(UP, DOWN).scale(SPACE_HEIGHT)
|
|
|
|
l_h_line = Line(LEFT, ORIGIN).scale(SPACE_WIDTH)
|
|
|
|
r_h_line = Line(ORIGIN, RIGHT).scale(SPACE_WIDTH)
|
|
|
|
r_h_line.next_to(title, DOWN)
|
|
|
|
l_h_line.next_to(r_h_line, LEFT, buff = 0)
|
|
|
|
self.add(v_line, l_h_line, r_h_line)
|
|
|
|
self.l_h_line, self.r_h_line = l_h_line, r_h_line
|
|
|
|
|
|
|
|
def add_dot_products(self, max_width = SPACE_WIDTH-1, dims = [2, 5]):
|
|
|
|
colors = [X_COLOR, Y_COLOR, Z_COLOR, MAROON_B, TEAL]
|
|
|
|
last_mob = self.l_h_line
|
|
|
|
for dim in dims:
|
|
|
|
arrays = [
|
|
|
|
[random.randint(0, 9) for in_count in range(dim)]
|
|
|
|
for out_count in range(2)
|
|
|
|
]
|
|
|
|
m1, m2 = map(Matrix, arrays)
|
|
|
|
for matrix in m1, m2:
|
|
|
|
for entry, color in zip(matrix.get_entries(), colors):
|
|
|
|
entry.highlight(color)
|
|
|
|
syms = map(TexMobject, ["="] + ["+"]*(dim-1))
|
|
|
|
result = Group(*it.chain(*zip(
|
|
|
|
syms,
|
|
|
|
[
|
|
|
|
Group(
|
|
|
|
e1, TexMobject("\\cdot"), e2
|
|
|
|
).arrange_submobjects()
|
|
|
|
for e1, e2 in zip(*[m.copy().get_entries() for m in m1, m2])
|
|
|
|
]
|
|
|
|
)))
|
|
|
|
result.arrange_submobjects(RIGHT)
|
|
|
|
dot_prod = Group(
|
|
|
|
m1, TexMobject("\\cdot"), m2, result
|
|
|
|
)
|
|
|
|
dot_prod.arrange_submobjects(RIGHT)
|
|
|
|
if dot_prod.get_width() > max_width:
|
|
|
|
dot_prod.scale_to_fit_width(max_width)
|
|
|
|
dot_prod.next_to(last_mob, DOWN, buff = MED_BUFF)
|
|
|
|
last_mob = dot_prod
|
|
|
|
dot_prod.to_edge(LEFT)
|
|
|
|
self.play(Write(dot_prod))
|
|
|
|
|
|
|
|
def add_cross_product(self):
|
|
|
|
colors = [X_COLOR, Y_COLOR, Z_COLOR]
|
|
|
|
|
|
|
|
arrays = [
|
|
|
|
[random.randint(0, 9) for in_count in range(3)]
|
|
|
|
for out_count in range(2)
|
2016-08-24 10:57:16 -07:00
|
|
|
]
|
2016-08-25 17:15:48 -07:00
|
|
|
matrices = map(Matrix, arrays)
|
|
|
|
for matrix in matrices:
|
|
|
|
for entry, color in zip(matrix.get_entries(), colors):
|
|
|
|
entry.highlight(color)
|
|
|
|
m1, m2 = matrices
|
|
|
|
cross_product = Group(m1, TexMobject("\\times"), m2)
|
|
|
|
cross_product.arrange_submobjects()
|
|
|
|
|
|
|
|
index_to_cross_enty = {}
|
|
|
|
syms = Group()
|
|
|
|
movement_sets = []
|
|
|
|
for a, b, c in it.permutations(range(3)):
|
|
|
|
e1, e2 = m1.get_entries()[b], m2.get_entries()[c]
|
|
|
|
for e in e1, e2:
|
|
|
|
e.target = e.copy()
|
|
|
|
movement_sets.append([e1, e1.target, e2, e2.target])
|
|
|
|
dot = TexMobject("\\cdot")
|
|
|
|
syms.add(dot)
|
|
|
|
cross_entry = Group(e1.target, dot, e2.target)
|
|
|
|
cross_entry.arrange_submobjects()
|
|
|
|
if a not in index_to_cross_enty:
|
|
|
|
index_to_cross_enty[a] = []
|
|
|
|
index_to_cross_enty[a].append(cross_entry)
|
|
|
|
result_entries = []
|
|
|
|
for a in range(3):
|
|
|
|
prod1, prod2 = index_to_cross_enty[a]
|
|
|
|
if a == 1:
|
|
|
|
prod1, prod2 = prod2, prod1
|
|
|
|
prod2.arrange_submobjects(LEFT)
|
|
|
|
minus = TexMobject("-")
|
|
|
|
syms.add(minus)
|
|
|
|
entry = Group(prod1, minus, prod2)
|
|
|
|
entry.arrange_submobjects(RIGHT)
|
|
|
|
result_entries.append(entry)
|
|
|
|
|
|
|
|
result = Matrix(result_entries)
|
|
|
|
full_cross_product = Group(
|
|
|
|
cross_product, TexMobject("="), result
|
|
|
|
)
|
|
|
|
full_cross_product.arrange_submobjects()
|
|
|
|
full_cross_product.scale(0.75)
|
|
|
|
full_cross_product.next_to(self.r_h_line, DOWN, buff = MED_BUFF/2)
|
|
|
|
full_cross_product.remove(result)
|
|
|
|
self.play(
|
|
|
|
Write(full_cross_product),
|
|
|
|
Write(syms)
|
|
|
|
)
|
|
|
|
movements = []
|
|
|
|
for e1, e1_target, e2, e2_target in movement_sets:
|
|
|
|
movements += [
|
|
|
|
e1.copy().move_to, e1_target,
|
|
|
|
e2.copy().move_to, e2_target,
|
|
|
|
]
|
|
|
|
self.play(
|
|
|
|
Write(result.get_brackets()),
|
|
|
|
*movements,
|
|
|
|
run_time = 2
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
brace = Brace(cross_product)
|
|
|
|
brace_text = brace.get_text("Only 3d")
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(brace),
|
|
|
|
Write(brace_text)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.cross_result = result
|
|
|
|
self.only_3d_text = brace_text
|
|
|
|
|
|
|
|
def add_2d_cross_product(self):
|
|
|
|
h_line = DashedLine(ORIGIN, SPACE_WIDTH*RIGHT)
|
|
|
|
h_line.next_to(self.only_3d_text, DOWN, buff = MED_BUFF/2)
|
|
|
|
h_line.to_edge(RIGHT, buff = 0)
|
|
|
|
arrays = np.random.randint(0, 9, (2, 2))
|
|
|
|
m1, m2 = matrices = map(Matrix, arrays)
|
|
|
|
for m in matrices:
|
|
|
|
for e, color in zip(m.get_entries(), [X_COLOR, Y_COLOR]):
|
|
|
|
e.highlight(color)
|
|
|
|
cross_product = Group(m1, TexMobject("\\times"), m2)
|
|
|
|
cross_product.arrange_submobjects()
|
|
|
|
(x1, x2), (x3, x4) = tuple(m1.get_entries()), tuple(m2.get_entries())
|
|
|
|
entries = [x1, x2, x3, x4]
|
|
|
|
for entry in entries:
|
|
|
|
entry.target = entry.copy()
|
|
|
|
eq, dot1, minus, dot2 = syms = map(TexMobject,
|
|
|
|
["=", "\\cdot", "-", "\\cdot"]
|
|
|
|
)
|
|
|
|
result = Group(
|
|
|
|
eq, x1.target, dot1, x4.target,
|
|
|
|
minus, x3.target, dot2, x2.target,
|
|
|
|
)
|
|
|
|
result.arrange_submobjects(RIGHT)
|
|
|
|
full_cross_product = Group(cross_product, result)
|
|
|
|
full_cross_product.arrange_submobjects(RIGHT)
|
|
|
|
full_cross_product.next_to(h_line, DOWN, buff = MED_BUFF/2)
|
2016-08-24 10:57:16 -07:00
|
|
|
|
2016-08-25 17:15:48 -07:00
|
|
|
self.play(ShowCreation(h_line))
|
|
|
|
self.play(Write(cross_product))
|
|
|
|
self.play(
|
|
|
|
Write(Group(*syms)),
|
|
|
|
*[
|
|
|
|
Transform(entry.copy(), entry.target)
|
|
|
|
for entry in entries
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.two_d_result = Group(*result[1:])
|
|
|
|
|
|
|
|
def emphasize_output_type(self):
|
|
|
|
three_d_brace = Brace(self.cross_result)
|
|
|
|
two_d_brace = Brace(self.two_d_result)
|
|
|
|
vector = three_d_brace.get_text("Vector")
|
|
|
|
number = two_d_brace.get_text("Number")
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(three_d_brace),
|
|
|
|
Write(vector)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(two_d_brace),
|
|
|
|
Write(number)
|
2016-08-24 10:57:16 -07:00
|
|
|
)
|
2016-08-25 17:15:48 -07:00
|
|
|
self.dither()
|
|
|
|
|
|
|
|
class PrereqDeterminant(Scene):
|
|
|
|
def construct(self):
|
|
|
|
title = TextMobject("""
|
|
|
|
Prerequisite: Understanding determinants
|
|
|
|
""")
|
|
|
|
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 Define2dCrossProduct(LinearTransformationScene):
|
|
|
|
CONFIG = {
|
|
|
|
"show_basis_vectors" : False,
|
|
|
|
"v_coords" : [3, 1],
|
|
|
|
"w_coords" : [2, -1],
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.initial_definition()
|
|
|
|
self.show_transformation()
|
|
|
|
self.transform_square()
|
|
|
|
self.show_orientation_rule()
|
|
|
|
|
|
|
|
|
|
|
|
def initial_definition(self):
|
|
|
|
self.plane.save_state()
|
|
|
|
self.plane.fade()
|
|
|
|
v = self.add_vector(self.v_coords, color = V_COLOR)
|
|
|
|
w = self.add_vector(self.w_coords, color = W_COLOR)
|
|
|
|
self.moving_vectors.remove(v)
|
|
|
|
self.moving_vectors.remove(w)
|
2016-08-26 09:39:09 -07:00
|
|
|
for vect, name, direction in (v, "v", "left"), (w, "w", "right"):
|
2016-08-25 17:15:48 -07:00
|
|
|
color = vect.get_color()
|
2016-08-26 09:39:09 -07:00
|
|
|
vect.label = self.label_vector(
|
|
|
|
vect, name, color = color, direction = direction
|
|
|
|
)
|
2016-08-25 17:15:48 -07:00
|
|
|
vect.coord_array = self.write_vector_coordinates(
|
|
|
|
vect, color = color
|
|
|
|
)
|
2016-08-26 09:39:09 -07:00
|
|
|
self.foreground_mobjects.remove(vect.coord_array)
|
2016-08-25 17:15:48 -07:00
|
|
|
vect.coords = vect.coord_array.get_entries()
|
2016-08-26 09:39:09 -07:00
|
|
|
for vect, edge in (v, DOWN), (w, UP):
|
|
|
|
vect.coord_array.move_to(
|
|
|
|
vect.coord_array.get_center(),
|
|
|
|
aligned_edge = edge
|
|
|
|
)
|
2016-08-25 17:15:48 -07:00
|
|
|
movers = [v.label, w.label, v.coords, w.coords]
|
|
|
|
for mover in movers:
|
|
|
|
mover.target = mover.copy()
|
|
|
|
times = TexMobject("\\times")
|
|
|
|
cross_product = Group(
|
|
|
|
v.label.target, times, w.label.target
|
|
|
|
)
|
|
|
|
|
|
|
|
cross_product.arrange_submobjects()
|
2016-08-24 10:57:16 -07:00
|
|
|
matrix = Matrix(np.array([
|
2016-08-25 17:15:48 -07:00
|
|
|
list(v.coords.target),
|
|
|
|
list(w.coords.target)
|
2016-08-24 10:57:16 -07:00
|
|
|
]).T)
|
|
|
|
det_text = get_det_text(matrix)
|
2016-08-25 17:15:48 -07:00
|
|
|
full_det = Group(det_text, matrix)
|
|
|
|
equals = TexMobject("=")
|
|
|
|
equation = Group(cross_product, equals, full_det)
|
|
|
|
equation.arrange_submobjects()
|
|
|
|
equation.to_corner(UP+LEFT)
|
|
|
|
|
|
|
|
matrix_background = BackgroundRectangle(matrix)
|
|
|
|
cross_background = BackgroundRectangle(cross_product)
|
|
|
|
|
|
|
|
disclaimer = TextMobject("$^*$ See ``Note on conventions'' in description")
|
|
|
|
disclaimer.scale(0.7)
|
|
|
|
disclaimer.highlight(RED)
|
|
|
|
disclaimer.next_to(
|
|
|
|
det_text.get_corner(UP+RIGHT), RIGHT, buff = 0
|
|
|
|
)
|
|
|
|
disclaimer.add_background_rectangle()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeIn(cross_background),
|
|
|
|
Transform(v.label.copy(), v.label.target),
|
|
|
|
Transform(w.label.copy(), w.label.target),
|
|
|
|
Write(times),
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(Transform(v.coords.copy(), v.coords.target))
|
|
|
|
self.play(Transform(w.coords.copy(), w.coords.target))
|
|
|
|
self.play(
|
|
|
|
ShowCreation(matrix_background),
|
|
|
|
Write(matrix.get_brackets()),
|
|
|
|
Animation(matrix.get_entries()),
|
|
|
|
run_time = 1
|
|
|
|
)
|
|
|
|
matrix.add_to_back(matrix_background)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
Write(equals),
|
|
|
|
Write(det_text),
|
|
|
|
Animation(matrix),
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeIn(disclaimer))
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeOut(disclaimer))
|
|
|
|
self.dither()
|
|
|
|
|
2016-08-26 09:39:09 -07:00
|
|
|
cross_product.add_to_back(cross_background)
|
|
|
|
cross_product.add(equals)
|
|
|
|
self.cross_product = cross_product
|
2016-08-25 17:15:48 -07:00
|
|
|
self.matrix = matrix
|
|
|
|
self.det_text = det_text
|
2016-08-26 09:39:09 -07:00
|
|
|
self.v, self.w = v, w
|
2016-08-25 17:15:48 -07:00
|
|
|
|
|
|
|
def show_transformation(self):
|
2016-08-26 09:39:09 -07:00
|
|
|
matrix = self.matrix.copy()
|
2016-08-25 17:15:48 -07:00
|
|
|
everything = self.get_mobjects()
|
|
|
|
everything.remove(self.plane)
|
|
|
|
everything.remove(self.background_plane)
|
|
|
|
self.play(
|
|
|
|
*map(FadeOut, everything) + [
|
|
|
|
Animation(self.background_plane),
|
|
|
|
self.plane.restore,
|
|
|
|
Animation(matrix),
|
|
|
|
])
|
2016-08-26 09:39:09 -07:00
|
|
|
i_hat, j_hat = self.get_basis_vectors()
|
|
|
|
for vect in i_hat, j_hat:
|
|
|
|
vect.save_state()
|
|
|
|
basis_labels = self.get_basis_vector_labels()
|
|
|
|
self.play(
|
|
|
|
ShowCreation(i_hat),
|
|
|
|
ShowCreation(j_hat),
|
|
|
|
Write(basis_labels)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
2016-08-25 17:15:48 -07:00
|
|
|
side_brace = Brace(matrix, RIGHT)
|
|
|
|
transform_words = side_brace.get_text("Linear transformation")
|
|
|
|
transform_words.add_background_rectangle()
|
|
|
|
|
|
|
|
col1, col2 = [
|
2016-08-26 09:39:09 -07:00
|
|
|
Group(*matrix.get_mob_matrix()[i,:])
|
2016-08-25 17:15:48 -07:00
|
|
|
for i in 0, 1
|
|
|
|
]
|
|
|
|
|
|
|
|
both_words = []
|
|
|
|
for char, color, col in ("i", X_COLOR, col1), ("j", Y_COLOR, col2):
|
|
|
|
words = TextMobject("Where $\\hat\\%smath$ lands"%char)
|
|
|
|
words.highlight(color)
|
|
|
|
words.add_background_rectangle()
|
|
|
|
words.next_to(col, DOWN, buff = LARGE_BUFF)
|
|
|
|
words.arrow = Arrow(words.get_top(), col.get_bottom(), color = color)
|
|
|
|
both_words.append(words)
|
|
|
|
i_words, j_words = both_words
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(side_brace),
|
|
|
|
Write(transform_words)
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Write(i_words),
|
|
|
|
ShowCreation(i_words.arrow),
|
|
|
|
col1.highlight, X_COLOR
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
Transform(i_words, j_words),
|
|
|
|
Transform(i_words.arrow, j_words.arrow),
|
|
|
|
col2.highlight, Y_COLOR
|
2016-08-24 10:57:16 -07:00
|
|
|
)
|
2016-08-25 17:15:48 -07:00
|
|
|
self.dither()
|
2016-08-26 09:39:09 -07:00
|
|
|
self.play(*map(FadeOut, [i_words, i_words.arrow, basis_labels]))
|
2016-08-25 17:15:48 -07:00
|
|
|
|
2016-08-26 09:39:09 -07:00
|
|
|
self.add_vector(i_hat, animate = False)
|
|
|
|
self.add_vector(j_hat, animate = False)
|
2016-08-25 17:15:48 -07:00
|
|
|
self.play(*map(FadeOut, [side_brace, transform_words]))
|
|
|
|
self.add_foreground_mobject(matrix)
|
|
|
|
self.apply_transposed_matrix([self.v_coords, self.w_coords])
|
|
|
|
self.dither()
|
2016-08-26 09:39:09 -07:00
|
|
|
self.play(
|
|
|
|
FadeOut(self.plane),
|
|
|
|
*map(Animation, [
|
|
|
|
self.background_plane,
|
|
|
|
matrix,
|
|
|
|
i_hat,
|
|
|
|
j_hat,
|
|
|
|
])
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
ShowCreation(self.v),
|
|
|
|
ShowCreation(self.w),
|
|
|
|
FadeIn(self.v.label),
|
|
|
|
FadeIn(self.w.label),
|
|
|
|
FadeIn(self.v.coord_array),
|
|
|
|
FadeIn(self.w.coord_array),
|
|
|
|
matrix.highlight_columns, V_COLOR, W_COLOR
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.i_hat, self.j_hat = i_hat, j_hat
|
|
|
|
self.matrix = matrix
|
2016-08-25 17:15:48 -07:00
|
|
|
|
|
|
|
|
|
|
|
def transform_square(self):
|
2016-08-26 09:39:09 -07:00
|
|
|
self.play(Write(self.det_text))
|
|
|
|
self.matrix.add(self.det_text)
|
|
|
|
|
|
|
|
vect_stuffs = Group(*it.chain(*[
|
|
|
|
[m, m.label, m.coord_array]
|
|
|
|
for m in self.v, self.w
|
|
|
|
]))
|
|
|
|
to_restore = [self.plane, self.i_hat, self.j_hat]
|
|
|
|
for mob in to_restore:
|
|
|
|
mob.fade(1)
|
|
|
|
|
|
|
|
self.play(*map(FadeOut, vect_stuffs))
|
|
|
|
self.play(
|
|
|
|
*[m.restore for m in to_restore] + [
|
|
|
|
Animation(self.matrix)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.add_unit_square(animate = True, opacity = 0.2)
|
|
|
|
self.square.save_state()
|
|
|
|
self.dither()
|
|
|
|
self.apply_transposed_matrix(
|
|
|
|
[self.v_coords, self.w_coords]
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
FadeOut(self.plane),
|
|
|
|
Animation(self.matrix),
|
|
|
|
*map(FadeIn, vect_stuffs)
|
|
|
|
)
|
|
|
|
self.play(Write(self.cross_product))
|
|
|
|
|
|
|
|
det_text_brace = Brace(self.det_text)
|
|
|
|
area_words = det_text_brace.get_text("Area of this parallelogram")
|
|
|
|
area_words.add_background_rectangle()
|
|
|
|
area_arrow = Arrow(
|
|
|
|
area_words.get_bottom(),
|
|
|
|
self.square.get_center(),
|
|
|
|
color = WHITE
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(det_text_brace),
|
|
|
|
Write(area_words),
|
|
|
|
ShowCreation(area_arrow)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
pm = Group(*map(TexMobject, ["+", "-"]))
|
|
|
|
pm.gradient_highlight(GREEN, RED)
|
|
|
|
pm.arrange_submobjects(DOWN, buff = SMALL_BUFF)
|
|
|
|
pm.add_to_back(BackgroundRectangle(pm))
|
|
|
|
pm.next_to(area_words[0], LEFT, aligned_edge = DOWN)
|
|
|
|
self.play(
|
|
|
|
Transform(self.square.get_point_mobject(), pm),
|
|
|
|
path_arc = -np.pi/2
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(*map(FadeOut, [
|
|
|
|
area_arrow, self.v.coord_array, self.w.coord_array
|
|
|
|
]))
|
2016-08-25 17:15:48 -07:00
|
|
|
|
|
|
|
def show_orientation_rule(self):
|
2016-08-26 09:39:09 -07:00
|
|
|
self.remove(self.i_hat, self.j_hat)
|
|
|
|
for vect in self.v, self.w:
|
|
|
|
vect.add(vect.label)
|
|
|
|
vect.target = vect.copy()
|
|
|
|
angle = np.pi/3
|
|
|
|
self.v.target.rotate(-angle)
|
|
|
|
self.w.target.rotate(angle)
|
|
|
|
self.v.target.label.rotate_in_place(angle)
|
|
|
|
self.w.target.label.rotate_in_place(-angle)
|
|
|
|
for vect in self.v, self.w:
|
|
|
|
vect.target.label[0].set_fill(opacity = 0)
|
|
|
|
self.square.target = self.square.copy().restore()
|
|
|
|
transform = self.get_matrix_transformation([
|
|
|
|
self.v.target.get_end()[:2],
|
|
|
|
self.w.target.get_end()[:2],
|
|
|
|
])
|
|
|
|
self.square.target.apply_function(transform)
|
|
|
|
|
|
|
|
movers = Group(self.square, self.v, self.w)
|
|
|
|
movers.target = Group(*[m.target for m in movers])
|
|
|
|
movers.save_state()
|
|
|
|
self.remove(self.square)
|
|
|
|
self.play(Transform(movers, movers.target))
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
v_tex, w_tex = ["\\vec{\\textbf{%s}}"%s for s in "v", "w"]
|
|
|
|
positive_words, negative_words = words_list = [
|
|
|
|
TexMobject(v_tex, "\\times", w_tex, "\\text{ is }", word)
|
|
|
|
for word in "\\text{positive}", "\\text{negative}"
|
|
|
|
]
|
|
|
|
for words in words_list:
|
|
|
|
words.highlight_by_tex(v_tex, V_COLOR)
|
|
|
|
words.highlight_by_tex(w_tex, W_COLOR)
|
|
|
|
words.highlight_by_tex("\\text{positive}", GREEN)
|
|
|
|
words.highlight_by_tex("\\text{negative}", RED)
|
|
|
|
words.add_background_rectangle()
|
|
|
|
words.next_to(self.square, UP)
|
|
|
|
arc = self.get_arc(self.v, self.w)
|
|
|
|
arc.highlight(GREEN)
|
|
|
|
self.play(
|
|
|
|
Write(positive_words),
|
|
|
|
ShowCreation(arc)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.remove(arc)
|
|
|
|
self.play(movers.restore)
|
|
|
|
arc = self.get_arc(self.v, self.w)
|
|
|
|
arc.highlight(RED)
|
|
|
|
self.play(
|
|
|
|
Transform(positive_words, negative_words),
|
|
|
|
ShowCreation(arc)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
anticommute = TexMobject(
|
|
|
|
v_tex, "\\times", w_tex, "=-", w_tex, "\\times", v_tex
|
|
|
|
)
|
|
|
|
anticommute.shift(SPACE_WIDTH*RIGHT/2)
|
|
|
|
anticommute.to_edge(UP)
|
|
|
|
anticommute.highlight_by_tex(v_tex, V_COLOR)
|
|
|
|
anticommute.highlight_by_tex(w_tex, W_COLOR)
|
|
|
|
anticommute.add_background_rectangle()
|
|
|
|
for v1, v2 in (self.v, self.w), (self.w, self.v):
|
|
|
|
v1.label[0].set_fill(opacity = 0)
|
|
|
|
v1.target = v1.copy()
|
|
|
|
v1.target.label.rotate_in_place(v1.get_angle()-v2.get_angle())
|
|
|
|
v1.target.label.scale_in_place(v1.get_length()/v2.get_length())
|
|
|
|
v1.target.rotate(v2.get_angle()-v1.get_angle())
|
|
|
|
v1.target.scale(v2.get_length()/v1.get_length())
|
|
|
|
v1.target.label.move_to(v2.label)
|
|
|
|
self.play(
|
|
|
|
FadeOut(arc),
|
|
|
|
Transform(positive_words, anticommute)
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Transform(self.v, self.v.target),
|
|
|
|
Transform(self.w, self.w.target),
|
|
|
|
rate_func = there_and_back,
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def get_arc(self, v, w, radius = 2):
|
|
|
|
v_angle, w_angle = v.get_angle(), w.get_angle()
|
|
|
|
nudge = 0.05
|
|
|
|
arc = Arc(
|
|
|
|
(1-2*nudge)*(v_angle - w_angle),
|
|
|
|
start_angle = interpolate(w_angle, v_angle, nudge),
|
|
|
|
radius = radius,
|
|
|
|
stroke_width = 8,
|
|
|
|
)
|
|
|
|
arc.add_tip()
|
|
|
|
return arc
|
2016-08-25 17:15:48 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-08-24 10:57:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|