mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
First page of chapter 5
This commit is contained in:
355
eola/chapter5.py
Normal file
355
eola/chapter5.py
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
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.chapter3 import MatrixVectorMultiplicationAbstract
|
||||||
|
|
||||||
|
class Blob(Circle):
|
||||||
|
CONFIG = {
|
||||||
|
"stroke_color" : TEAL,
|
||||||
|
"fill_color" : BLUE_E,
|
||||||
|
"fill_opacity" : 1,
|
||||||
|
"random_seed" : 1,
|
||||||
|
"random_nudge_size" : 0.5,
|
||||||
|
"height" : 2,
|
||||||
|
}
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
Circle.__init__(self, **kwargs)
|
||||||
|
random.seed(self.random_seed)
|
||||||
|
self.apply_complex_function(
|
||||||
|
lambda z : z*(1+self.random_nudge_size*(random.random()-0.5))
|
||||||
|
)
|
||||||
|
self.scale_to_fit_height(self.height).center()
|
||||||
|
|
||||||
|
def probably_contains(self, point):
|
||||||
|
border_points = np.array(self.get_anchors_and_handles()[0])
|
||||||
|
distances = map(lambda p : np.linalg.norm(p-point), border_points)
|
||||||
|
min3 = border_points[np.argsort(distances)[:3]]
|
||||||
|
center_direction = self.get_center() - point
|
||||||
|
in_center_direction = map(
|
||||||
|
lambda p : np.dot(p-point, center_direction) > 0,
|
||||||
|
min3
|
||||||
|
)
|
||||||
|
return sum(in_center_direction) <= 2
|
||||||
|
|
||||||
|
|
||||||
|
class OpeningQuote(Scene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject([
|
||||||
|
"``The purpose of computation is \\\\",
|
||||||
|
"insight",
|
||||||
|
", not ",
|
||||||
|
"numbers.",
|
||||||
|
"''",
|
||||||
|
], separate_list_arg_with_spaces = False)
|
||||||
|
# words.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
||||||
|
words.to_edge(UP)
|
||||||
|
words.split()[1].highlight(BLUE)
|
||||||
|
words.split()[3].highlight(GREEN)
|
||||||
|
author = TextMobject("-Richard Hamming")
|
||||||
|
author.highlight(YELLOW)
|
||||||
|
author.next_to(words, DOWN, buff = 0.5)
|
||||||
|
|
||||||
|
self.play(FadeIn(words))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(Write(author, run_time = 3))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class MovingForward(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
student = self.get_students()[1]
|
||||||
|
bubble = student.get_bubble(direction = RIGHT, width = 5)
|
||||||
|
bubble.rotate(-np.pi/12)
|
||||||
|
bubble.next_to(student, UP, aligned_edge = RIGHT)
|
||||||
|
bubble.shift(0.5*LEFT)
|
||||||
|
bubble.make_green_screen()
|
||||||
|
|
||||||
|
self.teacher_says("""
|
||||||
|
Y'all know about linear
|
||||||
|
transformations, right?
|
||||||
|
""", width = 7)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(bubble),
|
||||||
|
student.change_mode, "pondering"
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class StretchingTransformation(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_title("Generally stretches space")
|
||||||
|
self.apply_transposed_matrix([[3, 1], [-1, 2]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class SquishingTransformation(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : 3*SPACE_WIDTH,
|
||||||
|
"y_radius" : 3*SPACE_WIDTH,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_title("Generally squishes space")
|
||||||
|
self.apply_transposed_matrix([[1./2, -0.5], [1, 1./3]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class AskAboutStretching(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
words = TextMobject("""
|
||||||
|
Exactly how much are
|
||||||
|
things being stretched?
|
||||||
|
""")
|
||||||
|
words.add_background_rectangle()
|
||||||
|
words.to_corner(UP+RIGHT)
|
||||||
|
words.highlight(YELLOW)
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
[[2, 1], [-1, 3]],
|
||||||
|
added_anims = [Write(words)]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class AskAboutStretchingSpecifically(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_title(["How much are", "areas", "scaled?"])
|
||||||
|
hma, areas, scaled = self.title.split()[1].split()
|
||||||
|
areas.highlight(YELLOW)
|
||||||
|
blob = Blob().shift(UP+RIGHT)
|
||||||
|
|
||||||
|
label = TextMobject("Area")
|
||||||
|
label.highlight(YELLOW)
|
||||||
|
label = VMobject(VectorizedPoint(label.get_left()), label)
|
||||||
|
label.move_to(blob)
|
||||||
|
target_label = TexMobject(["c \\cdot", "\\text{Area}"])
|
||||||
|
target_label.split()[1].highlight(YELLOW)
|
||||||
|
|
||||||
|
self.add_transformable_mobject(blob)
|
||||||
|
self.add_moving_mobject(label, target_label)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([[2, -1], [1, 1]])
|
||||||
|
arrow = Arrow(scaled, label.target.split()[0])
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class BeautyNowUsesLater(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.teacher_says("Beauty now, uses later")
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class DiagonalExample(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_square" : False,
|
||||||
|
"show_coordinates" : True,
|
||||||
|
"transposed_matrix" : [[3, 0], [0, 2]]
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
matrix = Matrix(np.array(self.transposed_matrix).transpose())
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR)
|
||||||
|
matrix.next_to(ORIGIN, LEFT).to_edge(UP)
|
||||||
|
matrix_background = BackgroundRectangle(matrix)
|
||||||
|
self.play(ShowCreation(matrix_background), Write(matrix))
|
||||||
|
if self.show_square:
|
||||||
|
self.add_unit_square(animate = True)
|
||||||
|
self.add_foreground_mobject(matrix_background, matrix)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([self.transposed_matrix[0], [0, 1]])
|
||||||
|
self.apply_transposed_matrix([[1, 0], self.transposed_matrix[1]])
|
||||||
|
self.dither()
|
||||||
|
if self.show_square:
|
||||||
|
|
||||||
|
|
||||||
|
bottom_brace = Brace(self.i_hat, DOWN)
|
||||||
|
right_brace = Brace(self.square, RIGHT)
|
||||||
|
width = TexMobject(str(self.transposed_matrix[0][0]))
|
||||||
|
height = TexMobject(str(self.transposed_matrix[1][1]))
|
||||||
|
width.next_to(bottom_brace, DOWN)
|
||||||
|
height.next_to(right_brace, RIGHT)
|
||||||
|
for mob in bottom_brace, width, right_brace, height:
|
||||||
|
mob.add_background_rectangle()
|
||||||
|
self.play(Write(mob, run_time = 0.5))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
width_target, height_target = width.copy(), height.copy()
|
||||||
|
det = np.linalg.det(self.transposed_matrix)
|
||||||
|
times, eq_det = map(TexMobject, ["\\times", "=%d"%det])
|
||||||
|
words = TextMobject("New area $=$")
|
||||||
|
equation = VMobject(
|
||||||
|
words, width_target, times, height_target, eq_det
|
||||||
|
)
|
||||||
|
equation.arrange_submobjects(RIGHT, buff = 0.2)
|
||||||
|
equation.next_to(self.square, UP, aligned_edge = LEFT)
|
||||||
|
equation.shift(0.5*RIGHT)
|
||||||
|
background_rect = BackgroundRectangle(equation)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ShowCreation(background_rect),
|
||||||
|
Transform(width.copy(), width_target),
|
||||||
|
Transform(height.copy(), height_target),
|
||||||
|
*map(Write, [words, times, eq_det])
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class DiagonalExampleWithSquare(DiagonalExample):
|
||||||
|
CONFIG = {
|
||||||
|
"show_square" : True
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShearExample(DiagonalExample):
|
||||||
|
CONFIG = {
|
||||||
|
"show_square" : False,
|
||||||
|
"show_coordinates" : True,
|
||||||
|
"transposed_matrix" : [[1, 0], [1, 1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShearExampleWithSquare(DiagonalExample):
|
||||||
|
CONFIG = {
|
||||||
|
"show_square" : True,
|
||||||
|
"show_coordinates" : True,
|
||||||
|
"show_coordinates" : False,
|
||||||
|
"transposed_matrix" : [[1, 0], [1, 1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThisSquareTellsEverything(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_unit_square()
|
||||||
|
words = TextMobject("""
|
||||||
|
This square gives you
|
||||||
|
everything you need.
|
||||||
|
""")
|
||||||
|
words.to_corner(UP+RIGHT)
|
||||||
|
words.highlight(YELLOW)
|
||||||
|
words.add_background_rectangle()
|
||||||
|
arrow = Arrow(
|
||||||
|
words.get_bottom(), self.square.get_right(),
|
||||||
|
color = WHITE
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(Write(words, run_time = 2))
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.add_foreground_mobject(words, arrow)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([[1.5, -0.5], [1, 1.5]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class WhatHappensToOneSquareHappensToAll(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_unit_square()
|
||||||
|
pairs = [
|
||||||
|
(2*RIGHT+UP, 1),
|
||||||
|
(3*LEFT, 2),
|
||||||
|
(2*LEFT+DOWN, 0.5),
|
||||||
|
(3.5*RIGHT+2.5*UP, 1.5),
|
||||||
|
(RIGHT+2*DOWN, 0.25),
|
||||||
|
(3*LEFT+3*DOWN, 1),
|
||||||
|
]
|
||||||
|
squares = VMobject()
|
||||||
|
for position, side_length in pairs:
|
||||||
|
square = self.square.copy()
|
||||||
|
square.scale(side_length)
|
||||||
|
square.shift(position)
|
||||||
|
squares.add(square)
|
||||||
|
self.play(FadeIn(
|
||||||
|
squares, submobject_mode = "lagged_start",
|
||||||
|
run_time = 3
|
||||||
|
))
|
||||||
|
self.add_transformable_mobject(squares)
|
||||||
|
self.apply_transposed_matrix([[1, -1], [0.5, 1]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class BreakBlobIntoGridSquares(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"square_size" : 0.5,
|
||||||
|
"blob_height" : 3,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
blob = Blob(
|
||||||
|
height = self.blob_height,
|
||||||
|
random_seed = 5,
|
||||||
|
random_nudge_size = 0.2,
|
||||||
|
)
|
||||||
|
blob.next_to(ORIGIN, UP+RIGHT)
|
||||||
|
self.add_transformable_mobject(blob)
|
||||||
|
arange = np.arange(
|
||||||
|
0, self.blob_height + self.square_size,
|
||||||
|
self.square_size
|
||||||
|
)
|
||||||
|
square = Square(side_length = self.square_size)
|
||||||
|
square.set_stroke(YELLOW, width = 2)
|
||||||
|
square.set_fill(YELLOW, opacity = 0.3)
|
||||||
|
squares = VMobject()
|
||||||
|
for x, y in it.product(*[arange]*2):
|
||||||
|
point = x*RIGHT + y*UP
|
||||||
|
if blob.probably_contains(point):
|
||||||
|
squares.add(square.copy().shift(point))
|
||||||
|
self.play(ShowCreation(
|
||||||
|
squares, submobject_mode = "lagged_start",
|
||||||
|
run_time = 2,
|
||||||
|
))
|
||||||
|
self.add_transformable_mobject(squares)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([[1, -1], [0.5, 1]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class BreakBlobIntoGridSquaresGranular(BreakBlobIntoGridSquares):
|
||||||
|
CONFIG = {
|
||||||
|
"square_size" : 0.25
|
||||||
|
}
|
||||||
|
|
||||||
|
class BreakBlobIntoGridSquaresVeryGranular(BreakBlobIntoGridSquares):
|
||||||
|
CONFIG = {
|
||||||
|
"square_size" : 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
class NameDeterminant(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"t_matrix" : [[1, 0], [2, 1]]
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.setup()
|
||||||
|
self.add_unit_square()
|
||||||
|
self.add_title(["The", "``determinant''", "of a transformation"])
|
||||||
|
self.title.split()[1].split()[1].highlight(YELLOW)
|
||||||
|
|
||||||
|
text = TextMobject("Area $=1$")
|
||||||
|
text.move_to(self.square)
|
||||||
|
det = np.linalg.det(self.t_matrix)
|
||||||
|
self.add_moving_mobject(text, TextMobject("Area $=%d$"%det))
|
||||||
|
self.show_frame()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,7 +9,8 @@ from animation.transform import ApplyPointwiseFunction, Transform, \
|
|||||||
ApplyMethod, FadeOut, ApplyFunction
|
ApplyMethod, FadeOut, ApplyFunction
|
||||||
from animation.simple_animations import ShowCreation, Write
|
from animation.simple_animations import ShowCreation, Write
|
||||||
from topics.number_line import NumberPlane, Axes
|
from topics.number_line import NumberPlane, Axes
|
||||||
from topics.geometry import Vector, Line, Circle, Arrow, Dot, BackgroundRectangle
|
from topics.geometry import Vector, Line, Circle, Arrow, Dot, \
|
||||||
|
BackgroundRectangle, Square
|
||||||
|
|
||||||
from helpers import *
|
from helpers import *
|
||||||
from eola.matrix import Matrix, VECTOR_LABEL_SCALE_VAL, vector_coordinate_label
|
from eola.matrix import Matrix, VECTOR_LABEL_SCALE_VAL, vector_coordinate_label
|
||||||
@ -262,6 +263,7 @@ class LinearTransformationScene(VectorScene):
|
|||||||
self.transformable_mobjects = []
|
self.transformable_mobjects = []
|
||||||
self.moving_vectors = []
|
self.moving_vectors = []
|
||||||
self.transformable_labels = []
|
self.transformable_labels = []
|
||||||
|
self.moving_mobjects = []
|
||||||
|
|
||||||
|
|
||||||
self.background_plane = NumberPlane(
|
self.background_plane = NumberPlane(
|
||||||
@ -301,6 +303,24 @@ class LinearTransformationScene(VectorScene):
|
|||||||
def add_transformable_mobject(self, *mobjects):
|
def add_transformable_mobject(self, *mobjects):
|
||||||
self.add_special_mobjects(self.transformable_mobjects, *mobjects)
|
self.add_special_mobjects(self.transformable_mobjects, *mobjects)
|
||||||
|
|
||||||
|
def add_moving_mobject(self, mobject, target_mobject = None):
|
||||||
|
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))
|
||||||
|
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.add_transformable_mobject(square)
|
||||||
|
self.bring_to_front(*self.moving_vectors)
|
||||||
|
self.square = square
|
||||||
|
return self
|
||||||
|
|
||||||
def add_vector(self, vector, color = YELLOW, **kwargs):
|
def add_vector(self, vector, color = YELLOW, **kwargs):
|
||||||
vector = VectorScene.add_vector(
|
vector = VectorScene.add_vector(
|
||||||
self, vector, color = color, **kwargs
|
self, vector, color = color, **kwargs
|
||||||
@ -334,6 +354,7 @@ class LinearTransformationScene(VectorScene):
|
|||||||
if animate:
|
if animate:
|
||||||
self.play(Write(title))
|
self.play(Write(title))
|
||||||
self.add_foreground_mobject(title)
|
self.add_foreground_mobject(title)
|
||||||
|
self.title = title
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_matrix_transformation(self, transposed_matrix):
|
def get_matrix_transformation(self, transposed_matrix):
|
||||||
@ -353,6 +374,14 @@ class LinearTransformationScene(VectorScene):
|
|||||||
self.add(start.copy().fade(0.7))
|
self.add(start.copy().fade(0.7))
|
||||||
return Transform(start, target, submobject_mode = "all_at_once")
|
return Transform(start, target, submobject_mode = "all_at_once")
|
||||||
|
|
||||||
|
def get_moving_mobject_movement(self, func):
|
||||||
|
for m in self.moving_mobjects:
|
||||||
|
if m.target is None:
|
||||||
|
m.target = m.copy()
|
||||||
|
target_point = func(m.get_center())
|
||||||
|
m.target.move_to(target_point)
|
||||||
|
return self.get_piece_movement(self.moving_mobjects)
|
||||||
|
|
||||||
def get_vector_movement(self, func):
|
def get_vector_movement(self, func):
|
||||||
for v in self.moving_vectors:
|
for v in self.moving_vectors:
|
||||||
v.target = Vector(func(v.get_end()), color = v.get_color())
|
v.target = Vector(func(v.get_end()), color = v.get_color())
|
||||||
@ -382,13 +411,18 @@ class LinearTransformationScene(VectorScene):
|
|||||||
def apply_function(self, function, added_anims = [], **kwargs):
|
def apply_function(self, function, added_anims = [], **kwargs):
|
||||||
if "run_time" not in kwargs:
|
if "run_time" not in kwargs:
|
||||||
kwargs["run_time"] = 3
|
kwargs["run_time"] = 3
|
||||||
added_anims.append(self.get_vector_movement(function))
|
anims = [
|
||||||
added_anims.append(self.get_transformable_label_movement())
|
ApplyPointwiseFunction(function, t_mob)
|
||||||
added_anims += map(Animation, self.foreground_mobjects)
|
for t_mob in self.transformable_mobjects
|
||||||
function_application = ApplyPointwiseFunction(
|
] + [
|
||||||
function, VMobject(*self.transformable_mobjects)
|
self.get_vector_movement(function),
|
||||||
)
|
self.get_transformable_label_movement(),
|
||||||
self.play(function_application, *added_anims, **kwargs)
|
self.get_moving_mobject_movement(function),
|
||||||
|
] + [
|
||||||
|
Animation(f_mob)
|
||||||
|
for f_mob in self.foreground_mobjects
|
||||||
|
] + added_anims
|
||||||
|
self.play(*anims, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +122,8 @@ def is_scene(obj):
|
|||||||
|
|
||||||
def prompt_user_for_choice(name_to_obj):
|
def prompt_user_for_choice(name_to_obj):
|
||||||
num_to_name = {}
|
num_to_name = {}
|
||||||
for count, name in zip(it.count(1), name_to_obj):
|
names = sorted(name_to_obj.keys())
|
||||||
|
for count, name in zip(it.count(1), names):
|
||||||
print "%d: %s"%(count, name)
|
print "%d: %s"%(count, name)
|
||||||
num_to_name[count] = name
|
num_to_name[count] = name
|
||||||
try:
|
try:
|
||||||
|
@ -224,12 +224,12 @@ class Mobject(object):
|
|||||||
self.shift(target_point - point_to_align + buff*direction)
|
self.shift(target_point - point_to_align + buff*direction)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def shift_onto_screen(self):
|
def shift_onto_screen(self, **kwargs):
|
||||||
space_lengths = [SPACE_WIDTH, SPACE_HEIGHT]
|
space_lengths = [SPACE_WIDTH, SPACE_HEIGHT]
|
||||||
for vect in UP, DOWN, LEFT, RIGHT:
|
for vect in UP, DOWN, LEFT, RIGHT:
|
||||||
dim = np.argmax(np.abs(vect))
|
dim = np.argmax(np.abs(vect))
|
||||||
if abs(self.get_edge_center(vect)[dim]) > space_lengths[dim]:
|
if abs(self.get_edge_center(vect)[dim]) > space_lengths[dim]:
|
||||||
self.to_edge(vect)
|
self.to_edge(vect, **kwargs)
|
||||||
|
|
||||||
def stretch_to_fit(self, length, dim, stretch = True):
|
def stretch_to_fit(self, length, dim, stretch = True):
|
||||||
old_length = self.length_over_dim(dim)
|
old_length = self.length_over_dim(dim)
|
||||||
|
@ -14,6 +14,7 @@ class VMobject(Mobject):
|
|||||||
"is_subpath" : False,
|
"is_subpath" : False,
|
||||||
"close_new_points" : False,
|
"close_new_points" : False,
|
||||||
"mark_paths_closed" : False,
|
"mark_paths_closed" : False,
|
||||||
|
"considered_smooth" : True,
|
||||||
"propogate_style_to_family" : False,
|
"propogate_style_to_family" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -181,6 +182,7 @@ class VMobject(Mobject):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def make_smooth(self):
|
def make_smooth(self):
|
||||||
|
self.considered_smooth = True
|
||||||
return self.change_anchor_mode("smooth")
|
return self.change_anchor_mode("smooth")
|
||||||
|
|
||||||
def make_jagged(self):
|
def make_jagged(self):
|
||||||
@ -211,7 +213,7 @@ class VMobject(Mobject):
|
|||||||
|
|
||||||
def apply_function(self, function, maintain_smoothness = True):
|
def apply_function(self, function, maintain_smoothness = True):
|
||||||
Mobject.apply_function(self, function)
|
Mobject.apply_function(self, function)
|
||||||
if maintain_smoothness:
|
if maintain_smoothness and self.considered_smooth:
|
||||||
self.make_smooth()
|
self.make_smooth()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -114,13 +114,13 @@ class Scene(object):
|
|||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def bring_to_front(self, mobject):
|
def bring_to_front(self, *mobjects):
|
||||||
self.add(mobject)
|
self.add(*mobjects)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def bring_to_back(self, mobject):
|
def bring_to_back(self, *mobjects):
|
||||||
self.remove(mobject)
|
self.remove(*mobjects)
|
||||||
self.mobjects = [mobject] + self.mobjects
|
self.mobjects = mobjects + self.mobjects
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
@ -189,6 +189,7 @@ class Bubble(SVGMobject):
|
|||||||
self.stretch_to_fit_width(self.width)
|
self.stretch_to_fit_width(self.width)
|
||||||
if self.direction[0] > 0:
|
if self.direction[0] > 0:
|
||||||
Mobject.flip(self)
|
Mobject.flip(self)
|
||||||
|
self.direction_was_specified = ("direction" in kwargs)
|
||||||
self.content = Mobject()
|
self.content = Mobject()
|
||||||
|
|
||||||
def get_tip(self):
|
def get_tip(self):
|
||||||
@ -207,9 +208,11 @@ class Bubble(SVGMobject):
|
|||||||
self.direction = -np.array(self.direction)
|
self.direction = -np.array(self.direction)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def pin_to(self, mobject, allow_flipping = True):
|
def pin_to(self, mobject):
|
||||||
mob_center = mobject.get_center()
|
mob_center = mobject.get_center()
|
||||||
if np.sign(mob_center[0]) != np.sign(self.direction[0]) and allow_flipping:
|
want_to_filp = np.sign(mob_center[0]) != np.sign(self.direction[0])
|
||||||
|
can_flip = not self.direction_was_specified
|
||||||
|
if want_to_filp and can_flip:
|
||||||
self.flip()
|
self.flip()
|
||||||
boundary_point = mobject.get_critical_point(UP-self.direction)
|
boundary_point = mobject.get_critical_point(UP-self.direction)
|
||||||
vector_from_center = 1.0*(boundary_point-mob_center)
|
vector_from_center = 1.0*(boundary_point-mob_center)
|
||||||
|
@ -56,6 +56,7 @@ class Dot(Circle): #Use 1D density, even though 2D
|
|||||||
class Line(VMobject):
|
class Line(VMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"buff" : 0,
|
"buff" : 0,
|
||||||
|
"considered_smooth" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, start, end, **kwargs):
|
def __init__(self, start, end, **kwargs):
|
||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
@ -214,6 +215,7 @@ class Polygon(VMobject):
|
|||||||
"color" : GREEN_D,
|
"color" : GREEN_D,
|
||||||
"mark_paths_closed" : True,
|
"mark_paths_closed" : True,
|
||||||
"close_new_points" : True,
|
"close_new_points" : True,
|
||||||
|
"considered_smooth" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, *vertices, **kwargs):
|
def __init__(self, *vertices, **kwargs):
|
||||||
assert len(vertices) > 1
|
assert len(vertices) > 1
|
||||||
@ -244,6 +246,7 @@ class Rectangle(VMobject):
|
|||||||
"width" : 4.0,
|
"width" : 4.0,
|
||||||
"mark_paths_closed" : True,
|
"mark_paths_closed" : True,
|
||||||
"close_new_points" : True,
|
"close_new_points" : True,
|
||||||
|
"considered_smooth" : False,
|
||||||
}
|
}
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
y, x = self.height/2., self.width/2.
|
y, x = self.height/2., self.width/2.
|
||||||
@ -302,6 +305,7 @@ class Grid(VMobject):
|
|||||||
CONFIG = {
|
CONFIG = {
|
||||||
"height" : 6.0,
|
"height" : 6.0,
|
||||||
"width" : 6.0,
|
"width" : 6.0,
|
||||||
|
"considered_smooth" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, rows, columns, **kwargs):
|
def __init__(self, rows, columns, **kwargs):
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
|
Reference in New Issue
Block a user