mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 02:35:22 +08:00
1892
active_projects/eola2/cramer.py
Normal file
1892
active_projects/eola2/cramer.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,10 @@ from __future__ import absolute_import
|
||||
|
||||
import numpy as np
|
||||
|
||||
from mobject.mobject import Mobject
|
||||
from mobject.numbers import DecimalNumber
|
||||
from mobject.numbers import Integer
|
||||
from mobject.svg.tex_mobject import TexMobject
|
||||
from mobject.svg.tex_mobject import TextMobject
|
||||
from mobject.types.vectorized_mobject import VGroup
|
||||
from mobject.types.vectorized_mobject import VMobject
|
||||
from mobject.shape_matchers import BackgroundRectangle
|
||||
@ -38,7 +40,7 @@ def vector_coordinate_label(vector_mob, integer_labels=True,
|
||||
vect = np.round(vect).astype(int)
|
||||
vect = vect[:n_dim]
|
||||
vect = vect.reshape((n_dim, 1))
|
||||
label = Matrix(vect, add_background_rectangles=True)
|
||||
label = Matrix(vect, add_background_rectangles_to_entries=True)
|
||||
label.scale(VECTOR_LABEL_SCALE_FACTOR)
|
||||
|
||||
shift_dir = np.array(vector_mob.get_end())
|
||||
@ -55,9 +57,13 @@ def vector_coordinate_label(vector_mob, integer_labels=True,
|
||||
|
||||
class Matrix(VMobject):
|
||||
CONFIG = {
|
||||
"v_buff": 0.5,
|
||||
"h_buff": 1,
|
||||
"add_background_rectangles": False
|
||||
"v_buff": 0.8,
|
||||
"h_buff": 1.3,
|
||||
"add_background_rectangles_to_entries": False,
|
||||
"include_background_rectangle": False,
|
||||
"element_to_mobject": TexMobject,
|
||||
"element_to_mobject_config": {},
|
||||
"element_alignment_corner": DR,
|
||||
}
|
||||
|
||||
def __init__(self, matrix, **kwargs):
|
||||
@ -69,34 +75,34 @@ class Matrix(VMobject):
|
||||
matrix = np.array(matrix)
|
||||
if matrix.ndim == 1:
|
||||
matrix = matrix.reshape((matrix.size, 1))
|
||||
if not isinstance(matrix[0][0], Mobject):
|
||||
matrix = matrix.astype("string")
|
||||
matrix = self.string_matrix_to_mob_matrix(matrix)
|
||||
self.organize_mob_matrix(matrix)
|
||||
self.add(*matrix.flatten())
|
||||
mob_matrix = self.matrix_to_mob_matrix(matrix)
|
||||
self.organize_mob_matrix(mob_matrix)
|
||||
self.elements = VGroup(*mob_matrix.flatten())
|
||||
self.add(self.elements)
|
||||
self.add_brackets()
|
||||
self.center()
|
||||
self.mob_matrix = matrix
|
||||
if self.add_background_rectangles:
|
||||
for mob in matrix.flatten():
|
||||
self.mob_matrix = mob_matrix
|
||||
if self.add_background_rectangles_to_entries:
|
||||
for mob in self.elements:
|
||||
mob.add_background_rectangle()
|
||||
if self.include_background_rectangle:
|
||||
self.add_background_rectangle()
|
||||
|
||||
def string_matrix_to_mob_matrix(self, matrix):
|
||||
return np.array([
|
||||
map(TexMobject, row)
|
||||
for row in matrix
|
||||
]).reshape(matrix.shape)
|
||||
def matrix_to_mob_matrix(self, matrix):
|
||||
return np.vectorize(
|
||||
lambda e: self.element_to_mobject(
|
||||
e, **self.element_to_mobject_config
|
||||
)
|
||||
)(matrix)
|
||||
|
||||
def organize_mob_matrix(self, matrix):
|
||||
for i, row in enumerate(matrix):
|
||||
for j, elem in enumerate(row):
|
||||
mob = matrix[i][j]
|
||||
if i == 0 and j == 0:
|
||||
continue
|
||||
elif i == 0:
|
||||
mob.next_to(matrix[i][j - 1], RIGHT, self.h_buff)
|
||||
else:
|
||||
mob.next_to(matrix[i - 1][j], DOWN, self.v_buff)
|
||||
mob.move_to(
|
||||
i * self.v_buff * DOWN + j * self.h_buff * RIGHT,
|
||||
self.element_alignment_corner
|
||||
)
|
||||
return self
|
||||
|
||||
def add_brackets(self):
|
||||
@ -110,6 +116,10 @@ class Matrix(VMobject):
|
||||
self.brackets = VGroup(l_bracket, r_bracket)
|
||||
return self
|
||||
|
||||
def add_background_rectangle(self):
|
||||
self.background_rectangle = BackgroundRectangle(self)
|
||||
self.add_to_back(self.background_rectangle)
|
||||
|
||||
def set_color_columns(self, *colors):
|
||||
for i, color in enumerate(colors):
|
||||
VGroup(*self.mob_matrix[:, i]).set_color(color)
|
||||
@ -128,3 +138,42 @@ class Matrix(VMobject):
|
||||
|
||||
def get_brackets(self):
|
||||
return self.brackets
|
||||
|
||||
|
||||
class DecimalMatrix(Matrix):
|
||||
CONFIG = {
|
||||
"element_to_mobject": DecimalNumber,
|
||||
"element_to_mobject_config": {"num_decimal_points": 1}
|
||||
}
|
||||
|
||||
|
||||
class IntegerMatrix(Matrix):
|
||||
CONFIG = {
|
||||
"element_to_mobject": Integer,
|
||||
}
|
||||
|
||||
|
||||
class MobjectMatrix(Matrix):
|
||||
CONFIG = {
|
||||
"element_to_mobject": lambda m: m,
|
||||
}
|
||||
|
||||
|
||||
def get_det_text(matrix, determinant=None, background_rect=True, initial_scale_factor=2):
|
||||
parens = TexMobject(["(", ")"])
|
||||
parens.scale(initial_scale_factor)
|
||||
parens.stretch_to_fit_height(matrix.get_height())
|
||||
l_paren, r_paren = parens.split()
|
||||
l_paren.next_to(matrix, LEFT, buff=0.1)
|
||||
r_paren.next_to(matrix, RIGHT, buff=0.1)
|
||||
det = TextMobject("det").next_to(l_paren, LEFT, buff=0.1)
|
||||
if background_rect:
|
||||
det.add_background_rectangle()
|
||||
det_text = VMobject(det, l_paren, r_paren)
|
||||
if determinant is not None:
|
||||
eq = TexMobject("=")
|
||||
eq.next_to(r_paren, RIGHT, buff=0.1)
|
||||
result = TexMobject(str(determinant))
|
||||
result.next_to(eq, RIGHT, buff=0.2)
|
||||
det_text.add(eq, result)
|
||||
return det_text
|
||||
|
@ -887,7 +887,7 @@ class MatrixVectorMultiplication(LinearTransformationScene):
|
||||
)
|
||||
concrete_matrix = Matrix(
|
||||
copy.deepcopy(abstract_matrix),
|
||||
add_background_rectangles = True
|
||||
add_background_rectangles_to_entries = True
|
||||
)
|
||||
concrete_matrix.to_edge(UP)
|
||||
if self.abstract:
|
||||
|
@ -106,7 +106,7 @@ class FollowLinearCombination(LinearTransformationScene):
|
||||
direction = "right", color = Y_COLOR
|
||||
)
|
||||
vect = self.add_vector(vect_coords)
|
||||
vect_array = Matrix(["x", "y"], add_background_rectangles = True)
|
||||
vect_array = Matrix(["x", "y"], add_background_rectangles_to_entries = True)
|
||||
v_equals = TexMobject(["\\vec{\\textbf{v}}", "="])
|
||||
v_equals.split()[0].set_color(YELLOW)
|
||||
v_equals.next_to(vect_array, LEFT)
|
||||
|
@ -1,24 +1,6 @@
|
||||
from big_ol_pile_of_manim_imports import *
|
||||
from eola.chapter3 import MatrixVectorMultiplicationAbstract
|
||||
|
||||
def get_det_text(matrix, determinant = None, background_rect = True):
|
||||
parens = TexMobject(["(", ")"])
|
||||
parens.scale(2)
|
||||
parens.stretch_to_fit_height(matrix.get_height())
|
||||
l_paren, r_paren = parens.split()
|
||||
l_paren.next_to(matrix, LEFT, buff = 0.1)
|
||||
r_paren.next_to(matrix, RIGHT, buff = 0.1)
|
||||
det = TextMobject("det").next_to(l_paren, LEFT, buff = 0.1)
|
||||
if background_rect:
|
||||
det.add_background_rectangle()
|
||||
det_text = VMobject(det, l_paren, r_paren)
|
||||
if determinant is not None:
|
||||
eq = TexMobject("=")
|
||||
eq.next_to(r_paren, RIGHT, buff = 0.1)
|
||||
result = TexMobject(str(determinant))
|
||||
result.next_to(eq, RIGHT, buff = 0.2)
|
||||
det_text.add(eq, result)
|
||||
return det_text
|
||||
|
||||
class Blob(Circle):
|
||||
CONFIG = {
|
||||
|
@ -10,6 +10,7 @@ from animation.creation import Write
|
||||
from animation.transform import ApplyFunction
|
||||
from animation.transform import ApplyPointwiseFunction
|
||||
from animation.creation import FadeOut
|
||||
from animation.creation import GrowArrow
|
||||
from animation.transform import Transform
|
||||
from mobject.mobject import Mobject
|
||||
from mobject.svg.tex_mobject import TexMobject
|
||||
@ -20,7 +21,7 @@ from scene.scene import Scene
|
||||
from mobject.geometry import Arrow
|
||||
from mobject.geometry import Dot
|
||||
from mobject.geometry import Line
|
||||
from mobject.geometry import Square
|
||||
from mobject.geometry import Rectangle
|
||||
from mobject.geometry import Vector
|
||||
from mobject.coordinate_systems import Axes
|
||||
from mobject.coordinate_systems import NumberPlane
|
||||
@ -37,6 +38,12 @@ Y_COLOR = RED_C
|
||||
Z_COLOR = BLUE_D
|
||||
|
||||
|
||||
# TODO: Much of this scene type seems dependent on the coordinate system chosen.
|
||||
# That is, being centered at the origin with grid units corresponding to the
|
||||
# arbitrary space units. Change it!
|
||||
#
|
||||
# Also, methods I would have thought of as getters, like coords_to_vector, are
|
||||
# actually doing a lot of animating.
|
||||
class VectorScene(Scene):
|
||||
CONFIG = {
|
||||
"basis_vector_stroke_width": 6
|
||||
@ -65,11 +72,19 @@ class VectorScene(Scene):
|
||||
self.add(axes)
|
||||
self.freeze_background()
|
||||
|
||||
def get_vector(self, numerical_vector, **kwargs):
|
||||
return Arrow(
|
||||
self.plane.coords_to_point(0, 0),
|
||||
self.plane.coords_to_point(*numerical_vector[:2]),
|
||||
buff=0,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def add_vector(self, vector, color=YELLOW, animate=True, **kwargs):
|
||||
if not isinstance(vector, Arrow):
|
||||
vector = Vector(vector, color=color, **kwargs)
|
||||
if animate:
|
||||
self.play(ShowCreation(vector))
|
||||
self.play(GrowArrow(vector))
|
||||
self.add(vector)
|
||||
return vector
|
||||
|
||||
@ -106,6 +121,7 @@ class VectorScene(Scene):
|
||||
])
|
||||
|
||||
def get_vector_label(self, vector, label,
|
||||
at_tip=False,
|
||||
direction="left",
|
||||
rotate=False,
|
||||
color=None,
|
||||
@ -120,6 +136,11 @@ class VectorScene(Scene):
|
||||
label.scale(label_scale_factor)
|
||||
label.add_background_rectangle()
|
||||
|
||||
if at_tip:
|
||||
vect = vector.get_vector()
|
||||
vect /= np.linalg.norm(vect)
|
||||
label.next_to(vector.get_end(), vect, buff=SMALL_BUFF)
|
||||
else:
|
||||
angle = vector.get_angle()
|
||||
if not rotate:
|
||||
label.rotate(-angle, about_point=ORIGIN)
|
||||
@ -281,10 +302,10 @@ class LinearTransformationScene(VectorScene):
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
# The has_already_setup attr is to not break all the old Scenes
|
||||
if hasattr(self, "has_already_setup"):
|
||||
return
|
||||
self.has_already_setup = True
|
||||
# ^This is to not break all the old Scenes
|
||||
self.background_mobjects = []
|
||||
self.foreground_mobjects = []
|
||||
self.transformable_mobjects = []
|
||||
@ -311,6 +332,7 @@ class LinearTransformationScene(VectorScene):
|
||||
)
|
||||
self.moving_vectors += list(self.basis_vectors)
|
||||
self.i_hat, self.j_hat = self.basis_vectors
|
||||
self.add(self.basis_vectors)
|
||||
|
||||
def add_special_mobjects(self, mob_list, *mobs_to_add):
|
||||
for mobject in mobs_to_add:
|
||||
@ -321,6 +343,7 @@ class LinearTransformationScene(VectorScene):
|
||||
def add_background_mobject(self, *mobjects):
|
||||
self.add_special_mobjects(self.background_mobjects, *mobjects)
|
||||
|
||||
# TODO, this conflicts with Scene.add_fore
|
||||
def add_foreground_mobject(self, *mobjects):
|
||||
self.add_special_mobjects(self.foreground_mobjects, *mobjects)
|
||||
|
||||
@ -331,15 +354,26 @@ class LinearTransformationScene(VectorScene):
|
||||
mobject.target = target_mobject
|
||||
self.add_special_mobjects(self.moving_mobjects, mobject)
|
||||
|
||||
def add_unit_square(self, color=YELLOW, opacity=0.3, animate=False):
|
||||
square = Square(color=color, side_length=1)
|
||||
square.shift(-square.get_corner(DOWN + LEFT))
|
||||
def get_unit_square(self, color=YELLOW, opacity=0.3, stroke_width=3):
|
||||
square = Rectangle(
|
||||
color=color,
|
||||
width=self.plane.get_x_unit_size(),
|
||||
height=self.plane.get_y_unit_size(),
|
||||
stroke_color=color,
|
||||
stroke_width=stroke_width,
|
||||
fill_color=color,
|
||||
fill_opacity=opacity
|
||||
)
|
||||
square.move_to(self.plane.coords_to_point(0, 0), DL)
|
||||
return square
|
||||
|
||||
def add_unit_square(self, animate=False, **kwargs):
|
||||
square = self.get_unit_square(**kwargs)
|
||||
if animate:
|
||||
added_anims = map(Animation, self.moving_vectors)
|
||||
self.play(ShowCreation(square), *added_anims)
|
||||
self.play(square.set_fill, color, opacity, *added_anims)
|
||||
else:
|
||||
square.set_fill(color, opacity)
|
||||
self.play(
|
||||
DrawBorderThenFill(square),
|
||||
Animation(Group(*self.moving_vectors))
|
||||
)
|
||||
self.add_transformable_mobject(square)
|
||||
self.bring_to_front(*self.moving_vectors)
|
||||
self.square = square
|
||||
@ -357,12 +391,19 @@ class LinearTransformationScene(VectorScene):
|
||||
self.add_foreground_mobject(coords)
|
||||
return coords
|
||||
|
||||
def add_transformable_label(self, vector, label, new_label=None, **kwargs):
|
||||
def add_transformable_label(
|
||||
self, vector, label,
|
||||
transformation_name="L",
|
||||
new_label=None,
|
||||
**kwargs):
|
||||
label_mob = self.label_vector(vector, label, **kwargs)
|
||||
if new_label:
|
||||
label_mob.target_text = new_label
|
||||
else:
|
||||
label_mob.target_text = "L(%s)" % label_mob.get_tex_string()
|
||||
label_mob.target_text = "%s(%s)" % (
|
||||
transformation_name,
|
||||
label_mob.get_tex_string()
|
||||
)
|
||||
label_mob.vector = vector
|
||||
label_mob.kwargs = kwargs
|
||||
if "animate" in label_mob.kwargs:
|
||||
@ -427,6 +468,9 @@ class LinearTransformationScene(VectorScene):
|
||||
def apply_matrix(self, matrix, **kwargs):
|
||||
self.apply_transposed_matrix(np.array(matrix).T, **kwargs)
|
||||
|
||||
def apply_inverse(self, matrix, **kwargs):
|
||||
self.apply_matrix(np.linalg.inv(matrix), **kwargs)
|
||||
|
||||
def apply_transposed_matrix(self, transposed_matrix, **kwargs):
|
||||
func = self.get_transposed_matrix_transformation(transposed_matrix)
|
||||
if "path_arc" not in kwargs:
|
||||
|
Reference in New Issue
Block a user