mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
300 lines
8.9 KiB
Python
300 lines
8.9 KiB
Python
![]() |
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 animation.playground import *
|
||
|
from topics.geometry import *
|
||
|
from topics.characters import *
|
||
|
from topics.functions import *
|
||
|
from topics.number_line import *
|
||
|
from topics.combinatorics import *
|
||
|
from scene import Scene
|
||
|
from camera import Camera
|
||
|
from mobject.svg_mobject import *
|
||
|
from mobject.tex_mobject import *
|
||
|
|
||
|
from eola.utils import *
|
||
|
|
||
|
EXAMPLE_TRANFORM = [[0, 1], [-1, 1]]
|
||
|
TRANFORMED_VECTOR = [[1], [2]]
|
||
|
|
||
|
class OpeningQuote(Scene):
|
||
|
def construct(self):
|
||
|
words = TextMobject(
|
||
|
"""
|
||
|
``There is hardly any theory which is more elementary
|
||
|
than linear algebra, in spite of the fact that generations
|
||
|
of professors and textbook writers have obscured its
|
||
|
simplicity by preposterous calculations with matrices.''
|
||
|
""",
|
||
|
organize_left_to_right = False
|
||
|
)
|
||
|
words.scale_to_fit_width(2*(SPACE_WIDTH-1))
|
||
|
words.to_edge(UP)
|
||
|
for mob in words.submobjects[48:49+13]:
|
||
|
mob.highlight(GREEN)
|
||
|
words.show()
|
||
|
author = TextMobject("-Hermann Weyl")
|
||
|
author.highlight(YELLOW)
|
||
|
author.next_to(words, DOWN)
|
||
|
|
||
|
self.play(Write(words))
|
||
|
self.dither()
|
||
|
self.play(FadeIn(author))
|
||
|
self.dither()
|
||
|
|
||
|
|
||
|
class AboutLinearAlgebra(Scene):
|
||
|
def construct(self):
|
||
|
self.show_dependencies()
|
||
|
self.linalg_is_confusing()
|
||
|
self.ask_questions()
|
||
|
|
||
|
def show_dependencies(self):
|
||
|
linalg = TextMobject("Linear Algebra")
|
||
|
subjects = map(TextMobject, [
|
||
|
"Computer science",
|
||
|
"Physics",
|
||
|
"Electrical engineering",
|
||
|
"Mechanical engineering",
|
||
|
"Statistics",
|
||
|
"\\vdots"
|
||
|
])
|
||
|
prev = subjects[0]
|
||
|
for subject in subjects[1:]:
|
||
|
subject.next_to(prev, DOWN, aligned_edge = LEFT)
|
||
|
prev = subject
|
||
|
all_subs = VMobject(*subjects)
|
||
|
linalg.to_edge(LEFT)
|
||
|
all_subs.next_to(linalg, RIGHT, buff = 2)
|
||
|
arrows = VMobject(*[
|
||
|
Arrow(linalg, sub)
|
||
|
for sub in subjects
|
||
|
])
|
||
|
|
||
|
self.play(Write(linalg, run_time = 1))
|
||
|
self.dither()
|
||
|
self.play(
|
||
|
ShowCreation(arrows, submobject_mode = "lagged_start"),
|
||
|
FadeIn(all_subs),
|
||
|
run_time = 2
|
||
|
)
|
||
|
self.dither()
|
||
|
self.linalg = linalg
|
||
|
|
||
|
def linalg_is_confusing(self):
|
||
|
linalg = self.linalg
|
||
|
all_else = list(self.mobjects)
|
||
|
all_else.remove(linalg)
|
||
|
randy = Randolph()
|
||
|
randy.to_corner()
|
||
|
bubble = randy.get_bubble(width = 10)
|
||
|
new_linalg = bubble.position_mobject_inside(linalg.copy())
|
||
|
|
||
|
self.play(*map(FadeOut, all_else))
|
||
|
self.remove(*all_else)
|
||
|
self.play(
|
||
|
Transform(linalg, new_linalg),
|
||
|
Write(bubble),
|
||
|
FadeIn(randy)
|
||
|
)
|
||
|
self.play(ApplyMethod(randy.change_mode, "confused"))
|
||
|
self.dither()
|
||
|
self.play(Blink(randy))
|
||
|
self.play(FadeOut(linalg))
|
||
|
self.remove(linalg)
|
||
|
|
||
|
self.randy, self.bubble = randy, bubble
|
||
|
|
||
|
def ask_questions(self):
|
||
|
randy, bubble = self.randy, self.bubble
|
||
|
matrix_multiplication = TexMobject("""
|
||
|
\\left[
|
||
|
\\begin{array}{cc}
|
||
|
a & b \\\\
|
||
|
c & d
|
||
|
\\end{array}
|
||
|
\\right]
|
||
|
\\left[
|
||
|
\\begin{array}{cc}
|
||
|
e & f \\\\
|
||
|
g & h
|
||
|
\\end{array}
|
||
|
\\right]
|
||
|
=
|
||
|
\\left[
|
||
|
\\begin{array}{cc}
|
||
|
ae + bg & af + bh \\\\
|
||
|
ce + dg & cf + dh
|
||
|
\\end{array}
|
||
|
\\right]
|
||
|
""")
|
||
|
|
||
|
cross = TexMobject("\\vec{v} \\times \\vec{w}")
|
||
|
left_right_arrow = DoubleArrow(Point(LEFT), Point(RIGHT))
|
||
|
det = TextMobject("Det")
|
||
|
q_mark = TextMobject("?")
|
||
|
left_right_arrow.next_to(cross)
|
||
|
det.next_to(left_right_arrow)
|
||
|
q_mark.next_to(left_right_arrow, UP)
|
||
|
cross_question = VMobject(cross, left_right_arrow, q_mark, det)
|
||
|
cross_question.get_center = lambda : left_right_arrow.get_center()
|
||
|
|
||
|
eigen_q = TextMobject("Eigen?")
|
||
|
|
||
|
for mob in matrix_multiplication, cross_question, eigen_q:
|
||
|
bubble.position_mobject_inside(mob)
|
||
|
self.play(FadeIn(mob))
|
||
|
if randy.mode is not "pondering":
|
||
|
self.play(ApplyMethod(randy.change_mode, "pondering"))
|
||
|
self.dither()
|
||
|
else:
|
||
|
self.dither(2)
|
||
|
self.remove(mob)
|
||
|
|
||
|
|
||
|
|
||
|
class NumericVsGeometric(Scene):
|
||
|
def construct(self):
|
||
|
self.setup()
|
||
|
self.specifics_concepts()
|
||
|
self.clear_way_for_geometric()
|
||
|
self.list_geometric_benefits()
|
||
|
|
||
|
def setup(self):
|
||
|
numeric = TextMobject("Numeric operations")
|
||
|
geometric = TextMobject("Geometric intuition")
|
||
|
for mob in numeric, geometric:
|
||
|
mob.to_corner(UP+LEFT)
|
||
|
geometric.shift(SPACE_WIDTH*RIGHT)
|
||
|
hline = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT)
|
||
|
hline.next_to(numeric, DOWN)
|
||
|
hline.to_edge(LEFT, buff = 0)
|
||
|
vline = Line(SPACE_HEIGHT*UP, SPACE_HEIGHT*DOWN)
|
||
|
for mob in hline, vline:
|
||
|
mob.highlight(GREEN)
|
||
|
|
||
|
self.play(ShowCreation(VMobject(hline, vline)))
|
||
|
digest_locals(self)
|
||
|
|
||
|
def specifics_concepts(self):
|
||
|
matrix_vector_product = TexMobject(" ".join([
|
||
|
matrix_to_tex_string(EXAMPLE_TRANFORM),
|
||
|
matrix_to_tex_string(TRANFORMED_VECTOR),
|
||
|
"&=",
|
||
|
matrix_to_tex_string([
|
||
|
["1 \\cdot 1 + 0 \\cdot 2"],
|
||
|
["1 \\cdot 1 + (-1)\\cdot 2"]
|
||
|
]),
|
||
|
"\\\\ &=",
|
||
|
matrix_to_tex_string([[1], [-1]]),
|
||
|
]))
|
||
|
matrix_vector_product.scale_to_fit_width(SPACE_WIDTH-0.5)
|
||
|
matrix_vector_product.next_to(self.vline, LEFT)
|
||
|
|
||
|
self.play(
|
||
|
Write(self.numeric),
|
||
|
FadeIn(matrix_vector_product),
|
||
|
run_time = 2
|
||
|
)
|
||
|
self.dither()
|
||
|
self.play(Write(self.geometric, run_time = 2))
|
||
|
### Paste in linear transformation
|
||
|
self.dither()
|
||
|
digest_locals(self)
|
||
|
|
||
|
def clear_way_for_geometric(self):
|
||
|
new_line = Line(SPACE_HEIGHT*LEFT, SPACE_HEIGHT*RIGHT)
|
||
|
new_line.shift((SPACE_HEIGHT+1)*DOWN)
|
||
|
self.play(
|
||
|
Transform(self.vline, new_line),
|
||
|
Transform(self.hline, new_line),
|
||
|
ApplyMethod(self.numeric.shift, (2*SPACE_HEIGHT+1)*DOWN),
|
||
|
ApplyMethod(
|
||
|
self.matrix_vector_product.shift,
|
||
|
(2*SPACE_HEIGHT+1)*DOWN
|
||
|
),
|
||
|
ApplyMethod(self.geometric.to_edge, LEFT)
|
||
|
)
|
||
|
|
||
|
def list_geometric_benefits(self):
|
||
|
follow_words = TextMobject("is helpful for \\dots")
|
||
|
follow_words.next_to(self.geometric)
|
||
|
#Ugly hack
|
||
|
diff = follow_words.submobjects[0].get_bottom()[1] - \
|
||
|
self.geometric.submobjects[0].get_bottom()[1]
|
||
|
follow_words.shift(diff*DOWN)
|
||
|
randys = [
|
||
|
Randolph(mode = "speaking"),
|
||
|
Randolph(mode = "surprised"),
|
||
|
Randolph(mode = "pondering")
|
||
|
]
|
||
|
bulb = SVGMobject("light_bulb")
|
||
|
bulb.scale_to_fit_height(1)
|
||
|
bulb.highlight(YELLOW)
|
||
|
thoughts = [
|
||
|
matrix_to_mobject(EXAMPLE_TRANFORM),
|
||
|
bulb,
|
||
|
TextMobject("So therefore...").scale(0.5)
|
||
|
]
|
||
|
|
||
|
self.play(Write(follow_words, run_time = 1.5))
|
||
|
curr_randy = None
|
||
|
for randy, thought in zip(randys, thoughts):
|
||
|
randy.shift(DOWN)
|
||
|
thought.next_to(randy, UP+RIGHT, buff = 0)
|
||
|
if curr_randy:
|
||
|
self.play(
|
||
|
Transform(curr_randy, randy),
|
||
|
Transform(curr_thought, thought)
|
||
|
)
|
||
|
else:
|
||
|
self.play(
|
||
|
FadeIn(randy),
|
||
|
Write(thought, run_time = 1)
|
||
|
)
|
||
|
curr_randy = randy
|
||
|
curr_thought = thought
|
||
|
self.dither(1.5)
|
||
|
|
||
|
|
||
|
class ExampleTransformation(LinearTransformationScene):
|
||
|
def construct(self):
|
||
|
self.setup()
|
||
|
self.apply_matrix(EXAMPLE_TRANFORM)
|
||
|
self.dither()
|
||
|
|
||
|
|
||
|
|
||
|
class NumericToComputations(Scene):
|
||
|
def construct(self):
|
||
|
top = TextMobject("Numeric understanding")
|
||
|
arrow = Arrow(UP, DOWN)
|
||
|
bottom = TextMobject("Actual computations")
|
||
|
top.next_to(arrow, UP)
|
||
|
bottom.next_to(arrow, DOWN)
|
||
|
|
||
|
self.add(top)
|
||
|
self.play(ShowCreation(arrow, submobject_mode = "one_at_a_time"))
|
||
|
self.play(FadeIn(bottom))
|
||
|
self.dither()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|