mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
Rough drafts for chapter 8 parts
This commit is contained in:
@ -61,6 +61,12 @@ class CounterclockwiseTransform(Transform):
|
||||
"path_arc" : np.pi
|
||||
}
|
||||
|
||||
class MoveToTarget(Transform):
|
||||
def __init__(self, mobject, **kwargs):
|
||||
if not hasattr(mobject, "target"):
|
||||
raise Exception("MoveToTarget called on mobject without attribute 'target' ")
|
||||
Transform.__init__(self, mobject, mobject.target, **kwargs)
|
||||
|
||||
class GrowFromCenter(Transform):
|
||||
def __init__(self, mobject, **kwargs):
|
||||
target = mobject.copy()
|
||||
|
135
eola/chapter8.py
135
eola/chapter8.py
@ -34,22 +34,20 @@ def get_vect_tex(*strings):
|
||||
else:
|
||||
return result
|
||||
|
||||
def get_perm_sign(*permutation):
|
||||
identity = np.identity(len(permutation))
|
||||
return np.linalg.det(identity[list(permutation)])
|
||||
|
||||
class OpeningQuote(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject(
|
||||
"``And what is the use of a book,'' thought Alice,",
|
||||
"``without", "pictures", "or", "conversations", "?''"
|
||||
)
|
||||
words.highlight_by_tex("pictures", BLUE)
|
||||
words.highlight_by_tex("conversations", MAROON_B)
|
||||
words.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
||||
words = TextMobject("``Every dimension is special.''")
|
||||
words.to_edge(UP)
|
||||
author = TextMobject("-Lewis Carroll (Alice in Wonderland)")
|
||||
author = TextMobject("-Jeff Lagarias")
|
||||
author.highlight(YELLOW)
|
||||
author.next_to(words, DOWN, buff = 0.5)
|
||||
|
||||
self.play(FadeIn(words))
|
||||
self.dither(4)
|
||||
self.dither(1)
|
||||
self.play(Write(author, run_time = 3))
|
||||
self.dither()
|
||||
|
||||
@ -76,40 +74,98 @@ class DoTheSameForCross(TeacherStudentsScene):
|
||||
self.change_student_modes("pondering")
|
||||
self.random_blink()
|
||||
|
||||
class ListSteps(RandolphScene):
|
||||
class ListSteps(Scene):
|
||||
CONFIG = {
|
||||
"randy_corner" : DOWN+RIGHT
|
||||
}
|
||||
def construct(self):
|
||||
title = TextMobject("Two part chapter")
|
||||
title.highlight(YELLOW)
|
||||
title.to_edge(UP)
|
||||
h_line = Line(LEFT, RIGHT).scale(SPACE_WIDTH)
|
||||
h_line.next_to(title, DOWN)
|
||||
randy = Randolph().flip().to_corner(DOWN+RIGHT)
|
||||
randy.look(UP+LEFT)
|
||||
|
||||
step_1 = TextMobject("This video: Standard introduction")
|
||||
step_2 = TextMobject("Next video: 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)
|
||||
steps.next_to(randy, UP)
|
||||
steps.to_edge(LEFT, buff = LARGE_BUFF)
|
||||
|
||||
self.add(title)
|
||||
self.play(ShowCreation(h_line))
|
||||
for step in steps:
|
||||
self.play(Write(step))
|
||||
self.dither()
|
||||
for step in steps:
|
||||
target = step.copy()
|
||||
target.scale_in_place(1.1)
|
||||
target.highlight(YELLOW)
|
||||
target.highlight_by_tex("linear transformations", BLUE)
|
||||
step.target = target
|
||||
step.save_state()
|
||||
self.play(FadeIn(randy))
|
||||
self.play(Blink(randy))
|
||||
self.play(
|
||||
Write(step_1),
|
||||
ApplyFunction(
|
||||
lambda m : m.change_mode("happy").look(UP+LEFT),
|
||||
self.randy
|
||||
MoveToTarget(step_1),
|
||||
step_2.fade,
|
||||
randy.change_mode, "happy"
|
||||
)
|
||||
self.play(Blink(randy))
|
||||
self.play(
|
||||
Transform(step_1, step_1.copy().restore().fade()),
|
||||
MoveToTarget(step_2),
|
||||
randy.look, LEFT
|
||||
)
|
||||
self.play(randy.change_mode, "erm")
|
||||
self.dither(2)
|
||||
self.play(randy.change_mode, "pondering")
|
||||
self.play(Blink(randy))
|
||||
|
||||
class SimpleDefine2dCrossProduct(LinearTransformationScene):
|
||||
CONFIG = {
|
||||
"show_basis_vectors" : False,
|
||||
"v_coords" : [3, 1],
|
||||
"w_coords" : [2, -1],
|
||||
}
|
||||
def construct(self):
|
||||
self.add_vectors()
|
||||
self.show_area()
|
||||
self.show_sign()
|
||||
|
||||
def add_vectors(self):
|
||||
self.plane.fade()
|
||||
v = self.add_vector(self.v_coords, color = V_COLOR)
|
||||
w = self.add_vector(self.w_coords, color = W_COLOR)
|
||||
for vect, name, direction in (v, "v", "left"), (w, "w", "right"):
|
||||
color = vect.get_color()
|
||||
vect.label = self.label_vector(
|
||||
vect, name, color = color, direction = direction,
|
||||
)
|
||||
)
|
||||
self.dither(1)
|
||||
self.play(
|
||||
Write(step_2),
|
||||
self.randy.change_mode, "pondering"
|
||||
)
|
||||
self.dither()
|
||||
vect.coord_array = vector_coordinate_label(
|
||||
vect, color = color,
|
||||
)
|
||||
vect.coords = vect.coord_array.get_entries()
|
||||
for vect, edge in (v, DOWN), (w, UP):
|
||||
vect.coord_array.move_to(
|
||||
vect.coord_array.get_center(),
|
||||
aligned_edge = edge
|
||||
)
|
||||
self.play(Write(vect.coord_array, run_time = 1))
|
||||
self.v, self.w = v, w
|
||||
|
||||
def show_area(self):
|
||||
transform = self.get_matrix_transformation(np.array([
|
||||
self.v_coords,
|
||||
self.w_coords,
|
||||
]).T)
|
||||
self.square.apply_function(transform)
|
||||
|
||||
def show_sign(self):
|
||||
pass
|
||||
|
||||
|
||||
class ContrastDotAndCross(Scene):
|
||||
def construct(self):
|
||||
@ -986,7 +1042,8 @@ class WriteAreaOfParallelogram(Scene):
|
||||
|
||||
class WriteCrossProductProperties(Scene):
|
||||
def construct(self):
|
||||
v_tex, w_tex, p_tex = get_vect_tex(*"vwp")
|
||||
v_tex, w_tex, p_tex = texs = get_vect_tex(*"vwp")
|
||||
v_cash, w_cash, p_cash = ["$%s$"%tex for tex in texs]
|
||||
cross_product = TexMobject(v_tex, "\\times", w_tex, "=", p_tex)
|
||||
cross_product.highlight_by_tex(v_tex, V_COLOR)
|
||||
cross_product.highlight_by_tex(w_tex, W_COLOR)
|
||||
@ -997,15 +1054,23 @@ class WriteCrossProductProperties(Scene):
|
||||
brace.do_in_place(brace.stretch, 2, 0)
|
||||
vector = brace.get_text("vector")
|
||||
vector.highlight(P_COLOR)
|
||||
length_words = TextMobject("With length", "2.5")
|
||||
length_words.highlight_by_tex("2.5", BLUE)
|
||||
length_words.next_to(vector, DOWN, buff = MED_BUFF)
|
||||
perpendicular = TextMobject("""
|
||||
Perpendicular to
|
||||
the""", "parallelogram"
|
||||
length_words = TextMobject(
|
||||
"Length of ", p_cash, "\\\\ = ",
|
||||
"(parallelogram's area)"
|
||||
)
|
||||
perpendicular.highlight_by_tex("parallelogram", BLUE)
|
||||
perpendicular.next_to(length_words, DOWN, buff = MED_BUFF)
|
||||
length_words.highlight_by_tex(p_cash, P_COLOR)
|
||||
length_words.scale_to_fit_width(SPACE_WIDTH - 1)
|
||||
length_words.highlight_by_tex("(parallelogram's area)", BLUE)
|
||||
length_words.next_to(Group(cross_product, vector), DOWN, buff = LARGE_BUFF)
|
||||
perpendicular = TextMobject(
|
||||
"\\centering Perpendicular to",
|
||||
v_cash, "and", w_cash
|
||||
)
|
||||
perpendicular.scale_to_fit_width(SPACE_WIDTH - 1)
|
||||
perpendicular.highlight_by_tex(v_cash, V_COLOR)
|
||||
perpendicular.highlight_by_tex(w_cash, W_COLOR)
|
||||
perpendicular.next_to(length_words, DOWN, buff = LARGE_BUFF)
|
||||
|
||||
|
||||
self.play(Write(cross_product))
|
||||
self.play(
|
||||
@ -1082,10 +1147,6 @@ class ShowCrossProductFormula(Scene):
|
||||
cross_product.arrange_submobjects()
|
||||
cross_product.shift(2*LEFT)
|
||||
|
||||
def get_perm_sign(a, b, c):
|
||||
identity = np.identity(3)
|
||||
return np.linalg.det(identity[[a, b, c]])
|
||||
|
||||
entry_dicts = [{} for x in range(3)]
|
||||
movement_sets = []
|
||||
for a, b, c in it.permutations(range(3)):
|
||||
|
@ -20,8 +20,7 @@ from mobject.vectorized_mobject import *
|
||||
from eola.matrix import *
|
||||
from eola.two_d_space import *
|
||||
from eola.chapter5 import get_det_text
|
||||
from eola.chapter8 import get_vect_tex, CrossProductRightHandRule
|
||||
from eola.chapter8 import U_COLOR, V_COLOR, W_COLOR, P_COLOR
|
||||
from eola.chapter8 import *
|
||||
|
||||
|
||||
class OpeningQuote(Scene):
|
||||
@ -49,6 +48,26 @@ class OpeningQuote(Scene):
|
||||
self.play(Write(author, run_time = 3))
|
||||
self.dither()
|
||||
|
||||
class CrossProductSymbols(Scene):
|
||||
def construct(self):
|
||||
v_tex, w_tex, p_tex = get_vect_tex(*"vwp")
|
||||
equation = TexMobject(
|
||||
v_tex, "\\times", w_tex, "=", p_tex
|
||||
)
|
||||
equation.highlight_by_tex(v_tex, V_COLOR)
|
||||
equation.highlight_by_tex(w_tex, W_COLOR)
|
||||
equation.highlight_by_tex(p_tex, P_COLOR)
|
||||
brace = Brace(equation[-1])
|
||||
brace.stretch_to_fit_width(0.7)
|
||||
vector_text = brace.get_text("Vector")
|
||||
vector_text.highlight(RED)
|
||||
self.add(equation)
|
||||
self.play(*map(Write, [brace, vector_text]))
|
||||
self.dither()
|
||||
|
||||
class DeterminantTrickCopy(DeterminantTrick):
|
||||
pass
|
||||
|
||||
class BruteForceVerification(Scene):
|
||||
def construct(self):
|
||||
v = Matrix(["v_1", "v_2", "v_3"])
|
||||
@ -188,9 +207,12 @@ class DualityReview(TeacherStudentsScene):
|
||||
|
||||
class DotProductToTransformSymbol(Scene):
|
||||
CONFIG = {
|
||||
"vect_coords" : [4, 1]
|
||||
"vect_coords" : [2, 1]
|
||||
}
|
||||
def construct(self):
|
||||
v_mob = TexMobject(get_vect_tex("v"))
|
||||
v_mob.highlight(V_COLOR)
|
||||
|
||||
matrix = Matrix([self.vect_coords])
|
||||
vector = Matrix(self.vect_coords)
|
||||
matrix.highlight_columns(X_COLOR, Y_COLOR)
|
||||
@ -210,7 +232,17 @@ class DotProductToTransformSymbol(Scene):
|
||||
right_words = right_brace.get_text("Transform")
|
||||
right_words.scale_to_fit_width(right_brace.get_width())
|
||||
|
||||
self.play(*map(FadeIn, (matrix, right_input)))
|
||||
right_v_brace = Brace(right_input, UP)
|
||||
right_v_mob = v_mob.copy()
|
||||
right_v_brace.put_at_tip(right_v_mob)
|
||||
right_input.add(right_v_brace, right_v_mob)
|
||||
left_v_brace = Brace(left_input, UP)
|
||||
left_v_mob = v_mob.copy()
|
||||
left_v_brace.put_at_tip(left_v_mob)
|
||||
left_input.add(left_v_brace, left_v_mob)
|
||||
|
||||
|
||||
self.add(matrix, right_input)
|
||||
self.play(
|
||||
GrowFromCenter(right_brace),
|
||||
Write(right_words, run_time = 1)
|
||||
@ -228,11 +260,622 @@ class DotProductToTransformSymbol(Scene):
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class MathematicalWild(Scene):
|
||||
def construct(self):
|
||||
title = TextMobject("In the mathematical wild")
|
||||
title.to_edge(UP)
|
||||
self.add(title)
|
||||
|
||||
randy = Randolph()
|
||||
randy.shift(DOWN)
|
||||
bubble = ThoughtBubble(width = 5, height = 4)
|
||||
bubble.write("""
|
||||
\\centering
|
||||
Some linear
|
||||
transformation
|
||||
to the number line
|
||||
""")
|
||||
bubble.content.highlight(BLUE)
|
||||
bubble.content.shift(MED_BUFF*UP/2)
|
||||
bubble.remove(*bubble[:-1])
|
||||
bubble.add(bubble.content)
|
||||
bubble.next_to(randy.get_corner(UP+RIGHT), RIGHT)
|
||||
vector = Vector([1, 2])
|
||||
vector.move_to(randy.get_corner(UP+LEFT), aligned_edge = DOWN+LEFT)
|
||||
dual_words = TextMobject("Dual vector")
|
||||
dual_words.gradient_highlight(BLUE, YELLOW)
|
||||
dual_words.next_to(vector, LEFT)
|
||||
|
||||
self.add(randy)
|
||||
self.play(Blink(randy))
|
||||
self.play(FadeIn(bubble))
|
||||
self.play(randy.change_mode, "sassy")
|
||||
self.play(Blink(randy))
|
||||
self.dither()
|
||||
self.play(randy.look, UP+LEFT)
|
||||
self.play(
|
||||
ShowCreation(vector),
|
||||
randy.change_mode, "raise_right_hand"
|
||||
)
|
||||
self.dither()
|
||||
self.play(Write(dual_words))
|
||||
self.play(Blink(randy))
|
||||
self.dither()
|
||||
|
||||
class ThreeStepPlan(Scene):
|
||||
def construct(self):
|
||||
title = TextMobject("The plan")
|
||||
title.highlight(YELLOW)
|
||||
title.to_edge(UP)
|
||||
h_line = Line(LEFT, RIGHT).scale(SPACE_WIDTH)
|
||||
h_line.next_to(title, DOWN)
|
||||
|
||||
v_tex, w_tex = get_vect_tex(*"vw")
|
||||
v_text, w_text, cross_text = [
|
||||
"$%s$"%s
|
||||
for s in v_tex, w_tex, v_tex + "\\times" + w_tex
|
||||
]
|
||||
steps = [
|
||||
TextMobject(
|
||||
"1. Define a 3d-to-1d", "linear \\\\", "transformation",
|
||||
"in terms of", v_text, "and", w_text
|
||||
),
|
||||
TextMobject(
|
||||
"2. Find its", "dual vector"
|
||||
),
|
||||
TextMobject(
|
||||
"3. Show that this dual is", cross_text
|
||||
)
|
||||
]
|
||||
linear, transformation = steps[0][1:1+2]
|
||||
steps[0].highlight_by_tex(v_text, V_COLOR)
|
||||
steps[0].highlight_by_tex(w_text, W_COLOR)
|
||||
steps[1][1].gradient_highlight(BLUE, YELLOW)
|
||||
steps[2].highlight_by_tex(cross_text, P_COLOR)
|
||||
Group(*steps).arrange_submobjects(
|
||||
DOWN, aligned_edge = LEFT, buff = LARGE_BUFF
|
||||
).next_to(h_line, DOWN, buff = MED_BUFF)
|
||||
|
||||
self.add(title)
|
||||
self.play(ShowCreation(h_line))
|
||||
for step in steps:
|
||||
self.play(Write(step, run_time = 2))
|
||||
self.dither()
|
||||
|
||||
linear_transformation = TextMobject("Linear", "transformation")
|
||||
linear_transformation.next_to(h_line, DOWN, MED_BUFF)
|
||||
det = self.get_det()
|
||||
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
||||
rect.scale_to_fit_height(3.5)
|
||||
left_right_arrow = TexMobject("\\Leftrightarrow")
|
||||
left_right_arrow.shift(DOWN)
|
||||
det.next_to(left_right_arrow, LEFT)
|
||||
rect.next_to(left_right_arrow, RIGHT)
|
||||
|
||||
steps[0].remove(linear, transformation)
|
||||
self.play(
|
||||
Transform(
|
||||
Group(linear, transformation),
|
||||
linear_transformation
|
||||
),
|
||||
*map(FadeOut, steps)
|
||||
)
|
||||
self.dither()
|
||||
self.play(Write(left_right_arrow))
|
||||
self.play(Write(det))
|
||||
self.play(ShowCreation(rect))
|
||||
self.dither(0)
|
||||
|
||||
def get_det(self):
|
||||
matrix = Matrix(np.array([
|
||||
["\\hat{\\imath}", "\\hat{\\jmath}", "\\hat{k}"],
|
||||
["v_%d"%d for d in range(1, 4)],
|
||||
["w_%d"%d for d in range(1, 4)],
|
||||
]).T)
|
||||
matrix.highlight_columns(X_COLOR, V_COLOR, W_COLOR)
|
||||
matrix.get_mob_matrix()[1, 0].highlight(Y_COLOR)
|
||||
matrix.get_mob_matrix()[2, 0].highlight(Z_COLOR)
|
||||
Group(*matrix.get_mob_matrix()[1, 1:]).shift(0.15*DOWN)
|
||||
Group(*matrix.get_mob_matrix()[2, 1:]).shift(0.35*DOWN)
|
||||
det_text = get_det_text(matrix)
|
||||
det_text.add(matrix)
|
||||
return det_text
|
||||
|
||||
class DefineDualTransform(Scene):
|
||||
def construct(self):
|
||||
self.add_title()
|
||||
self.show_triple_cross_product()
|
||||
self.write_function()
|
||||
self.introduce_dual_vector()
|
||||
self.expand_dot_product()
|
||||
self.ask_question()
|
||||
|
||||
def add_title(self):
|
||||
title = TextMobject("What a student might think")
|
||||
title.not_real = TextMobject("Not the real cross product")
|
||||
for mob in title, title.not_real:
|
||||
mob.scale_to_fit_width(SPACE_WIDTH - 1)
|
||||
mob.highlight(RED)
|
||||
mob.to_edge(UP)
|
||||
self.add(title)
|
||||
self.title = title
|
||||
|
||||
def show_triple_cross_product(self):
|
||||
colors = [WHITE, ORANGE, W_COLOR]
|
||||
tex_mobs = map(TexMobject, get_vect_tex(*"uvw"))
|
||||
u_tex, v_tex, w_tex = tex_mobs
|
||||
arrays = [
|
||||
Matrix(["%s_%d"%(s, d) for d in range(1, 4)])
|
||||
for s in "uvw"
|
||||
]
|
||||
defs_equals = Group()
|
||||
definitions = Group()
|
||||
for array, tex_mob, color in zip(arrays, tex_mobs, colors):
|
||||
array.highlight_columns(color)
|
||||
tex_mob.highlight(color)
|
||||
equals = TexMobject("=")
|
||||
definition = Group(tex_mob, equals, array)
|
||||
definition.arrange_submobjects(RIGHT)
|
||||
definitions.add(definition)
|
||||
defs_equals.add(equals)
|
||||
definitions.arrange_submobjects(buff = MED_BUFF)
|
||||
definitions.shift(2*DOWN)
|
||||
|
||||
mobs_with_targets = list(it.chain(
|
||||
tex_mobs, *[a.get_entries() for a in arrays]
|
||||
))
|
||||
for mob in mobs_with_targets:
|
||||
mob.target = mob.copy()
|
||||
matrix = Matrix(np.array([
|
||||
[e.target for e in array.get_entries()]
|
||||
for array in arrays
|
||||
]).T)
|
||||
det_text = get_det_text(matrix, background_rect = False)
|
||||
syms = times1, times2, equals = [
|
||||
TexMobject(sym)
|
||||
for sym in "\\times", "\\times", "=",
|
||||
]
|
||||
triple_cross = Group(
|
||||
u_tex.target, times1, v_tex.target, times2, w_tex.target, equals
|
||||
)
|
||||
triple_cross.arrange_submobjects()
|
||||
|
||||
final_mobs = Group(triple_cross, Group(det_text, matrix))
|
||||
final_mobs.arrange_submobjects()
|
||||
final_mobs.next_to(self.title, DOWN, buff = MED_BUFF)
|
||||
|
||||
for mob in definitions, final_mobs:
|
||||
mob.scale_to_fit_width(SPACE_WIDTH - 1)
|
||||
|
||||
for array in arrays:
|
||||
brackets = array.get_brackets()
|
||||
brackets.target = matrix.get_brackets()
|
||||
mobs_with_targets.append(brackets)
|
||||
for def_equals in defs_equals:
|
||||
def_equals.target = equals
|
||||
mobs_with_targets.append(def_equals)
|
||||
|
||||
self.play(FadeIn(
|
||||
definitions,
|
||||
run_time = 2,
|
||||
submobject_mode = "lagged_start"
|
||||
))
|
||||
self.dither(2)
|
||||
self.play(*[
|
||||
Transform(mob.copy(), mob.target)
|
||||
for mob in tex_mobs
|
||||
] + [
|
||||
Write(times1),
|
||||
Write(times2),
|
||||
])
|
||||
triple_cross.add(*self.get_mobjects_from_last_animation()[:3])
|
||||
self.play(*[
|
||||
Transform(mob.copy(), mob.target)
|
||||
for mob in mobs_with_targets
|
||||
if mob not in tex_mobs
|
||||
])
|
||||
u_entries = self.get_mobjects_from_last_animation()[:3]
|
||||
v_entries = self.get_mobjects_from_last_animation()[3:6]
|
||||
w_entries = self.get_mobjects_from_last_animation()[6:9]
|
||||
self.play(Write(det_text))
|
||||
self.dither(2)
|
||||
|
||||
self.det_text = det_text
|
||||
self.definitions = definitions
|
||||
self.u_entries = u_entries
|
||||
self.v_entries = v_entries
|
||||
self.w_entries = w_entries
|
||||
self.matrix = matrix
|
||||
self.triple_cross = triple_cross
|
||||
self.v_tex, self.w_tex = v_tex, w_tex
|
||||
self.equals = equals
|
||||
|
||||
def write_function(self):
|
||||
brace = Brace(self.det_text, DOWN)
|
||||
number_text = brace.get_text("Number")
|
||||
self.play(Transform(self.title, self.title.not_real))
|
||||
self.dither()
|
||||
self.play(FadeOut(self.definitions))
|
||||
self.play(
|
||||
GrowFromCenter(brace),
|
||||
Write(number_text)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
x, y, z = variables = map(TexMobject, "xyz")
|
||||
for var, entry in zip(variables, self.u_entries):
|
||||
var.scale(0.8)
|
||||
var.move_to(entry)
|
||||
entry.target = var
|
||||
brace.target = Brace(z)
|
||||
brace.target.stretch_to_fit_width(0.5)
|
||||
number_text.target = brace.target.get_text("Variable")
|
||||
v_brace = Brace(self.matrix.get_mob_matrix()[0, 1], UP)
|
||||
w_brace = Brace(self.matrix.get_mob_matrix()[0, 2], UP)
|
||||
for vect_brace, tex in (v_brace, self.v_tex), (w_brace, self.w_tex):
|
||||
vect_brace.stretch_to_fit_width(brace.target.get_width())
|
||||
new_tex = tex.copy()
|
||||
vect_brace.put_at_tip(new_tex)
|
||||
vect_brace.tex = new_tex
|
||||
func_tex = TexMobject(
|
||||
"f\\left(%s\\right)"%matrix_to_tex_string(list("xyz"))
|
||||
)
|
||||
func_tex.scale(0.7)
|
||||
func_input = Matrix(list("xyz"))
|
||||
func_input_template = Group(*func_tex[3:-2])
|
||||
func_input.scale_to_fit_height(func_input_template.get_height())
|
||||
func_input.next_to(Group(*func_tex[:3]), RIGHT)
|
||||
Group(*func_tex[-2:]).next_to(func_input, RIGHT)
|
||||
func_tex[0].scale_in_place(1.5)
|
||||
|
||||
func_tex = Group(
|
||||
Group(*[func_tex[i] for i in 0, 1, 2, -2, -1]),
|
||||
func_input
|
||||
)
|
||||
func_tex.next_to(self.equals, LEFT)
|
||||
|
||||
self.play(
|
||||
FadeOut(self.title),
|
||||
FadeOut(self.triple_cross),
|
||||
*[
|
||||
Transform(mob, mob.target)
|
||||
for mob in [brace, number_text]
|
||||
]
|
||||
)
|
||||
self.play(*[
|
||||
Transform(mob, mob.target)
|
||||
for mob in self.u_entries
|
||||
])
|
||||
self.play(*[
|
||||
Write(Group(vect_brace, vect_brace.tex))
|
||||
for vect_brace in v_brace, w_brace
|
||||
])
|
||||
self.dither()
|
||||
self.play(Write(func_tex))
|
||||
self.dither()
|
||||
|
||||
self.func_tex = func_tex
|
||||
self.variables_text = Group(brace, number_text)
|
||||
|
||||
def introduce_dual_vector(self):
|
||||
everything = Group(*self.get_mobjects())
|
||||
colors = [X_COLOR, Y_COLOR, Z_COLOR]
|
||||
q_marks = Group(*map(TextMobject, "???"))
|
||||
q_marks.scale(2)
|
||||
q_marks.gradient_highlight(*colors)
|
||||
|
||||
title = Group(TextMobject("This function is linear"))
|
||||
title.highlight(GREEN)
|
||||
title.to_edge(UP)
|
||||
matrix = Matrix([list(q_marks.copy())])
|
||||
matrix.scale_to_fit_height(self.func_tex.get_height()/2)
|
||||
dual_vector = Matrix(list(q_marks))
|
||||
dual_vector.scale_to_fit_height(self.func_tex.get_height())
|
||||
dual_vector.get_brackets()[0].shift(0.2*LEFT)
|
||||
dual_vector.get_entries().shift(0.1*LEFT)
|
||||
dual_dot = Group(
|
||||
dual_vector,
|
||||
TexMobject("\\cdot").next_to(dual_vector)
|
||||
)
|
||||
|
||||
self.play(
|
||||
Write(title, run_time = 2),
|
||||
everything.shift, DOWN
|
||||
)
|
||||
self.remove(everything)
|
||||
self.add(*everything)
|
||||
self.dither()
|
||||
|
||||
func, func_input = self.func_tex
|
||||
func_input.target = func_input.copy()
|
||||
func_input.target.scale(1.2)
|
||||
func_input.target2 = func_input.copy()
|
||||
func_input.target.move_to(
|
||||
self.variables_text.get_right(),
|
||||
aligned_edge = UP
|
||||
)
|
||||
func_input.target2.move_to(self.func_tex, aligned_edge = RIGHT)
|
||||
matrix.next_to(func_input.target, LEFT)
|
||||
dual_dot.next_to(func_input.target2, LEFT)
|
||||
|
||||
self.play(
|
||||
Transform(func, matrix),
|
||||
MoveToTarget(func_input),
|
||||
FadeOut(self.variables_text),
|
||||
)
|
||||
self.dither()
|
||||
self.play(
|
||||
Transform(func, dual_vector),
|
||||
Transform(func_input, func_input.target2),
|
||||
Write(dual_dot[1])
|
||||
)
|
||||
self.dither()
|
||||
|
||||
p_coords = Group(*map(TexMobject, [
|
||||
"p_%d"%d for d in range(1, 4)
|
||||
]))
|
||||
p_coords.highlight(RED)
|
||||
p_array = Matrix(list(p_coords))
|
||||
p_array.scale_to_fit_height(dual_vector.get_height())
|
||||
p_array.move_to(dual_vector, aligned_edge = RIGHT)
|
||||
p_brace = Brace(p_array, UP)
|
||||
p_tex = TexMobject(get_vect_tex("p"))
|
||||
p_tex.highlight(P_COLOR)
|
||||
p_brace.put_at_tip(p_tex)
|
||||
|
||||
self.play(
|
||||
GrowFromCenter(p_brace),
|
||||
Write(p_tex)
|
||||
)
|
||||
self.play(Transform(
|
||||
func, p_array,
|
||||
run_time = 2,
|
||||
submobject_mode = "lagged_start"
|
||||
))
|
||||
self.remove(func)
|
||||
self.add(p_array)
|
||||
self.dither()
|
||||
self.play(FadeOut(title))
|
||||
self.dither()
|
||||
|
||||
self.p_array = p_array
|
||||
self.input_array = func_input
|
||||
|
||||
def expand_dot_product(self):
|
||||
everything = Group(*self.get_mobjects())
|
||||
self.play(everything.to_edge, UP)
|
||||
self.remove(everything)
|
||||
self.add(*everything)
|
||||
to_fade = Group()
|
||||
|
||||
p_entries = self.p_array.get_entries()
|
||||
input_entries = self.input_array.get_entries()
|
||||
dot_components = Group()
|
||||
for p, x, i in zip(p_entries, input_entries, it.count()):
|
||||
if i == 2:
|
||||
x.sym = TexMobject("=")
|
||||
else:
|
||||
x.sym = TexMobject("+")
|
||||
p.sym = TexMobject("\\cdot")
|
||||
p.target = p.copy().scale(2)
|
||||
x.target = x.copy().scale(2)
|
||||
component = Group(p.target, p.sym, x.target, x.sym)
|
||||
component.arrange_submobjects()
|
||||
dot_components.add(component)
|
||||
dot_components.arrange_submobjects()
|
||||
dot_components.next_to(ORIGIN, LEFT)
|
||||
dot_components.shift(1.5*DOWN)
|
||||
dot_arrow = Arrow(self.p_array.get_corner(DOWN+RIGHT), dot_components)
|
||||
to_fade.add(dot_arrow)
|
||||
self.play(ShowCreation(dot_arrow))
|
||||
new_ps = Group()
|
||||
for p, x in zip(p_entries, input_entries):
|
||||
self.play(
|
||||
MoveToTarget(p.copy()),
|
||||
MoveToTarget(x.copy()),
|
||||
Write(p.sym),
|
||||
Write(x.sym)
|
||||
)
|
||||
mobs = self.get_mobjects_from_last_animation()
|
||||
new_ps.add(mobs[0])
|
||||
to_fade.add(*mobs[1:])
|
||||
self.dither()
|
||||
|
||||
x, y, z = self.u_entries
|
||||
v1, v2, v3 = self.v_entries
|
||||
w1, w2, w3 = self.w_entries
|
||||
cross_components = Group()
|
||||
quints = [
|
||||
(x, v2, w3, v3, w2),
|
||||
(y, v3, w1, v1, w3),
|
||||
(z, v1, w2, v2, w1),
|
||||
]
|
||||
quints = [
|
||||
[m.copy() for m in quint]
|
||||
for quint in quints
|
||||
]
|
||||
for i, quint in enumerate(quints):
|
||||
sym_strings = ["(", "\\cdot", "-", "\\cdot", ")"]
|
||||
if i < 2:
|
||||
sym_strings[-1] += "+"
|
||||
syms = map(TexMobject, sym_strings)
|
||||
for mob, sym in zip(quint, syms):
|
||||
mob.target = mob.copy()
|
||||
mob.target.scale(1.5)
|
||||
mob.sym = sym
|
||||
quint_targets = [mob.target for mob in quint]
|
||||
component = Group(*it.chain(*zip(quint_targets, syms)))
|
||||
component.arrange_submobjects()
|
||||
cross_components.add(component)
|
||||
to_fade.add(syms[0], syms[-1], quint[0])
|
||||
cross_components.arrange_submobjects(DOWN, aligned_edge = LEFT, buff = MED_BUFF)
|
||||
cross_components.next_to(dot_components, RIGHT)
|
||||
for quint in quints:
|
||||
self.play(*[
|
||||
ApplyMethod(mob.highlight, YELLOW)
|
||||
for mob in quint
|
||||
])
|
||||
self.dither(0.5)
|
||||
self.play(*[
|
||||
MoveToTarget(mob)
|
||||
for mob in quint
|
||||
] + [
|
||||
Write(mob.sym)
|
||||
for mob in quint
|
||||
])
|
||||
self.dither()
|
||||
self.play(
|
||||
ApplyFunction(
|
||||
lambda m : m.arrange_submobjects(
|
||||
DOWN, buff = MED_BUFF+SMALL_BUFF
|
||||
).next_to(cross_components, LEFT),
|
||||
new_ps
|
||||
),
|
||||
*map(FadeOut, to_fade)
|
||||
)
|
||||
self.play(*[
|
||||
Write(TexMobject("=").next_to(p, buff = 2*SMALL_BUFF))
|
||||
for p in new_ps
|
||||
])
|
||||
equals = self.get_mobjects_from_last_animation()
|
||||
self.dither(2)
|
||||
everything = everything.copy()
|
||||
self.play(
|
||||
FadeOut(Group(*self.get_mobjects())),
|
||||
Animation(everything)
|
||||
)
|
||||
self.clear()
|
||||
self.add(everything)
|
||||
|
||||
def ask_question(self):
|
||||
everything = Group(*self.get_mobjects())
|
||||
p_tex = "$%s$"%get_vect_tex("p")
|
||||
question = TextMobject(
|
||||
"What vector",
|
||||
p_tex,
|
||||
"has \\\\ the property that"
|
||||
)
|
||||
question.to_edge(UP)
|
||||
question.highlight(YELLOW)
|
||||
question.highlight_by_tex(p_tex, P_COLOR)
|
||||
everything.target = everything.copy()
|
||||
everything.target.next_to(
|
||||
question, DOWN, buff = MED_BUFF
|
||||
)
|
||||
self.play(
|
||||
MoveToTarget(everything),
|
||||
Write(question)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
class ThreeDTripleCrossProduct(Scene):
|
||||
pass #Simple parallelepiped
|
||||
|
||||
class ThreeDMovingVariableVector(Scene):
|
||||
pass #white u moves around
|
||||
|
||||
class ThreeDMovingVariableVectorWithCrossShowing(Scene):
|
||||
pass #white u moves around, red p is present
|
||||
|
||||
class NowForTheCoolPart(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.teacher_says(
|
||||
"Now for the\\\\",
|
||||
"cool part"
|
||||
)
|
||||
self.change_student_modes(*["happy"]*3)
|
||||
self.random_blink(2)
|
||||
self.teacher_says(
|
||||
"Let's answer the same question,\\\\",
|
||||
"but this time geometrically"
|
||||
)
|
||||
self.change_student_modes(*["pondering"]*3)
|
||||
self.random_blink(2)
|
||||
|
||||
class ThreeDDotProductProjection(Scene):
|
||||
pass #
|
||||
|
||||
class DotProductWords(Scene):
|
||||
def construct(self):
|
||||
p_tex = "$%s$"%get_vect_tex("p")
|
||||
p_mob = TextMobject(p_tex)
|
||||
p_mob.scale(1.5)
|
||||
p_mob.highlight(P_COLOR)
|
||||
input_array = Matrix(list("xyz"))
|
||||
dot_product = Group(p_mob, Dot(radius = 0.07), input_array)
|
||||
dot_product.arrange_submobjects(buff = MED_BUFF/2)
|
||||
equals = TexMobject("=")
|
||||
dot_product.next_to(equals, LEFT)
|
||||
words = Group(*it.starmap(TextMobject, [
|
||||
("(Length of projection)",),
|
||||
("(Length of ", p_tex, ")",)
|
||||
]))
|
||||
times = TexMobject("\\times")
|
||||
words[1].highlight_by_tex(p_tex, P_COLOR)
|
||||
words[0].next_to(equals, RIGHT)
|
||||
words[1].next_to(words[0], DOWN, aligned_edge = LEFT)
|
||||
times.next_to(words[0], RIGHT)
|
||||
|
||||
everyone = Group(dot_product, equals, times, words)
|
||||
everyone.center().scale_to_fit_width(SPACE_WIDTH - 1)
|
||||
self.add(dot_product)
|
||||
self.play(Write(equals))
|
||||
self.play(Write(words[0]))
|
||||
self.dither()
|
||||
self.play(
|
||||
Write(times),
|
||||
Write(words[1])
|
||||
)
|
||||
self.dither()
|
||||
|
||||
class ThreeDProjectToPerpendicular(Scene):
|
||||
pass #
|
||||
|
||||
class GeometricVolumeWords(Scene):
|
||||
def construct(self):
|
||||
v_tex, w_tex = [
|
||||
"$%s$"%s
|
||||
for s in get_vect_tex(*"vw")
|
||||
]
|
||||
|
||||
words = Group(
|
||||
TextMobject("(Area of", "parallelogram", ")$\\times$"),
|
||||
TextMobject(
|
||||
"(Component of $%s$"%matrix_to_tex_string(list("xyz")),
|
||||
"perpendicular to", v_tex, "and", w_tex, ")"
|
||||
)
|
||||
)
|
||||
words[0].highlight_by_tex("parallelogram", BLUE)
|
||||
words[1].highlight_by_tex(v_tex, ORANGE)
|
||||
words[1].highlight_by_tex(w_tex, W_COLOR)
|
||||
words.arrange_submobjects(RIGHT)
|
||||
words.scale_to_fit_width(2*SPACE_WIDTH - 1)
|
||||
words.to_edge(DOWN, buff = SMALL_BUFF)
|
||||
for word in words:
|
||||
self.play(Write(word))
|
||||
self.dither()
|
||||
|
||||
class WriteXYZ(Scene):
|
||||
def construct(self):
|
||||
self.play(Write(Matrix(list("xyz"))))
|
||||
self.dither()
|
||||
|
||||
class ThreeDDotProductWithCross(Scene):
|
||||
pass
|
||||
|
||||
class NextVideo(Scene):
|
||||
def construct(self):
|
||||
title = TextMobject("""
|
||||
Next video: Change of basis
|
||||
""")
|
||||
title.to_edge(UP, buff = MED_BUFF/2)
|
||||
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()
|
||||
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ def play_chord(*nums):
|
||||
pass
|
||||
|
||||
def play_error_sound():
|
||||
play_chord(12, 11, 8, 6, 1)
|
||||
play_chord(11, 8, 6, 1)
|
||||
|
||||
|
||||
def play_finish_sound():
|
||||
@ -144,7 +144,7 @@ def bezier(points):
|
||||
n = len(points) - 1
|
||||
return lambda t : sum([
|
||||
((1-t)**(n-k))*(t**k)*choose(n, k)*point
|
||||
for point, k in zip(points, it.count())
|
||||
for k, point in enumerate(points)
|
||||
])
|
||||
|
||||
def remove_list_redundancies(l):
|
||||
|
@ -31,6 +31,7 @@ class PiCreature(SVGMobject):
|
||||
"initial_scale_factor" : 0.01,
|
||||
"corner_scale_factor" : 0.75,
|
||||
"flip_at_start" : False,
|
||||
"is_looking_direction_purposeful" : False,
|
||||
}
|
||||
def __init__(self, mode = "plain", **kwargs):
|
||||
self.parts_named = False
|
||||
@ -81,18 +82,20 @@ class PiCreature(SVGMobject):
|
||||
def change_mode(self, mode):
|
||||
curr_center = self.get_center()
|
||||
curr_height = self.get_height()
|
||||
looking_direction = None
|
||||
looking_direction = self.get_looking_direction()
|
||||
should_be_flipped = self.is_flipped()
|
||||
should_be_flipped = self.is_flipped()
|
||||
if self.is_looking_direction_purposeful:
|
||||
looking_direction = self.get_looking_direction()
|
||||
self.__init__(mode)
|
||||
self.scale_to_fit_height(curr_height)
|
||||
self.shift(curr_center)
|
||||
self.look(looking_direction)
|
||||
if should_be_flipped ^ self.is_flipped():
|
||||
self.flip()
|
||||
if self.is_looking_direction_purposeful:
|
||||
self.look(looking_direction)
|
||||
return self
|
||||
|
||||
def look(self, direction):
|
||||
self.is_looking_direction_purposeful = True
|
||||
x, y = direction[:2]
|
||||
for pupil, eye in zip(self.pupils.split(), self.eyes.split()):
|
||||
pupil.move_to(eye, aligned_edge = direction)
|
||||
@ -113,7 +116,7 @@ class PiCreature(SVGMobject):
|
||||
def get_looking_direction(self):
|
||||
return np.sign(np.round(
|
||||
self.pupils.get_center() - self.eyes.get_center(),
|
||||
decimals = 1
|
||||
decimals = 2
|
||||
))
|
||||
|
||||
def is_flipped(self):
|
||||
|
Reference in New Issue
Block a user