mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
Up to physics example in eola chapter 0
This commit is contained in:
parent
c910b00a32
commit
d35a8f76ac
9 changed files with 425 additions and 64 deletions
|
@ -114,6 +114,17 @@ class Flash(Animation):
|
|||
alpha
|
||||
)
|
||||
|
||||
class MoveAlongPath(Animation):
|
||||
def __init__(self, mobject, vmobject, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
Animation.__init__(self, mobject, **kwargs)
|
||||
|
||||
def update_mobject(self, alpha):
|
||||
self.mobject.shift(
|
||||
self.vmobject.point_from_proportion(alpha) - \
|
||||
self.mobject.get_center()
|
||||
)
|
||||
|
||||
class Homotopy(Animation):
|
||||
def __init__(self, homotopy, mobject, **kwargs):
|
||||
"""
|
||||
|
|
|
@ -22,7 +22,7 @@ LOW_QUALITY_CAMERA_CONFIG = {
|
|||
DEFAULT_POINT_DENSITY_2D = 25
|
||||
DEFAULT_POINT_DENSITY_1D = 250
|
||||
|
||||
DEFAULT_POINT_THICKNESS = 3
|
||||
DEFAULT_POINT_THICKNESS = 4
|
||||
|
||||
#TODO, Make sure these are not needed
|
||||
SPACE_HEIGHT = 4.0
|
||||
|
|
383
eola/chapter0.py
383
eola/chapter0.py
|
@ -16,6 +16,7 @@ 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.utils import *
|
||||
|
||||
|
@ -37,22 +38,20 @@ class OpeningQuote(Scene):
|
|||
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.play(FadeIn(words))
|
||||
self.dither(3)
|
||||
self.play(Write(author))
|
||||
self.dither()
|
||||
|
||||
|
||||
class AboutLinearAlgebra(Scene):
|
||||
def construct(self):
|
||||
self.show_dependencies()
|
||||
self.linalg_is_confusing()
|
||||
self.ask_questions()
|
||||
self.to_thought_bubble()
|
||||
|
||||
def show_dependencies(self):
|
||||
linalg = TextMobject("Linear Algebra")
|
||||
|
@ -86,7 +85,7 @@ class AboutLinearAlgebra(Scene):
|
|||
self.dither()
|
||||
self.linalg = linalg
|
||||
|
||||
def linalg_is_confusing(self):
|
||||
def to_thought_bubble(self):
|
||||
linalg = self.linalg
|
||||
all_else = list(self.mobjects)
|
||||
all_else.remove(linalg)
|
||||
|
@ -94,6 +93,7 @@ class AboutLinearAlgebra(Scene):
|
|||
randy.to_corner()
|
||||
bubble = randy.get_bubble(width = 10)
|
||||
new_linalg = bubble.position_mobject_inside(linalg.copy())
|
||||
q_marks = TextMobject("???").next_to(randy, UP)
|
||||
|
||||
self.play(*map(FadeOut, all_else))
|
||||
self.remove(*all_else)
|
||||
|
@ -102,17 +102,44 @@ class AboutLinearAlgebra(Scene):
|
|||
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
|
||||
topics = [
|
||||
self.get_matrix_multiplication(),
|
||||
self.get_determinant(),
|
||||
self.get_cross_product(),
|
||||
self.get_eigenvalue(),
|
||||
]
|
||||
questions = [
|
||||
self.get_matrix_multiplication_question(),
|
||||
self.get_cross_product_question(),
|
||||
self.get_eigen_question(),
|
||||
]
|
||||
for count, topic in enumerate(topics + questions):
|
||||
bubble.position_mobject_inside(topic)
|
||||
if count == len(topics):
|
||||
self.play(FadeOut(linalg))
|
||||
self.play(
|
||||
ApplyMethod(randy.change_mode, "confused"),
|
||||
Write(q_marks, run_time = 1)
|
||||
)
|
||||
linalg = VectorizedPoint(linalg.get_center())
|
||||
if count > len(topics):
|
||||
self.remove(linalg)
|
||||
self.play(FadeIn(topic))
|
||||
linalg = topic
|
||||
else:
|
||||
self.play(Transform(linalg, topic))
|
||||
|
||||
def ask_questions(self):
|
||||
randy, bubble = self.randy, self.bubble
|
||||
matrix_multiplication = TexMobject("""
|
||||
if count %3 == 0:
|
||||
self.play(Blink(randy))
|
||||
self.dither()
|
||||
else:
|
||||
self.dither(2)
|
||||
|
||||
|
||||
def get_matrix_multiplication(self):
|
||||
return TexMobject("""
|
||||
\\left[
|
||||
\\begin{array}{cc}
|
||||
a & b \\\\
|
||||
|
@ -134,6 +161,44 @@ class AboutLinearAlgebra(Scene):
|
|||
\\right]
|
||||
""")
|
||||
|
||||
def get_determinant(self):
|
||||
return TexMobject("""
|
||||
\\text{Det}\\left(
|
||||
\\begin{array}{cc}
|
||||
a & b \\\\
|
||||
c & d
|
||||
\\end{array}
|
||||
\\right)
|
||||
=
|
||||
ac - bc
|
||||
""")
|
||||
|
||||
def get_cross_product(self):
|
||||
return TexMobject("""
|
||||
\\vec\\textbf{v} \\times \\textbf{w} =
|
||||
\\text{Det}\\left(
|
||||
\\begin{array}{ccc}
|
||||
\\hat{\imath} & \\hat{\jmath} & \\hat{k} \\\\
|
||||
v_1 & v_2 & v_3 \\\\
|
||||
w_1 & w_2 & w_3 \\\\
|
||||
\\end{array}
|
||||
\\right)
|
||||
""")
|
||||
|
||||
def get_eigenvalue(self):
|
||||
result = TextMobject("\\Text{Det}\\left(A - \\lambda I \\right) = 0")
|
||||
result.submobjects[-5].highlight(YELLOW)
|
||||
return result
|
||||
|
||||
def get_matrix_multiplication_question(self):
|
||||
why = TextMobject("Why?").highlight(BLUE)
|
||||
mult = self.get_matrix_multiplication()
|
||||
why.next_to(mult, UP)
|
||||
result = VMobject(why, mult)
|
||||
result.get_center = lambda : mult.get_center()
|
||||
return result
|
||||
|
||||
def get_cross_product_question(self):
|
||||
cross = TexMobject("\\vec{v} \\times \\vec{w}")
|
||||
left_right_arrow = DoubleArrow(Point(LEFT), Point(RIGHT))
|
||||
det = TextMobject("Det")
|
||||
|
@ -143,19 +208,16 @@ class AboutLinearAlgebra(Scene):
|
|||
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()
|
||||
return cross_question
|
||||
|
||||
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)
|
||||
def get_eigen_question(self):
|
||||
result = TextMobject(
|
||||
"What the heck \\\\ does ``eigen'' mean?",
|
||||
|
||||
)
|
||||
for mob in result.submobjects[-11:-6]:
|
||||
mob.highlight(YELLOW)
|
||||
return result
|
||||
|
||||
|
||||
class NumericVsGeometric(Scene):
|
||||
|
@ -265,11 +327,11 @@ class NumericVsGeometric(Scene):
|
|||
class ExampleTransformation(LinearTransformationScene):
|
||||
def construct(self):
|
||||
self.setup()
|
||||
self.add_vector(np.array(TRANFORMED_VECTOR).flatten())
|
||||
self.apply_matrix(EXAMPLE_TRANFORM)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class NumericToComputations(Scene):
|
||||
def construct(self):
|
||||
top = TextMobject("Numeric understanding")
|
||||
|
@ -285,6 +347,273 @@ class NumericToComputations(Scene):
|
|||
|
||||
|
||||
|
||||
class LinAlgPyramid(Scene):
|
||||
def construct(self):
|
||||
rects = self.get_rects()
|
||||
words = self.place_words_in_rects([
|
||||
"Geometric understanding",
|
||||
"Computations",
|
||||
"Uses"
|
||||
], rects)
|
||||
for word, rect in zip(words, rects):
|
||||
self.play(
|
||||
Write(word),
|
||||
ShowCreation(rect),
|
||||
run_time = 1
|
||||
)
|
||||
self.dither()
|
||||
self.play(*[
|
||||
ApplyMethod(m.highlight, DARK_GREY)
|
||||
for m in words[0], rects[0]
|
||||
])
|
||||
self.dither()
|
||||
self.list_applications(rects[-1])
|
||||
|
||||
def get_rects(self):
|
||||
height = 1
|
||||
rects = [
|
||||
Rectangle(height = height, width = width)
|
||||
for width in 8, 5, 2
|
||||
]
|
||||
rects[0].shift(2*DOWN)
|
||||
for i in 1, 2:
|
||||
rects[i].next_to(rects[i-1], UP, buff = 0)
|
||||
return rects
|
||||
|
||||
def place_words_in_rects(self, words, rects):
|
||||
result = []
|
||||
for word, rect in zip(words, rects):
|
||||
tex_mob = TextMobject(word)
|
||||
tex_mob.shift(rect.get_center())
|
||||
result.append(tex_mob)
|
||||
return result
|
||||
|
||||
def list_applications(self, top_mob):
|
||||
subjects = [
|
||||
TextMobject(word).to_corner(UP+RIGHT)
|
||||
for word in [
|
||||
"computer science",
|
||||
"engineering",
|
||||
"statistics",
|
||||
"economics",
|
||||
"pure math",
|
||||
]
|
||||
]
|
||||
arrow = Arrow(top_mob, subjects[0].get_bottom(), color = RED)
|
||||
|
||||
self.play(ShowCreation(arrow))
|
||||
curr_subject = None
|
||||
for subject in subjects:
|
||||
if curr_subject:
|
||||
subject.shift(curr_subject.get_center()-subject.get_center())
|
||||
self.play(Transform(curr_subject, subject, run_time = 0.5))
|
||||
else:
|
||||
curr_subject = subject
|
||||
self.play(FadeIn(curr_subject, run_time = 0.5))
|
||||
self.dither()
|
||||
|
||||
|
||||
class IndimidatingProf(Scene):
|
||||
def construct(self):
|
||||
randy = Randolph().to_corner()
|
||||
morty = Mortimer().to_corner(DOWN+RIGHT)
|
||||
morty.shift(3*LEFT)
|
||||
speech_bubble = SpeechBubble(height = 3).flip()
|
||||
speech_bubble.pin_to(morty)
|
||||
speech_bubble.shift(RIGHT)
|
||||
speech_bubble.write("And of course $B^{-1}AB$ will \\\\ also have positive eigenvalues...")
|
||||
thought_bubble = ThoughtBubble(width = 4, height = 4)
|
||||
thought_bubble.next_to(morty, UP)
|
||||
thought_bubble.to_edge(RIGHT)
|
||||
q_marks = TextMobject("???")
|
||||
q_marks.next_to(randy, UP)
|
||||
|
||||
self.add(randy, morty)
|
||||
self.play(
|
||||
FadeIn(speech_bubble),
|
||||
ApplyMethod(morty.change_mode, "speaking")
|
||||
)
|
||||
self.play(FadeIn(thought_bubble))
|
||||
self.dither()
|
||||
self.play(
|
||||
ApplyMethod(randy.change_mode, "confused"),
|
||||
Write(q_marks, run_time = 1)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class ThoughtBubbleTransformation(LinearTransformationScene):
|
||||
def construct(self):
|
||||
self.setup()
|
||||
rotation = rotation_about_z(np.pi/3)
|
||||
self.apply_matrix(
|
||||
np.linalg.inv(rotation),
|
||||
path_arc = -np.pi/3,
|
||||
)
|
||||
self.apply_matrix(EXAMPLE_TRANFORM)
|
||||
self.apply_matrix(
|
||||
rotation,
|
||||
path_arc = np.pi/3,
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class SineApproximations(Scene):
|
||||
def construct(self):
|
||||
series = self.get_series()
|
||||
one_approx = self.get_approx_series("1", 1)
|
||||
one_approx.highlight(YELLOW)
|
||||
pi_sixts_approx = self.get_approx_series("\\pi/6", np.pi/6)
|
||||
pi_sixts_approx.highlight(RED)
|
||||
words = TextMobject("(How calculators compute sine)")
|
||||
words.highlight(GREEN)
|
||||
|
||||
series.to_edge(UP)
|
||||
one_approx.next_to(series, DOWN, buff = 1.5)
|
||||
pi_sixts_approx.next_to(one_approx, DOWN, buff = 1.5)
|
||||
|
||||
self.play(Write(series))
|
||||
self.dither()
|
||||
self.play(FadeIn(words))
|
||||
self.dither(2)
|
||||
self.play(FadeOut(words))
|
||||
self.remove(words)
|
||||
self.dither()
|
||||
self.play(Write(one_approx))
|
||||
self.play(Write(pi_sixts_approx))
|
||||
self.dither()
|
||||
|
||||
def get_series(self):
|
||||
return TexMobject("""
|
||||
\\sin(x) = x - \\dfrac{x^3}{3!} + \\dfrac{x^5}{5!}
|
||||
+ \\cdots + (-1)^n \\dfrac{x^{2n+1}}{(2n+1)!} + \\cdots
|
||||
""")
|
||||
|
||||
def get_approx_series(self, val_str, val):
|
||||
#Default to 3 terms
|
||||
approximation = val - (val**3)/6. + (val**5)/120.
|
||||
return TexMobject("""
|
||||
\\sin(%s) \\approx
|
||||
%s - \\dfrac{(%s)^3}{3!} + \\dfrac{(%s)^5}{5!} \\approx
|
||||
%.04f
|
||||
"""%(val_str, val_str, val_str, val_str, approximation))
|
||||
|
||||
|
||||
class LooseConnectionToTriangles(Scene):
|
||||
def construct(self):
|
||||
sine = TexMobject("\\sin(x)")
|
||||
triangle = Polygon(ORIGIN, 2*RIGHT, 2*RIGHT+UP)
|
||||
arrow = DoubleArrow(LEFT, RIGHT)
|
||||
sine.next_to(arrow, LEFT)
|
||||
triangle.next_to(arrow, RIGHT)
|
||||
|
||||
q_mark = TextMobject("?").scale(1.5)
|
||||
q_mark.next_to(arrow, UP)
|
||||
|
||||
self.add(sine)
|
||||
self.play(ShowCreation(arrow))
|
||||
self.play(ShowCreation(triangle))
|
||||
self.play(Write(q_mark))
|
||||
self.dither()
|
||||
|
||||
|
||||
class PhysicsExample(Scene):
|
||||
def construct(self):
|
||||
title = TextMobject("Physics")
|
||||
title.to_corner(UP+LEFT)
|
||||
parabola = FunctionGraph(
|
||||
lambda x : (3-x)*(3+x)/4,
|
||||
x_min = -4,
|
||||
x_max = 4
|
||||
)
|
||||
|
||||
self.play(Write(title))
|
||||
self.projectile(parabola)
|
||||
self.velocity_vector(parabola)
|
||||
self.approximate_sine()
|
||||
|
||||
def projectile(self, parabola):
|
||||
dot = Dot(radius = 0.15)
|
||||
kwargs = {
|
||||
"run_time" : 3,
|
||||
"rate_func" : None
|
||||
}
|
||||
self.play(
|
||||
MoveAlongPath(dot, parabola.copy(), **kwargs),
|
||||
ShowCreation(parabola, **kwargs)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
def velocity_vector(self, parabola):
|
||||
alpha = 0.7
|
||||
d_alpha = 0.01
|
||||
vector_length = 3
|
||||
|
||||
p1 = parabola.point_from_proportion(alpha)
|
||||
p2 = parabola.point_from_proportion(alpha + d_alpha)
|
||||
vector = vector_length*(p2-p1)/np.linalg.norm(p2-p1)
|
||||
v_mob = Vector(vector, color = YELLOW)
|
||||
vx = Vector(vector[0]*RIGHT, color = GREEN_B)
|
||||
vy = Vector(vector[1]*UP, color = RED)
|
||||
v_mob.shift(p1)
|
||||
vx.shift(p1)
|
||||
vy.shift(vx.get_end())
|
||||
|
||||
arc = Arc(
|
||||
angle_of_vector(vector),
|
||||
radius = vector_length / 4.
|
||||
)
|
||||
arc.shift(p1)
|
||||
theta = TexMobject("\\theta").scale(0.75)
|
||||
theta.next_to(arc, RIGHT, buff = 0.1)
|
||||
|
||||
v_label = TexMobject("\\vec{v}")
|
||||
v_label.shift(p1 + RIGHT*vector[0]/4 + UP*vector[1]/2)
|
||||
v_label.highlight(v_mob.get_color())
|
||||
vx_label = TexMobject("\\vec{v} \\cos(\\theta)")
|
||||
vx_label.next_to(vx, UP)
|
||||
vx_label.highlight(vx.get_color())
|
||||
vy_label = TexMobject("\\vec{v} \\sin(\\theta)")
|
||||
vy_label.next_to(vy, RIGHT)
|
||||
vy_label.highlight(vy.get_color())
|
||||
|
||||
kwargs = {"submobject_mode" : "one_at_a_time"}
|
||||
for v in v_mob, vx, vy:
|
||||
self.play(
|
||||
ShowCreation(v, submobject_mode = "one_at_a_time")
|
||||
)
|
||||
self.play(
|
||||
ShowCreation(arc),
|
||||
Write(theta, run_time = 1)
|
||||
)
|
||||
for label in v_label, vx_label, vy_label:
|
||||
self.play(Write(label, run_time = 1))
|
||||
self.dither()
|
||||
|
||||
def approximate_sine(self):
|
||||
approx = TexMobject("\\sin(\\theta) \\approx 0.7\\text{-ish}")
|
||||
morty = Mortimer(mode = "speaking")
|
||||
morty.flip()
|
||||
morty.to_corner()
|
||||
bubble = SpeechBubble(width = 4, height = 3)
|
||||
bubble.set_fill(BLACK, opacity = 1)
|
||||
bubble.pin_to(morty)
|
||||
bubble.position_mobject_inside(approx)
|
||||
|
||||
self.play(
|
||||
FadeIn(morty),
|
||||
ShowCreation(bubble),
|
||||
Write(approx),
|
||||
run_time = 2
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class LinearAlgebraIntuitions(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import numpy as np
|
|||
from scene import Scene
|
||||
from mobject.vectorized_mobject import VMobject
|
||||
from mobject.tex_mobject import TexMobject, TextMobject
|
||||
from animation.transform import ApplyMatrix, ApplyMethod
|
||||
from animation.transform import ApplyPointwiseFunction, Transform
|
||||
from topics.number_line import NumberPlane
|
||||
from topics.geometry import Vector
|
||||
|
||||
|
@ -41,7 +41,9 @@ class LinearTransformationScene(Scene):
|
|||
}
|
||||
def setup(self):
|
||||
self.background_mobjects = []
|
||||
self.foreground_mobjects = []
|
||||
self.transformable_mobject = []
|
||||
self.moving_vectors = []
|
||||
|
||||
self.background_plane = NumberPlane(
|
||||
color = GREY,
|
||||
secondary_color = DARK_GREY,
|
||||
|
@ -54,13 +56,10 @@ class LinearTransformationScene(Scene):
|
|||
self.add_to_background(self.background_plane)
|
||||
if self.include_foreground_plane:
|
||||
self.plane = NumberPlane(**self.foreground_plane_kwargs)
|
||||
self.add_to_foreground(self.plane)
|
||||
self.add_to_transformable(self.plane)
|
||||
if self.show_basis_vectors:
|
||||
i_hat = Vector(self.background_plane.num_pair_to_point((1, 0)))
|
||||
j_hat = Vector(self.background_plane.num_pair_to_point((0, 1)))
|
||||
i_hat.highlight(self.i_hat_color)
|
||||
j_hat.highlight(self.j_hat_color)
|
||||
self.add_to_foreground(i_hat, j_hat)
|
||||
self.add_vector((1, 0), self.i_hat_color)
|
||||
self.add_vector((0, 1), self.j_hat_color)
|
||||
|
||||
def add_to_background(self, *mobjects):
|
||||
for mobject in mobjects:
|
||||
|
@ -68,18 +67,47 @@ class LinearTransformationScene(Scene):
|
|||
self.background_mobjects.append(mobject)
|
||||
self.add(mobject)
|
||||
|
||||
def add_to_foreground(self, *mobjects):
|
||||
def add_to_transformable(self, *mobjects):
|
||||
for mobject in mobjects:
|
||||
if mobject not in self.foreground_mobjects:
|
||||
self.foreground_mobjects.append(mobject)
|
||||
if mobject not in self.transformable_mobject:
|
||||
self.transformable_mobject.append(mobject)
|
||||
self.add(mobject)
|
||||
|
||||
def add_vector(self, coords, color = YELLOW):
|
||||
vector = Vector(self.background_plane.num_pair_to_point(coords))
|
||||
vector.highlight(color)
|
||||
self.moving_vectors.append(vector)
|
||||
return vector
|
||||
|
||||
def apply_matrix(self, matrix, **kwargs):
|
||||
self.play(ApplyMatrix(
|
||||
matrix,
|
||||
VMobject(*self.foreground_mobjects),
|
||||
**kwargs
|
||||
))
|
||||
matrix = np.array(matrix)
|
||||
if matrix.shape == (2, 2):
|
||||
new_matrix = np.identity(3)
|
||||
new_matrix[:2, :2] = matrix
|
||||
matrix = new_matrix
|
||||
elif matrix.shape != (3, 3):
|
||||
raise "Matrix has bad dimensions"
|
||||
transpose = np.transpose(matrix)
|
||||
|
||||
def func(point):
|
||||
return np.dot(point, transpose)
|
||||
|
||||
new_vectors = [
|
||||
Vector(func(v.get_end()), color = v.get_stroke_color())
|
||||
for v in self.moving_vectors
|
||||
]
|
||||
self.play(
|
||||
ApplyPointwiseFunction(
|
||||
func,
|
||||
VMobject(*self.transformable_mobject),
|
||||
**kwargs
|
||||
),
|
||||
Transform(
|
||||
VMobject(*self.moving_vectors),
|
||||
VMobject(*new_vectors),
|
||||
**kwargs
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class TexMobject(SVGMobject):
|
|||
"next_to_direction" : RIGHT,
|
||||
"next_to_buff" : 0.25,
|
||||
"initial_scale_val" : TEX_MOB_SCALE_VAL,
|
||||
"organize_left_to_right" : True,
|
||||
"organize_left_to_right" : False,
|
||||
"propogate_style_to_family" : True,
|
||||
}
|
||||
def __init__(self, expression, **kwargs):
|
||||
|
|
|
@ -237,13 +237,10 @@ class Scene(object):
|
|||
|
||||
def write_to_movie(self, name = None):
|
||||
if len(self.frames) == 0:
|
||||
print "No frames, I'll just save an image instead"
|
||||
self.show_frame()
|
||||
self.save_image(name = name)
|
||||
print "No frames, so I'm not writing anything"
|
||||
return
|
||||
if name is None:
|
||||
name = str(self)
|
||||
|
||||
file_path = self.get_movie_file_path(name, ".mp4")
|
||||
print "Writing to %s"%file_path
|
||||
|
||||
|
|
|
@ -74,11 +74,11 @@ class PiCreature(SVGMobject):
|
|||
def change_mode(self, mode):
|
||||
curr_center = self.get_center()
|
||||
curr_height = self.get_height()
|
||||
flip = self.is_flipped()
|
||||
self.__class__.__init__(self, mode)
|
||||
should_be_flipped = self.is_flipped()
|
||||
self.__init__(mode)
|
||||
self.scale_to_fit_height(curr_height)
|
||||
self.shift(curr_center)
|
||||
if flip:
|
||||
if should_be_flipped^self.is_flipped():
|
||||
self.flip()
|
||||
return self
|
||||
|
||||
|
@ -129,7 +129,7 @@ class Mortimer(PiCreature):
|
|||
PiCreature.__init__(self, *args, **kwargs)
|
||||
self.flip()
|
||||
|
||||
|
||||
|
||||
class Mathematician(PiCreature):
|
||||
CONFIG = {
|
||||
"color" : GREY,
|
||||
|
|
|
@ -9,8 +9,7 @@ class FunctionGraph(VMobject):
|
|||
"color" : BLUE_D,
|
||||
"x_min" : -SPACE_WIDTH,
|
||||
"x_max" : SPACE_WIDTH,
|
||||
"space_unit_to_num" : 1,
|
||||
"epsilon" : 0.5,
|
||||
"num_steps" : 20,
|
||||
}
|
||||
def __init__(self, function, **kwargs):
|
||||
self.function = function
|
||||
|
@ -19,8 +18,7 @@ class FunctionGraph(VMobject):
|
|||
def generate_points(self):
|
||||
self.set_anchor_points([
|
||||
x*RIGHT + self.function(x)*UP
|
||||
for pre_x in np.arange(self.x_min, self.x_max, self.epsilon)
|
||||
for x in [self.space_unit_to_num*pre_x]
|
||||
for x in np.linspace(self.x_min, self.x_max, self.num_steps)
|
||||
], mode = "smooth")
|
||||
|
||||
|
||||
|
|
|
@ -22,14 +22,12 @@ class Arc(VMobject):
|
|||
self.scale(self.radius)
|
||||
|
||||
def get_unscaled_anchor_points(self):
|
||||
step = self.angle/self.num_anchors
|
||||
end_angle = self.start_angle + self.angle
|
||||
if self.anchors_span_full_range:
|
||||
end_angle += step
|
||||
return [
|
||||
np.cos(a)*RIGHT+np.sin(a)*UP
|
||||
for a in np.arange(
|
||||
self.start_angle, end_angle, step
|
||||
for a in np.linspace(
|
||||
self.start_angle,
|
||||
self.start_angle + self.angle,
|
||||
self.num_anchors
|
||||
)
|
||||
]
|
||||
|
||||
|
@ -238,7 +236,7 @@ class Rectangle(VMobject):
|
|||
"close_new_points" : True,
|
||||
}
|
||||
def generate_points(self):
|
||||
y, x = self.height/2, self.width/2
|
||||
y, x = self.height/2., self.width/2.
|
||||
self.set_anchor_points([
|
||||
x*LEFT+y*UP,
|
||||
x*RIGHT+y*UP,
|
||||
|
|
Loading…
Add table
Reference in a new issue