TransformingAreasYCoord and TransformingAreasXCoord

This commit is contained in:
Grant Sanderson 2018-04-28 11:29:44 -07:00
parent 944632ef90
commit 7b4094794c

View file

@ -51,7 +51,8 @@ class LinearSystem(VGroup):
self.input_vect_mob.elements.set_color_by_gradient(*colors)
if output_vect is None:
output_vect = np.random.randint(self.min_int, self.max_int, size=(dim, 1))
output_vect = np.random.randint(
self.min_int, self.max_int, size=(dim, 1))
self.output_vect_mob = IntegerMatrix(output_vect)
self.output_vect_mob.elements.set_color(OUTPUT_COLOR)
@ -133,7 +134,8 @@ class LeaveItToComputers(TeacherStudentsScene):
numer, line, denom = cg.rhs
x_copy = system.input_vect_mob.elements[0].copy()
self.play(
RemovePiCreatureBubble(self.teacher, target_mode="raise_right_hand"),
RemovePiCreatureBubble(
self.teacher, target_mode="raise_right_hand"),
ShowCreation(line),
ReplacementTransform(
system.matrix_mobject.copy(),
@ -295,7 +297,8 @@ class SetupSimpleSystemOfEquations(LinearTransformationScene):
lag_ratio=0.7
))
self.play(FadeOut(unknown_circles))
self.play(LaggedStart(ShowCreation, row_rects, run_time=1, lag_ratio=0.8))
self.play(LaggedStart(ShowCreation, row_rects,
run_time=1, lag_ratio=0.8))
self.play(FadeOut(row_rects))
self.wait()
self.remove(system)
@ -389,7 +392,8 @@ class SetupSimpleSystemOfEquations(LinearTransformationScene):
column_mob = IntegerMatrix(matrix[:, i])
column_mob.elements.set_color([X_COLOR, Y_COLOR][i])
column_mob.scale(scale_factor)
column_mob.next_to(self.plane.coords_to_point(*matrix[:, i]), RIGHT)
column_mob.next_to(
self.plane.coords_to_point(*matrix[:, i]), RIGHT)
column_mob.add_to_back(BackgroundRectangle(column_mob))
column_mobs.add(column_mob)
@ -398,7 +402,8 @@ class SetupSimpleSystemOfEquations(LinearTransformationScene):
output_vect_label.add_to_back(BackgroundRectangle(output_vect_label))
output_vect_label.generate_target()
output_vect_label.target.scale(scale_factor)
output_vect_label.target.next_to(output_vect_mob.get_end(), LEFT, SMALL_BUFF)
output_vect_label.target.next_to(
output_vect_mob.get_end(), LEFT, SMALL_BUFF)
input_vect = np.dot(np.linalg.inv(self.matrix), self.output_vect)
input_vect_mob = self.get_vector(input_vect, color=INPUT_COLOR)
@ -586,7 +591,8 @@ class ShowZeroDeterminantCase(LinearTransformationScene):
FadeOut(vect_off_span_mob.circle),
ReplacementTransform(vect_off_span_mob, vect_in_span_mob),
ReplacementTransform(vect_off_span_words, vect_in_span_words),
ReplacementTransform(vect_off_span_mob.circle, vect_in_span_mob.circle),
ReplacementTransform(vect_off_span_mob.circle,
vect_in_span_mob.circle),
)
self.wait(2)
self.play(
@ -609,7 +615,8 @@ class ShowZeroDeterminantCase(LinearTransformationScene):
"\\det(", "A", ")", self.det_eq_symbol, "0"
)
det_equation.scale(self.tex_scale_factor)
det_equation.next_to(equation, DOWN, buff=MED_LARGE_BUFF, aligned_edge=LEFT)
det_equation.next_to(
equation, DOWN, buff=MED_LARGE_BUFF, aligned_edge=LEFT)
det_rect = BackgroundRectangle(det_equation)
self.play(
FadeIn(det_rect),
@ -727,7 +734,8 @@ class ThinkOfPuzzleAsLinearCombination(SetupSimpleSystemOfEquations):
MoveToTarget(corner_rect),
FadeOut(input_vect.brackets),
ReplacementTransform(matrix.brackets, column_arrays[0].brackets),
ReplacementTransform(matrix.brackets.copy(), column_arrays[1].brackets),
ReplacementTransform(matrix.brackets.copy(),
column_arrays[1].brackets),
ReplacementTransform(columns[0], column_arrays[0].elements),
ReplacementTransform(columns[1], column_arrays[1].elements),
Write(plus, rate_func=squish_rate_func(smooth, 0.5, 1)),
@ -750,7 +758,8 @@ class ThinkOfPuzzleAsLinearCombination(SetupSimpleSystemOfEquations):
basis.ghost.set_color(average_color(basis.get_color(), BLACK))
self.add_foreground_mobjects(basis.ghost, basis)
basis.generate_target()
basis_coords = np.array(self.plane.point_to_coords(basis.get_end()))
basis_coords = np.array(
self.plane.point_to_coords(basis.get_end()))
new_coords = scalar * basis_coords
basis.target.put_start_and_end_on(
origin, self.plane.coords_to_point(*new_coords),
@ -825,7 +834,8 @@ class LookAtDotProducts(SetupSimpleSystemOfEquations):
equations.add(equation)
equations.arrange_submobjects(DOWN, buff=MED_LARGE_BUFF)
equations.to_corner(UL)
corner_rect = self.corner_rect = BackgroundRectangle(equations, opacity=0.8)
corner_rect = self.corner_rect = BackgroundRectangle(
equations, opacity=0.8)
self.resize_corner_rect_to_mobjet(corner_rect, equations)
corner_rect.save_state()
self.resize_corner_rect_to_mobjet(corner_rect, equations[0])
@ -946,7 +956,8 @@ class LookAtDotProducts(SetupSimpleSystemOfEquations):
MoveToTarget(moving_equations[0]),
LaggedStart(FadeIn, transformed_equations[0].parts_to_write),
FadeIn(self.column_mobs),
ReplacementTransform(self.input_vect_mob.copy(), self.output_vect_mob)
ReplacementTransform(
self.input_vect_mob.copy(), self.output_vect_mob)
])
self.play(
MoveToTarget(moving_equations[1]),
@ -991,8 +1002,10 @@ class LookAtDotProducts(SetupSimpleSystemOfEquations):
# Helpers
def resize_corner_rect_to_mobjet(self, rect, mobject):
rect.stretch_to_fit_width(mobject.get_width() + MED_LARGE_BUFF + SMALL_BUFF)
rect.stretch_to_fit_height(mobject.get_height() + MED_LARGE_BUFF + SMALL_BUFF)
rect.stretch_to_fit_width(
mobject.get_width() + MED_LARGE_BUFF + SMALL_BUFF)
rect.stretch_to_fit_height(
mobject.get_height() + MED_LARGE_BUFF + SMALL_BUFF)
rect.to_corner(UL, buff=0)
return rect
@ -1169,7 +1182,8 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
output_vect_label = system.output_vect_mob.copy()
output_vect_label.add_background_rectangle()
output_vect_label.scale(self.array_scale_factor)
output_vect_label.next_to(output_vect_mob.get_end(), RIGHT, buff=SMALL_BUFF)
output_vect_label.next_to(
output_vect_mob.get_end(), RIGHT, buff=SMALL_BUFF)
input_vect = np.dot(np.linalg.inv(matrix), output_vect)
input_vect_mob = self.get_vector(input_vect, color=INPUT_COLOR)
@ -1216,7 +1230,8 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
self.apply_inverse(matrix, added_anims=[
FadeOut(column_mobs),
ReplacementTransform(output_vect_mob.copy(), input_vect_mob),
ReplacementTransform(output_dashed_lines.copy(), input_dashed_lines),
ReplacementTransform(
output_dashed_lines.copy(), input_dashed_lines),
FadeIn(input_vect_label),
])
self.wait()
@ -1224,7 +1239,8 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
self.apply_matrix(matrix, added_anims=[
FadeOut(input_vect_label),
ReplacementTransform(input_vect_mob.copy(), output_vect_mob),
ReplacementTransform(input_dashed_lines.copy(), output_dashed_lines),
ReplacementTransform(input_dashed_lines.copy(),
output_dashed_lines),
FadeIn(column_mobs),
])
@ -1241,7 +1257,8 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
TexMobject("\\cdot"),
moving_column_mob.generate_target()
)
equation.movers = VGroup(moving_var, moving_output_vect_label, moving_column_mob)
equation.movers = VGroup(
moving_var, moving_output_vect_label, moving_column_mob)
equation.to_write = equation[1::2]
equation[2].match_height(equation[4])
equation.arrange_submobjects(RIGHT, buff=SMALL_BUFF)
@ -1255,7 +1272,8 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
self.play(
FadeIn(equation.background_rectangle),
Write(equation.to_write),
LaggedStart(MoveToTarget, equation.movers, path_arc=60 * DEGREES),
LaggedStart(MoveToTarget, equation.movers,
path_arc=60 * DEGREES),
)
self.wait()
@ -1281,3 +1299,594 @@ class SolvingASystemWithOrthonormalMatrix(LinearTransformationScene):
]
for i, cm in enumerate(column_mobs)
]))
class TransitionToParallelogramIdea(TeacherStudentsScene):
def construct(self):
teacher_words = TextMobject(
"Now ask about \\\\ other geometric \\\\ views of",
"$x$", "and", "$y$"
)
teacher_words.set_color_by_tex_to_color_map({
"$x$": X_COLOR,
"$y$": Y_COLOR,
})
self.student_says(
"But that's a super \\\\ specific case",
target_mode="sassy",
added_anims=[self.teacher.change, "guilty"]
)
self.change_student_modes("confused", "sassy", "angry")
self.wait()
self.teacher_says(
teacher_words,
added_anims=[self.get_student_changes(*["pondering"] * 3)]
)
self.wait()
class TransformingAreasYCoord(LinearTransformationScene):
CONFIG = {
# Determines whether x-coordinate or y-coordinate is computed
"index": 1,
"matrix": [[2, -1], [0, 1]],
"input_vect": [3, 2],
"array_scale_factor": 0.7,
}
def construct(self):
self.init_matrix()
self.init_plane()
self.show_coord_parallelogram()
self.transform_space()
self.solve_for_coord()
def init_matrix(self):
self.matrix = np.array(self.matrix)
def init_plane(self):
self.plane.set_stroke(width=2)
def show_coord_parallelogram(self):
index = self.index
non_index = (index + 1) % 2
input_vect = self.input_vect
input_vect_mob = self.get_vector(input_vect, color=INPUT_COLOR)
input_vect_label = Matrix(["x", "y"])
input_vect_label.add_background_rectangle()
input_vect_label.scale(self.array_scale_factor)
self.set_input_vect_label_position(input_vect_mob, input_vect_label)
mystery_words = TextMobject("Mystery input vector")
mystery_words.next_to(input_vect_label, RIGHT)
mystery_words.add_background_rectangle()
# Add basis vector labels
basis_labels = self.basis_labels = VGroup()
basis_vectors = self.basis_vectors
chars = ["\\imath", "\\jmath"]
directions = ["right", "left"]
for basis, char, direction in zip(basis_vectors, chars, directions):
label = self.get_vector_label(
basis, "\\mathbf{\\hat{%s}}" % char,
direction=direction
)
self.basis_labels.add(label)
ip = self.get_input_parallelogram(input_vect_mob)
area_arrow_direction = 1.5 * DOWN + RIGHT if self.index == 0 else DR
area_arrow = Vector(
area_arrow_direction, color=WHITE,
rectangular_stem_width=0.025,
tip_length=0.2,
)
area_arrow.shift(ip.get_center() - area_arrow.get_end() + SMALL_BUFF * DL)
area_words = TexMobject(
"\\text{Area}", "=", "1", "\\times",
["x", "y"][index]
)
area_words.next_to(
area_arrow.get_start(), UL, SMALL_BUFF,
submobject_to_align=area_words[0]
)
area_words.set_color_by_tex_to_color_map({
"Area": YELLOW,
"x": X_COLOR,
"y": Y_COLOR,
})
area_words.rect = BackgroundRectangle(area_words)
origin = self.plane.coords_to_point(0, 0)
unit_brace = Brace(
Line(origin, basis_vectors[non_index].get_end()),
[DOWN, LEFT][non_index],
buff=SMALL_BUFF
)
one = unit_brace.get_tex("1")
one.add_background_rectangle()
coord_brace = self.get_parallelogram_braces(ip)[index]
self.add(input_vect_mob, input_vect_label)
self.add(basis_labels)
self.play(
FadeIn(ip),
Animation(VGroup(basis_vectors, input_vect_mob))
)
self.play(
ShowCreationThenDestruction(SurroundingRectangle(basis_labels[non_index])),
GrowArrow(self.basis_vectors[non_index].copy(), remover=True)
)
self.play(
ShowCreationThenDestruction(SurroundingRectangle(input_vect_label)),
GrowArrow(input_vect_mob.copy(), remover=True),
)
self.wait()
self.play(
FadeIn(area_words.rect),
Write(area_words[:2]),
GrowArrow(area_arrow),
)
self.wait()
self.play(
FadeOut(basis_labels),
GrowFromCenter(unit_brace),
FadeIn(one),
FadeIn(area_words[2])
)
self.wait()
self.play(
GrowFromCenter(coord_brace),
FadeIn(coord_brace.label),
FadeIn(area_words[3:]),
)
self.wait()
self.play(
area_words.rect.stretch_to_fit_width,
area_words[:3].get_width() + SMALL_BUFF, {"about_edge": LEFT},
FadeOut(area_words[2:4]),
area_words[4].shift,
(area_words[2].get_left()[0] - area_words[4].get_left()[0]) * RIGHT,
Animation(area_words[:2]),
)
area_words.remove(*area_words[2:4])
self.wait()
# Run with me
morty = Mortimer(height=2).flip()
morty.to_corner(DL)
randy = Randolph(height=2, color=BLUE_C).flip()
randy.move_to(4 * RIGHT)
randy.to_edge(DOWN)
self.play(FadeIn(randy))
self.play(randy.change, "confused", ip)
self.play(Blink(randy), FadeIn(morty))
self.play(
PiCreatureSays(morty, "Run with \\\\ me here...", look_at_arg=randy.eyes),
randy.look_at, morty.eyes,
)
self.play(Blink(morty))
self.play(FadeOut(VGroup(morty, morty.bubble, morty.bubble.content, randy)))
# Signed area
signed = TextMobject("Signed")
signed.match_color(area_words[0])
signed.next_to(area_words, LEFT)
brace_group = VGroup(coord_brace, coord_brace.label)
def update_brace_group(brace_group):
new_brace = self.get_parallelogram_braces(ip)[index]
new_group = VGroup(new_brace, new_brace.label)
Transform(brace_group, new_group).update(1)
area_words.add_to_back(signed)
self.play(
area_words.rect.stretch_to_fit_width, area_words.get_width(),
{"about_edge": RIGHT},
Write(signed),
Animation(area_words),
)
self.play(
UpdateFromFunc(
ip, lambda m: Transform(m, self.get_input_parallelogram(input_vect_mob)).update(1)
),
input_vect_mob.rotate, np.pi, {"about_point": origin},
Animation(self.basis_vectors),
UpdateFromFunc(brace_group, update_brace_group),
UpdateFromFunc(
input_vect_label,
lambda ivl: self.set_input_vect_label_position(input_vect_mob, ivl)
),
MaintainPositionRelativeTo(area_arrow, ip),
MaintainPositionRelativeTo(area_words.rect, area_arrow),
MaintainPositionRelativeTo(area_words, area_arrow),
run_time=9,
rate_func=there_and_back_with_pause,
)
# Fade out unneeded bits
self.play(LaggedStart(FadeOut, VGroup(
unit_brace, one, coord_brace, coord_brace.label,
)))
self.input_parallelogram = ip
self.area_words = area_words
self.area_arrow = area_arrow
self.input_vect_mob = input_vect_mob
self.input_vect_label = input_vect_label
def transform_space(self):
matrix = self.matrix
ip = self.input_parallelogram
area_words = self.area_words
area_arrow = self.area_arrow
input_vect_mob = self.input_vect_mob
input_vect_label = self.input_vect_label
basis_vectors = self.basis_vectors
index = self.index
non_index = (index + 1) % 2
apply_words = TextMobject("Apply")
apply_words.add_background_rectangle()
matrix_mobject = IntegerMatrix(self.matrix)
matrix_mobject.set_color_columns(X_COLOR, Y_COLOR)
matrix_mobject.add_background_rectangle()
matrix_mobject.next_to(apply_words, RIGHT)
matrix_brace = Brace(matrix_mobject, DOWN, buff=SMALL_BUFF)
matrix_label = matrix_brace.get_tex("A")
matrix_label.add_background_rectangle()
apply_group = VGroup(apply_words, matrix_mobject, matrix_brace, matrix_label)
apply_group.to_corner(UL, buff=MED_SMALL_BUFF)
area_scale_words = TextMobject("All areas get scaled by", "$\\det(A)$")
area_scale_words.scale(1.5)
area_scale_words.move_to(2 * DOWN)
area_scale_words.add_background_rectangle()
blobs = VGroup(
Circle(radius=0.5).move_to(2 * LEFT + UP),
Square(side_length=1).rotate(TAU / 12).move_to(2 * UP + 0.5 * RIGHT),
TexMobject("\\pi").scale(3).move_to(3 * RIGHT)
)
blobs.set_stroke(YELLOW, 3)
blobs.set_fill(YELLOW, 0.3)
# Initial transform
self.add_transformable_mobject(ip)
self.add(self.basis_vectors)
self.add_vector(input_vect_mob, animate=False)
self.play(
Write(apply_words), FadeIn(matrix_mobject),
GrowFromCenter(matrix_brace), Write(matrix_label),
)
self.add_foreground_mobjects(apply_group)
self.play(*map(FadeOut, [
area_words.rect, area_words, area_arrow, input_vect_label,
]))
self.apply_matrix(matrix)
self.wait(2)
self.apply_inverse(matrix, run_time=0)
# Show many areas
self.play(
LaggedStart(DrawBorderThenFill, blobs),
Write(area_scale_words)
)
self.add_transformable_mobject(blobs)
self.add_foreground_mobject(area_scale_words)
self.apply_matrix(matrix)
# Ask about parallelogram
ip_copy = ip.copy()
ip_copy.set_stroke(BLACK, 4)
ip_copy.set_fill(BLACK, 0)
q_marks = TexMobject("???")
q_marks.scale(1.5)
q_marks.rect = BackgroundRectangle(q_marks)
q_marks_group = VGroup(q_marks, q_marks.rect)
q_marks_group.rotate(input_vect_mob.get_angle())
q_marks_group.move_to(ip)
column_mobs = VGroup()
for i, vect in zip(range(2), [DOWN, LEFT]):
column = matrix_mobject.deepcopy().mob_matrix[:, i]
column_mob = MobjectMatrix(column)
column_mob.scale(self.array_scale_factor)
column_mob.next_to(basis_vectors[i].get_end(), vect)
column_mob.add_background_rectangle()
column_mobs.add(column_mob)
column_mob = column_mobs[non_index]
transformed_input_vect_label = VGroup(input_vect_label.copy())
transformed_input_vect_label.add_to_back(matrix_label.copy())
transformed_input_vect_label.arrange_submobjects(RIGHT, buff=SMALL_BUFF)
transformed_input_vect_label.next_to(input_vect_mob.get_end(), UP)
self.play(
ShowPassingFlash(ip_copy),
FadeIn(q_marks.rect),
Animation(ip),
Animation(basis_vectors),
Animation(input_vect_mob),
Write(q_marks),
LaggedStart(FadeOut, blobs),
)
self.transformable_mobjects.remove(blobs)
self.play(
FadeIn(column_mob.background_rectangle),
ReplacementTransform(
matrix_mobject.brackets.copy(), column_mob.brackets
),
ReplacementTransform(
VGroup(*matrix_mobject.mob_matrix[:, non_index]).copy(),
column_mob.elements
),
)
self.wait()
self.play(
ReplacementTransform(matrix_label.copy(), transformed_input_vect_label[0]),
FadeIn(transformed_input_vect_label[1])
)
self.wait(2)
# Back to input state
self.remove(q_marks.rect)
self.apply_inverse(matrix, added_anims=[
FadeOut(q_marks),
FadeOut(transformed_input_vect_label),
FadeOut(column_mob),
FadeIn(area_words.rect),
FadeIn(area_words),
FadeIn(area_arrow),
])
self.wait(2)
# Show how parallelogram scales by det(A)
self.apply_matrix(matrix, added_anims=[
UpdateFromFunc(
area_arrow,
lambda a: a.put_start_and_end_on(
area_arrow.get_start(), ip.get_center() + SMALL_BUFF * DL
)
),
Animation(area_words.rect),
Animation(area_words),
])
det_A = area_scale_words.get_part_by_tex("det").copy()
det_A.generate_target()
det_A.target.scale(1.0 / 1.5)
det_A.target.next_to(
area_words[1:3], RIGHT, SMALL_BUFF,
aligned_edge=DOWN,
submobject_to_align=det_A.target[0]
)
coord = area_words[-1]
coord.generate_target()
coord.target.next_to(det_A.target, RIGHT, SMALL_BUFF)
self.play(
area_words.rect.match_width, VGroup(area_words, coord.target),
{"stretch": True, "about_edge": LEFT},
Animation(area_words),
MoveToTarget(det_A),
MoveToTarget(coord),
)
self.wait(2)
area_words.submobjects.insert(-1, det_A)
self.area_scale_words = area_scale_words
self.apply_group = apply_group
def solve_for_coord(self):
apply_group = self.apply_group
area_words = self.area_words.copy()
index = self.index
non_index = (index + 1) % 2
# Setup rearrangement
signed, area, equals, det, coord = area_words
for part in area_words:
part.add_background_rectangle()
part.generate_target()
apply_word, matrix_mobject, matrix_brace, matrix_label = apply_group
h_line = Line(LEFT, RIGHT).match_width(det)
frac = VGroup(area.target, h_line, det.target)
frac.arrange_submobjects(DOWN)
coord_equation = VGroup(coord.target, equals.target, frac)
equals.target.next_to(coord.target, RIGHT)
frac.next_to(equals.target, RIGHT, submobject_to_align=h_line)
coord_equation.next_to(ORIGIN, DOWN, buff=1.2)
coord_equation.to_edge(LEFT)
output_vect = np.dot(self.matrix, self.input_vect)
new_matrix = np.array(self.matrix)
new_matrix[:, self.index] = output_vect
# Setup rhs
frac_matrix_height = 1.5
matrix_mobject_copy = matrix_mobject.copy()
matrix_mobject_copy.scale_to_fit_height(frac_matrix_height)
denom_det_text = get_det_text(matrix_mobject_copy)
top_matrix_mobject = IntegerMatrix(new_matrix)
top_matrix_mobject.scale_to_fit_height(frac_matrix_height)
top_matrix_mobject.set_color_columns(X_COLOR, Y_COLOR)
VGroup(*top_matrix_mobject.mob_matrix[:, self.index]).set_color(MAROON_B)
top_matrix_mobject.add_background_rectangle()
num_det_text = get_det_text(top_matrix_mobject)
rhs_h_line = Line(LEFT, RIGHT)
rhs_h_line.match_width(num_det_text)
rhs = VGroup(
VGroup(num_det_text, top_matrix_mobject),
rhs_h_line,
VGroup(matrix_mobject_copy, denom_det_text)
)
rhs.arrange_submobjects(DOWN, buff=SMALL_BUFF)
rhs_equals = TexMobject("=")
rhs_equals.next_to(h_line, RIGHT)
rhs.next_to(rhs_equals, submobject_to_align=rhs_h_line)
# Setup linear system
output_vect_label = IntegerMatrix(output_vect)
output_vect_label.elements.match_color(self.input_vect_mob)
output_vect_label.scale(self.array_scale_factor)
output_vect_label.add_background_rectangle()
self.set_input_vect_label_position(self.input_vect_mob, output_vect_label)
matrix_mobject.generate_target()
system_input = Matrix(["x", "y"])
system_input.add_background_rectangle()
system_output = output_vect_label.copy()
system_output.generate_target()
system_eq = TexMobject("=")
for array in system_input, system_output.target:
array.match_height(matrix_mobject.target)
system = VGroup(
matrix_mobject.target,
system_input, system_eq, system_output.target
)
system.arrange_submobjects(RIGHT, buff=SMALL_BUFF)
system.to_corner(UL)
# Rearrange
self.play(
FadeOut(self.area_scale_words),
ShowCreation(h_line),
*map(MoveToTarget, area_words[1:]),
run_time=3
)
self.wait()
self.play(
ReplacementTransform(matrix_mobject.copy(), matrix_mobject_copy),
Write(rhs_equals),
Write(denom_det_text),
ShowCreation(rhs_h_line)
)
self.wait(2)
# Show output coord
self.play(
FadeIn(output_vect_label.background_rectangle),
ReplacementTransform(
self.input_vect_mob.copy(),
output_vect_label.elements,
),
Write(output_vect_label.brackets),
)
self.wait()
self.play(
FadeOut(apply_word),
MoveToTarget(matrix_mobject),
MaintainPositionRelativeTo(matrix_brace, matrix_mobject),
MaintainPositionRelativeTo(matrix_label, matrix_mobject),
)
self.play(
FadeIn(system_input),
FadeIn(system_eq),
MoveToTarget(system_output),
area_words.rect.stretch_to_fit_width, self.area_words[1:].get_width(),
{"about_edge": RIGHT},
Animation(self.area_words[1:]),
FadeOut(self.area_words[0]),
)
self.wait()
replaced_column = VGroup(*top_matrix_mobject.mob_matrix[:, self.index])
replaced_column.set_fill(opacity=0)
self.play(
ReplacementTransform(matrix_mobject_copy.copy(), top_matrix_mobject),
ReplacementTransform(denom_det_text.copy(), num_det_text),
)
self.wiggle_vector(self.basis_vectors[non_index])
self.wait()
self.wiggle_vector(self.input_vect_mob)
self.remove(replaced_column)
self.play(
Transform(
output_vect_label.elements.copy(),
replaced_column.copy().set_fill(opacity=1),
remover=True
)
)
replaced_column.set_fill(opacity=1)
self.wait()
# Circle equation
equation = VGroup(
area_words[1:], h_line,
rhs_equals, rhs,
)
equation_rect = SurroundingRectangle(equation)
equation_rect.set_stroke(YELLOW, 3)
equation_rect.set_fill(BLACK, 0.9)
self.play(
DrawBorderThenFill(equation_rect),
Animation(equation)
)
self.wait()
# Helpers
def get_input_parallelogram(self, input_vect_mob):
input_vect = np.array(self.plane.point_to_coords(input_vect_mob.get_end()))
matrix = self.matrix
dim = matrix.shape[0]
# Transofmration from unit square to input parallelogram
square_to_ip = self.square_to_ip = np.identity(dim)
square_to_ip[:, self.index] = np.array(input_vect)
ip = self.get_unit_square()
ip.apply_matrix(self.square_to_ip)
if input_vect[self.index] < 0:
ip.set_color(GOLD)
return ip
def get_parallelogram_braces(self, input_parallelogram):
braces = VGroup(*[
Brace(
input_parallelogram, vect,
buff=SMALL_BUFF,
min_num_quads=3,
max_num_quads=3,
)
for vect in DOWN, RIGHT
])
for brace, tex, color in zip(braces, "xy", [X_COLOR, Y_COLOR]):
brace.label = brace.get_tex(tex, buff=SMALL_BUFF)
brace.label.add_background_rectangle()
brace.label.set_color(color)
return braces
def set_input_vect_label_position(self, input_vect_mob, input_vect_label):
direction = np.sign(input_vect_mob.get_vector())
input_vect_label.next_to(input_vect_mob.get_end(), direction, buff=SMALL_BUFF)
return input_vect_label
def wiggle_vector(self, vector_mob):
self.play(
Rotate(
vector_mob, 15 * DEGREES,
about_point=ORIGIN,
rate_func=wiggle,
)
)
class TransformingAreasXCoord(TransformingAreasYCoord):
CONFIG = {
"index": 0,
}
class WriteCramersRule(Scene):
def construct(self):
words = TextMobject("``Cramer's Rule''")
words.scale_to_fit_width(FRAME_WIDTH - LARGE_BUFF)
self.play(Write(words))
self.wait()