mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
Through coordinates section in chapter 1
This commit is contained in:
@ -117,7 +117,7 @@ class Rotate(ApplyMethod):
|
|||||||
"in_place" : False,
|
"in_place" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, mobject, angle = np.pi, axis = OUT, **kwargs):
|
def __init__(self, mobject, angle = np.pi, axis = OUT, **kwargs):
|
||||||
kwargs["path_func"] = path_along_arc(angle)
|
kwargs["path_arc"] = angle
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
if self.in_place:
|
if self.in_place:
|
||||||
method = mobject.rotate_in_place
|
method = mobject.rotate_in_place
|
||||||
|
613
eola/chapter1.py
613
eola/chapter1.py
@ -51,12 +51,42 @@ class OpeningQuote(Scene):
|
|||||||
self.play(Write(author, run_time = 4))
|
self.play(Write(author, run_time = 4))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
class IntroVector(Scene):
|
|
||||||
|
class DifferentConceptions(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
physy = Physicist()
|
||||||
|
mathy = Mathematician(mode = "pondering")
|
||||||
|
compy = ComputerScientist()
|
||||||
|
creatures = [physy, compy, mathy]
|
||||||
|
physy.title = TextMobject("Physics student").to_corner(DOWN+LEFT)
|
||||||
|
compy.title = TextMobject("CS student").to_corner(DOWN+RIGHT)
|
||||||
|
mathy.title = TextMobject("Mathematician").to_edge(DOWN)
|
||||||
|
names = VMobject(physy.title, mathy.title, compy.title)
|
||||||
|
names.arrange_submobjects(RIGHT, buff = 1)
|
||||||
|
names.to_corner(DOWN+LEFT)
|
||||||
|
for pi in creatures:
|
||||||
|
pi.next_to(pi.title, UP)
|
||||||
|
|
||||||
|
vector, symbol, coordinates = self.intro_vector()
|
||||||
|
for pi in creatures:
|
||||||
|
self.play(
|
||||||
|
Write(pi.title),
|
||||||
|
FadeIn(pi),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.remove(symbol, coordinates)
|
||||||
|
self.physics_conception(creatures, vector)
|
||||||
|
self.cs_conception(creatures)
|
||||||
|
self.handle_mathy(creatures)
|
||||||
|
|
||||||
|
def intro_vector(self):
|
||||||
plane = NumberPlane()
|
plane = NumberPlane()
|
||||||
labels = plane.get_coordinate_labels()
|
labels = VMobject(*plane.get_coordinate_labels())
|
||||||
vector = Vector(RIGHT+2*UP, color = YELLOW)
|
vector = Vector(RIGHT+2*UP, color = YELLOW)
|
||||||
coordinates = vector_coordinate_label(vector)
|
coordinates = vector_coordinate_label(vector)
|
||||||
|
symbol = TexMobject("\\vec{\\textbf{v}}")
|
||||||
|
symbol.shift(0.5*(RIGHT+UP))
|
||||||
|
|
||||||
self.play(ShowCreation(
|
self.play(ShowCreation(
|
||||||
plane,
|
plane,
|
||||||
@ -67,71 +97,542 @@ class IntroVector(Scene):
|
|||||||
vector,
|
vector,
|
||||||
submobject_mode = "one_at_a_time"
|
submobject_mode = "one_at_a_time"
|
||||||
))
|
))
|
||||||
self.play(Write(VMobject(*labels)), Write(coordinates))
|
self.play(
|
||||||
|
Write(labels),
|
||||||
|
Write(coordinates),
|
||||||
|
Write(symbol)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
FadeOut(plane),
|
||||||
|
FadeOut(labels),
|
||||||
|
ApplyMethod(vector.shift, 4*LEFT+UP),
|
||||||
|
ApplyMethod(coordinates.shift, 2.5*RIGHT+0.5*DOWN),
|
||||||
|
ApplyMethod(symbol.shift, 0.5*(UP+LEFT))
|
||||||
|
)
|
||||||
|
self.remove(plane, labels)
|
||||||
|
return vector, symbol, coordinates
|
||||||
|
|
||||||
|
def physics_conception(self, creatures, original_vector):
|
||||||
|
self.fade_all_but(creatures, 0)
|
||||||
|
physy, compy, mathy = creatures
|
||||||
|
|
||||||
|
vector = Vector(2*RIGHT)
|
||||||
|
vector.next_to(physy, UP+RIGHT)
|
||||||
|
brace = Brace(vector, DOWN)
|
||||||
|
length = TextMobject("Length")
|
||||||
|
length.next_to(brace, DOWN)
|
||||||
|
group = VMobject(vector, brace, length)
|
||||||
|
group.rotate_in_place(np.pi/6)
|
||||||
|
vector.get_center = lambda : vector.get_start()
|
||||||
|
|
||||||
|
direction = TextMobject("Direction")
|
||||||
|
direction.next_to(vector, RIGHT)
|
||||||
|
direction.shift(UP)
|
||||||
|
|
||||||
|
two_dimensional = TextMobject("Two-dimensional")
|
||||||
|
three_dimensional = TextMobject("Three-dimensional")
|
||||||
|
two_dimensional.to_corner(UP+RIGHT)
|
||||||
|
three_dimensional.to_corner(UP+RIGHT)
|
||||||
|
|
||||||
|
random_vectors = VMobject(*[
|
||||||
|
Vector(
|
||||||
|
random.uniform(-2, 2)*RIGHT + \
|
||||||
|
random.uniform(-2, 2)*UP
|
||||||
|
).shift(
|
||||||
|
random.uniform(0, 4)*RIGHT + \
|
||||||
|
random.uniform(-1, 2)*UP
|
||||||
|
).highlight(random_color())
|
||||||
|
for x in range(5)
|
||||||
|
])
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Transform(original_vector, vector),
|
||||||
|
ApplyMethod(physy.change_mode, "speaking")
|
||||||
|
)
|
||||||
|
self.remove(original_vector)
|
||||||
|
self.add(vector )
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(length),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.remove(brace, length)
|
||||||
|
self.play(
|
||||||
|
Rotate(vector, np.pi/3, in_place = True),
|
||||||
|
Write(direction),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
for angle in -2*np.pi/3, np.pi/3:
|
||||||
|
self.play(Rotate(
|
||||||
|
vector, angle,
|
||||||
|
in_place = True,
|
||||||
|
run_time = 1
|
||||||
|
))
|
||||||
|
self.play(ApplyMethod(physy.change_mode, "plain"))
|
||||||
|
self.remove(direction)
|
||||||
|
for point in 2*UP, 4*RIGHT, ORIGIN:
|
||||||
|
self.play(ApplyMethod(vector.move_to, point))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Write(two_dimensional),
|
||||||
|
ApplyMethod(physy.change_mode, "pondering"),
|
||||||
|
ShowCreation(random_vectors, submobject_mode = "lagged_start"),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.remove(random_vectors, vector)
|
||||||
|
self.play(Transform(two_dimensional, three_dimensional))
|
||||||
|
self.dither(5)
|
||||||
|
self.remove(two_dimensional)
|
||||||
|
self.restore_creatures(creatures)
|
||||||
|
|
||||||
|
def cs_conception(self, creatures):
|
||||||
|
self.fade_all_but(creatures, 1)
|
||||||
|
physy, compy, mathy = creatures
|
||||||
|
|
||||||
|
title = TextMobject("Vectors $\\Leftrightarrow$ lists of numbers")
|
||||||
|
title.to_edge(UP)
|
||||||
|
|
||||||
|
vectors = VMobject(*map(matrix_to_mobject, [
|
||||||
|
[2, 1],
|
||||||
|
[5, 0, 0, -3],
|
||||||
|
[2.3, -7.1, 0.1],
|
||||||
|
]))
|
||||||
|
vectors.arrange_submobjects(RIGHT, buff = 1)
|
||||||
|
vectors.to_edge(LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ApplyMethod(compy.change_mode, "sassy"),
|
||||||
|
Write(title, run_time = 1)
|
||||||
|
)
|
||||||
|
self.play(Write(vectors))
|
||||||
|
self.dither()
|
||||||
|
self.play(ApplyMethod(compy.change_mode, "pondering"))
|
||||||
|
self.house_example(vectors, title)
|
||||||
|
self.restore_creatures(creatures)
|
||||||
|
|
||||||
|
|
||||||
|
def house_example(self, starter_mobject, title):
|
||||||
|
house = SVGMobject("house")
|
||||||
|
house.set_stroke(width = 0)
|
||||||
|
house.set_fill(BLUE_C, opacity = 1)
|
||||||
|
house.scale_to_fit_height(3)
|
||||||
|
house.center()
|
||||||
|
square_footage_words = TextMobject("Square footage:")
|
||||||
|
price_words = TextMobject("Price: ")
|
||||||
|
square_footage = TexMobject("2{,}600\\text{ ft}^2")
|
||||||
|
price = TextMobject("\\$300{,}000")
|
||||||
|
|
||||||
|
house.to_edge(LEFT).shift(UP)
|
||||||
|
square_footage_words.next_to(house, RIGHT)
|
||||||
|
square_footage_words.shift(0.5*UP)
|
||||||
|
square_footage_words.highlight(RED)
|
||||||
|
price_words.next_to(square_footage_words, DOWN, aligned_edge = LEFT)
|
||||||
|
price_words.highlight(GREEN)
|
||||||
|
square_footage.next_to(square_footage_words)
|
||||||
|
square_footage.highlight(RED)
|
||||||
|
price.next_to(price_words)
|
||||||
|
price.highlight(GREEN)
|
||||||
|
|
||||||
|
vector = Matrix([square_footage.copy(), price.copy()])
|
||||||
|
vector.next_to(house, RIGHT).shift(0.25*UP)
|
||||||
|
new_square_footage, new_price = vector.get_mob_matrix().flatten()
|
||||||
|
not_equals = TexMobject("\\ne")
|
||||||
|
not_equals.next_to(vector)
|
||||||
|
alt_vector = Matrix([
|
||||||
|
TextMobject("300{,}000\\text{ ft}^2").highlight(RED),
|
||||||
|
TextMobject("\\$2{,}600").highlight(GREEN)
|
||||||
|
])
|
||||||
|
alt_vector.next_to(not_equals)
|
||||||
|
|
||||||
|
brace = Brace(vector, RIGHT)
|
||||||
|
two_dimensional = TextMobject("2 dimensional")
|
||||||
|
two_dimensional.next_to(brace)
|
||||||
|
brackets = vector.get_brackets()
|
||||||
|
|
||||||
|
self.play(Transform(starter_mobject, house))
|
||||||
|
self.remove(starter_mobject)
|
||||||
|
self.add(house)
|
||||||
|
self.add(square_footage_words)
|
||||||
|
self.play(Write(square_footage, run_time = 2))
|
||||||
|
self.add(price_words)
|
||||||
|
self.play(Write(price, run_time = 2))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
FadeOut(square_footage_words), FadeOut(price_words),
|
||||||
|
Transform(square_footage, new_square_footage),
|
||||||
|
Transform(price, new_price),
|
||||||
|
Write(brackets),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.remove(square_footage_words, price_words)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Write(not_equals),
|
||||||
|
Write(alt_vector),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(FadeOut(not_equals), FadeOut(alt_vector))
|
||||||
|
self.remove(not_equals, alt_vector)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(two_dimensional),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
everything = VMobject(
|
||||||
|
house, square_footage, price, brackets, brace,
|
||||||
|
two_dimensional, title
|
||||||
|
)
|
||||||
|
self.play(ApplyMethod(everything.shift, 2*SPACE_WIDTH*LEFT))
|
||||||
|
self.remove(everything)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_mathy(self, creatures):
|
||||||
|
self.fade_all_but(creatures, 2)
|
||||||
|
physy, compy, mathy = creatures
|
||||||
|
|
||||||
|
v_color = YELLOW
|
||||||
|
w_color = BLUE
|
||||||
|
sum_color = GREEN
|
||||||
|
|
||||||
|
v_arrow = Vector([1, 1])
|
||||||
|
w_arrow = Vector([2, 1])
|
||||||
|
w_arrow.shift(v_arrow.get_end())
|
||||||
|
sum_arrow = Vector(w_arrow.get_end())
|
||||||
|
arrows = VMobject(v_arrow, w_arrow, sum_arrow)
|
||||||
|
arrows.scale(0.7)
|
||||||
|
arrows.to_edge(LEFT, buff = 2)
|
||||||
|
|
||||||
|
v_array = matrix_to_mobject([3, -5])
|
||||||
|
w_array = matrix_to_mobject([2, 1])
|
||||||
|
sum_array = matrix_to_mobject(["3+2", "-5+1"])
|
||||||
|
arrays = VMobject(
|
||||||
|
v_array, TexMobject("+"), w_array, TexMobject("="), sum_array
|
||||||
|
)
|
||||||
|
arrays.arrange_submobjects(RIGHT)
|
||||||
|
arrays.scale(0.5)
|
||||||
|
arrays.to_edge(RIGHT).shift(UP)
|
||||||
|
|
||||||
|
v_sym = TexMobject("\\vec{\\textbf{v}}")
|
||||||
|
w_sym = TexMobject("\\vec{\\textbf{w}}")
|
||||||
|
syms = VMobject(v_sym, TexMobject("+"), w_sym)
|
||||||
|
syms.arrange_submobjects(RIGHT)
|
||||||
|
syms.center().shift(2*UP)
|
||||||
|
|
||||||
|
VMobject(v_arrow, v_array, v_sym).highlight(v_color)
|
||||||
|
VMobject(w_arrow, w_array, w_sym).highlight(w_color)
|
||||||
|
VMobject(sum_arrow, sum_array).highlight(sum_color)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(syms), Write(arrays),
|
||||||
|
ShowCreation(arrows, submobject_mode = "one_at_a_time"),
|
||||||
|
ApplyMethod(mathy.change_mode, "pondering"),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.play(Blink(mathy))
|
||||||
|
self.add_scaling(arrows, syms, arrays)
|
||||||
|
|
||||||
|
def add_scaling(self, arrows, syms, arrays):
|
||||||
|
s_arrows = VMobject(
|
||||||
|
TexMobject("2"), Vector([1, 1]).highlight(YELLOW),
|
||||||
|
TexMobject("="), Vector([2, 2]).highlight(WHITE)
|
||||||
|
)
|
||||||
|
s_arrows.arrange_submobjects(RIGHT)
|
||||||
|
s_arrows.scale(0.75)
|
||||||
|
s_arrows.next_to(arrows, DOWN)
|
||||||
|
|
||||||
|
s_arrays = VMobject(
|
||||||
|
TexMobject("2"),
|
||||||
|
matrix_to_mobject([3, -5]).highlight(YELLOW),
|
||||||
|
TextMobject("="),
|
||||||
|
matrix_to_mobject(["2(3)", "2(-5)"])
|
||||||
|
)
|
||||||
|
s_arrays.arrange_submobjects(RIGHT)
|
||||||
|
s_arrays.scale(0.5)
|
||||||
|
s_arrays.next_to(arrays, DOWN)
|
||||||
|
|
||||||
|
s_syms = TexMobject(["2", "\\vec{\\textbf{v}}"])
|
||||||
|
s_syms.split()[-1].highlight(YELLOW)
|
||||||
|
s_syms.next_to(syms, DOWN)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(s_arrows), Write(s_arrays), Write(s_syms),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
class DifferentConceptions(Scene):
|
|
||||||
|
def fade_all_but(self, creatures, index):
|
||||||
|
self.play(*[
|
||||||
|
FadeOut(VMobject(pi, pi.title))
|
||||||
|
for pi in creatures[:index] + creatures[index+1:]
|
||||||
|
])
|
||||||
|
|
||||||
|
def restore_creatures(self, creatures):
|
||||||
|
self.play(*[
|
||||||
|
ApplyFunction(lambda m : m.change_mode("plain").highlight(m.color), pi)
|
||||||
|
for pi in creatures
|
||||||
|
] + [
|
||||||
|
ApplyMethod(pi.title.set_fill, WHITE, 1.0)
|
||||||
|
for pi in creatures
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class HelpsToHaveOneThought(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
physy = Physicist()
|
morty = Mortimer()
|
||||||
mathy = Mathematician(mode = "pondering")
|
morty.to_corner(DOWN+RIGHT)
|
||||||
compy = ComputerScientist()
|
morty.look(DOWN+LEFT)
|
||||||
people = [physy, compy, mathy]
|
new_morty = morty.copy().change_mode("speaking")
|
||||||
physy.name = TextMobject("Physics student").to_corner(DOWN+LEFT)
|
new_morty.look(DOWN+LEFT)
|
||||||
compy.name = TextMobject("CS student").to_corner(DOWN+RIGHT)
|
|
||||||
mathy.name = TextMobject("Mathematician").to_edge(DOWN)
|
|
||||||
names = VMobject(physy.name, mathy.name, compy.name)
|
|
||||||
names.arrange_submobjects(RIGHT, buff = 1)
|
|
||||||
names.to_corner(DOWN+LEFT)
|
|
||||||
for pi in people:
|
|
||||||
pi.next_to(pi.name, UP)
|
|
||||||
self.add(pi)
|
|
||||||
|
|
||||||
for pi in people:
|
|
||||||
self.play(Write(pi.name), run_time = 1)
|
|
||||||
self.preview_conceptions(people)
|
|
||||||
self.physics_conception(people)
|
|
||||||
self.cs_conception(people)
|
|
||||||
self.handle_mathy(people)
|
|
||||||
|
|
||||||
|
|
||||||
def preview_conceptions(self, people):
|
|
||||||
arrow = Vector(2*RIGHT+ UP)
|
|
||||||
array = matrix_to_mobject([[2], [1]])
|
|
||||||
tex = TextMobject("""
|
|
||||||
Set $V$ with operations \\\\
|
|
||||||
$a : V \\times V \\to V$ and \\\\
|
|
||||||
$s : \\mathds{R} \\times V \\to V$ such that...
|
|
||||||
""")
|
|
||||||
physy, compy, mathy = people
|
|
||||||
physy.bubble = physy.get_bubble("speech")
|
|
||||||
compy.bubble = compy.get_bubble("speech")
|
|
||||||
mathy.bubble = mathy.get_bubble(width = 4)
|
|
||||||
|
|
||||||
for pi, sym in zip(people, [arrow, array, tex]):
|
|
||||||
pi.bubble.set_fill(BLACK, opacity = 1.0)
|
|
||||||
pi.bubble.add_content(sym)
|
|
||||||
self.play(FadeIn(pi.bubble))
|
|
||||||
self.dither()
|
|
||||||
for pi in people:
|
|
||||||
self.remove(pi.bubble)
|
|
||||||
|
|
||||||
|
|
||||||
def physics_conception(self, people):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def cs_conception(self, people):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def handle_mathy(self, people):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
randys = VMobject(*[
|
||||||
|
Randolph(color = color).scale(0.8)
|
||||||
|
for color in BLUE_D, BLUE_C, BLUE_E
|
||||||
|
])
|
||||||
|
randys.arrange_submobjects(RIGHT)
|
||||||
|
randys.to_corner(DOWN+LEFT)
|
||||||
|
randy = randys.split()[1]
|
||||||
|
|
||||||
|
speech_bubble = morty.get_bubble("speech")
|
||||||
|
words = TextMobject("Think of some vector...")
|
||||||
|
speech_bubble.position_mobject_inside(words)
|
||||||
|
thought_bubble = randy.get_bubble()
|
||||||
|
arrow = Vector([2, 1]).scale(0.7)
|
||||||
|
or_word = TextMobject("or")
|
||||||
|
array = Matrix([2, 1]).scale(0.5)
|
||||||
|
q_mark = TextMobject("?")
|
||||||
|
thought = VMobject(arrow, or_word, array, q_mark)
|
||||||
|
thought.arrange_submobjects(RIGHT, buff = 0.2)
|
||||||
|
thought_bubble.position_mobject_inside(thought)
|
||||||
|
thought_bubble.set_fill(BLACK, opacity = 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.add(morty, randys)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(speech_bubble),
|
||||||
|
Transform(morty, new_morty),
|
||||||
|
Write(words)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
FadeOut(speech_bubble),
|
||||||
|
FadeOut(words),
|
||||||
|
ApplyMethod(randy.change_mode, "pondering"),
|
||||||
|
ShowCreation(thought_bubble),
|
||||||
|
Write(thought)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
class HowIWantYouToThinkAboutVectors(Scene):
|
||||||
|
def construct(self):
|
||||||
|
vector = Vector([-2, 3])
|
||||||
|
plane = NumberPlane()
|
||||||
|
axis_labels = plane.get_axis_labels()
|
||||||
|
other_vectors = VMobject(*map(Vector, [
|
||||||
|
[1, 2], [2, -1], [4, 0]
|
||||||
|
]))
|
||||||
|
colors = [GREEN_B, MAROON_B, PINK]
|
||||||
|
for v, color in zip(other_vectors.split(), colors):
|
||||||
|
v.highlight(color)
|
||||||
|
shift_val = 4*RIGHT+DOWN
|
||||||
|
|
||||||
|
dot = Dot(radius = 0.1)
|
||||||
|
dot.highlight(RED)
|
||||||
|
tail_word = TextMobject("Tail")
|
||||||
|
tail_word.shift(0.5*DOWN+2.5*LEFT)
|
||||||
|
line = Line(tail_word, dot)
|
||||||
|
|
||||||
|
self.play(ShowCreation(vector, submobject_mode = "one_at_a_time"))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(plane, summobject_mode = "lagged_start"),
|
||||||
|
Animation(vector)
|
||||||
|
)
|
||||||
|
self.play(Write(axis_labels, run_time = 1))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(dot),
|
||||||
|
ShowCreation(line),
|
||||||
|
Write(tail_word, run_time = 1)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
FadeOut(tail_word),
|
||||||
|
ApplyMethod(VMobject(dot, line).scale, 0.01)
|
||||||
|
)
|
||||||
|
self.remove(tail_word, line, dot)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.play(ApplyMethod(
|
||||||
|
vector.shift, shift_val,
|
||||||
|
path_arc = 3*np.pi/2,
|
||||||
|
run_time = 3
|
||||||
|
))
|
||||||
|
self.play(ApplyMethod(
|
||||||
|
vector.shift, -shift_val,
|
||||||
|
rate_func = rush_into,
|
||||||
|
run_time = 0.5
|
||||||
|
))
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
self.play(ShowCreation(
|
||||||
|
other_vectors,
|
||||||
|
submobject_mode = "one_at_a_time",
|
||||||
|
run_time = 3
|
||||||
|
))
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
x_axis, y_axis = plane.get_axes().split()
|
||||||
|
x_label = axis_labels.split()[0]
|
||||||
|
x_axis = x_axis.copy()
|
||||||
|
x_label = x_label.copy()
|
||||||
|
everything = VMobject(*self.mobjects)
|
||||||
|
self.play(
|
||||||
|
FadeOut(everything),
|
||||||
|
Animation(x_axis), Animation(x_label)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ListsOfNumbersAddOn(Scene):
|
||||||
|
def construct(self):
|
||||||
|
arrays = VMobject(*map(matrix_to_mobject, [
|
||||||
|
[-2, 3], [1, 2], [2, -1], [4, 0]
|
||||||
|
]))
|
||||||
|
arrays.arrange_submobjects(buff = 0.4)
|
||||||
|
arrays.scale(2)
|
||||||
|
self.play(Write(arrays))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
class CoordinateSystemWalkthrough(VectorCoordinateScene):
|
||||||
|
def construct(self):
|
||||||
|
self.introduce_coordinate_plane()
|
||||||
|
self.show_vector_coordinates()
|
||||||
|
self.coords_to_vector([3, -1])
|
||||||
|
self.vector_to_coords([-2, -1.5], integer_labels = False)
|
||||||
|
|
||||||
|
def introduce_coordinate_plane(self):
|
||||||
|
plane = NumberPlane()
|
||||||
|
x_axis, y_axis = plane.get_axes().copy().split()
|
||||||
|
x_label, y_label = plane.get_axis_labels().split()
|
||||||
|
number_line = NumberLine(tick_frequency = 1)
|
||||||
|
x_tick_marks = number_line.get_tick_marks()
|
||||||
|
y_tick_marks = x_tick_marks.copy().rotate(np.pi/2)
|
||||||
|
tick_marks = VMobject(x_tick_marks, y_tick_marks)
|
||||||
|
tick_marks.highlight(WHITE)
|
||||||
|
plane_lines = filter(
|
||||||
|
lambda m : isinstance(m, Line),
|
||||||
|
plane.submobject_family()
|
||||||
|
)
|
||||||
|
origin_words = TextMobject("Origin")
|
||||||
|
origin_words.shift(2*UP+2*LEFT)
|
||||||
|
dot = Dot(radius = 0.1).highlight(RED)
|
||||||
|
line = Line(origin_words.get_bottom(), dot.get_corner(UP+LEFT))
|
||||||
|
|
||||||
|
unit_brace = Brace(Line(RIGHT, 2*RIGHT))
|
||||||
|
one = TexMobject("1").next_to(unit_brace, DOWN)
|
||||||
|
|
||||||
|
self.add(x_axis, x_label)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(y_axis))
|
||||||
|
self.play(Write(y_label, run_time = 1))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
Write(origin_words),
|
||||||
|
GrowFromCenter(dot),
|
||||||
|
ShowCreation(line),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
FadeOut(VMobject(origin_words, dot, line))
|
||||||
|
)
|
||||||
|
self.remove(origin_words, dot, line)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(tick_marks, submobject_mode = "one_at_a_time")
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(unit_brace),
|
||||||
|
Write(one, run_time = 1)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.remove(unit_brace, one)
|
||||||
|
self.play(
|
||||||
|
*map(GrowFromCenter, plane_lines) + [
|
||||||
|
Animation(x_axis), Animation(y_axis)
|
||||||
|
])
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
FadeOut(plane),
|
||||||
|
Animation(VMobject(x_axis, y_axis, tick_marks))
|
||||||
|
)
|
||||||
|
self.remove(plane)
|
||||||
|
self.add(tick_marks)
|
||||||
|
|
||||||
|
def show_vector_coordinates(self):
|
||||||
|
starting_mobjects = list(self.mobjects)
|
||||||
|
|
||||||
|
vector = Vector([-2, 3])
|
||||||
|
x_line = Line(ORIGIN, -2*RIGHT)
|
||||||
|
y_line = Line(-2*RIGHT, -2*RIGHT+3*UP)
|
||||||
|
x_line.highlight(X_COLOR)
|
||||||
|
y_line.highlight(Y_COLOR)
|
||||||
|
|
||||||
|
array = vector_coordinate_label(vector)
|
||||||
|
x_label, y_label = array.get_mob_matrix().flatten()
|
||||||
|
x_label_copy = x_label.copy()
|
||||||
|
x_label_copy.highlight(X_COLOR)
|
||||||
|
y_label_copy = y_label.copy()
|
||||||
|
y_label_copy.highlight(Y_COLOR)
|
||||||
|
|
||||||
|
point = Dot(4*LEFT+2*UP)
|
||||||
|
point_word = TextMobject("(-4, 2) as \\\\ a point")
|
||||||
|
point_word.scale(0.7)
|
||||||
|
point_word.next_to(point, DOWN)
|
||||||
|
point.add(point_word)
|
||||||
|
|
||||||
|
self.play(ShowCreation(vector, submobject_mode = "one_at_a_time"))
|
||||||
|
self.play(Write(array))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(ApplyMethod(x_label_copy.next_to, x_line, DOWN))
|
||||||
|
self.play(ShowCreation(x_line))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(ApplyMethod(y_label_copy.next_to, y_line, LEFT))
|
||||||
|
self.play(ShowCreation(y_line))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(FadeIn(point))
|
||||||
|
self.dither()
|
||||||
|
self.play(ApplyFunction(
|
||||||
|
lambda m : m.scale_in_place(1.25).highlight(YELLOW),
|
||||||
|
array.get_brackets(),
|
||||||
|
rate_func = there_and_back
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
self.play(FadeOut(point))
|
||||||
|
self.remove(point)
|
||||||
|
self.dither()
|
||||||
|
self.clear()
|
||||||
|
self.add(*starting_mobjects)
|
||||||
|
|
||||||
|
|
||||||
|
class ThreeAxisLabels(Scene):
|
||||||
|
def construct(self):
|
||||||
|
z = TexMobject("z").scale(2)
|
||||||
|
z.show()
|
||||||
|
self.play(Write(z, run_time = 1))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
120
eola/utils.py
120
eola/utils.py
@ -5,17 +5,22 @@ from mobject import Mobject
|
|||||||
from mobject.vectorized_mobject import VMobject
|
from mobject.vectorized_mobject import VMobject
|
||||||
from mobject.tex_mobject import TexMobject, TextMobject
|
from mobject.tex_mobject import TexMobject, TextMobject
|
||||||
from animation.transform import ApplyPointwiseFunction, Transform, \
|
from animation.transform import ApplyPointwiseFunction, Transform, \
|
||||||
ApplyMethod, FadeOut
|
ApplyMethod, FadeOut, ApplyFunction
|
||||||
from animation.simple_animations import ShowCreation
|
from animation.simple_animations import ShowCreation, Write
|
||||||
from topics.number_line import NumberPlane
|
from topics.number_line import NumberPlane
|
||||||
from topics.geometry import Vector, Line, Circle
|
from topics.geometry import Vector, Line, Circle, Arrow
|
||||||
|
|
||||||
from helpers import *
|
from helpers import *
|
||||||
|
|
||||||
VECTOR_LABEL_SCALE_VAL = 0.7
|
VECTOR_LABEL_SCALE_VAL = 0.7
|
||||||
|
|
||||||
|
X_COLOR = GREEN_C
|
||||||
|
Y_COLOR = RED_C
|
||||||
|
|
||||||
def matrix_to_tex_string(matrix):
|
def matrix_to_tex_string(matrix):
|
||||||
matrix = np.array(matrix).astype("string")
|
matrix = np.array(matrix).astype("string")
|
||||||
|
if matrix.ndim == 1:
|
||||||
|
matrix = matrix.reshape((matrix.size, 1))
|
||||||
n_rows, n_cols = matrix.shape
|
n_rows, n_cols = matrix.shape
|
||||||
prefix = "\\left[ \\begin{array}{%s}"%("c"*n_cols)
|
prefix = "\\left[ \\begin{array}{%s}"%("c"*n_cols)
|
||||||
suffix = "\\end{array} \\right]"
|
suffix = "\\end{array} \\right]"
|
||||||
@ -35,7 +40,7 @@ def vector_coordinate_label(vector_mob, integer_labels = True, n_dim = 2):
|
|||||||
vect = vect.astype(int)
|
vect = vect.astype(int)
|
||||||
vect = vect[:n_dim]
|
vect = vect[:n_dim]
|
||||||
vect = vect.reshape((n_dim, 1))
|
vect = vect.reshape((n_dim, 1))
|
||||||
label = matrix_to_mobject(vect)
|
label = Matrix(vect)
|
||||||
label.scale(VECTOR_LABEL_SCALE_VAL)
|
label.scale(VECTOR_LABEL_SCALE_VAL)
|
||||||
|
|
||||||
shift_dir = np.array(vector_mob.get_end())
|
shift_dir = np.array(vector_mob.get_end())
|
||||||
@ -146,7 +151,8 @@ class Matrix(VMobject):
|
|||||||
"""
|
"""
|
||||||
VMobject.__init__(self, **kwargs)
|
VMobject.__init__(self, **kwargs)
|
||||||
matrix = np.array(matrix)
|
matrix = np.array(matrix)
|
||||||
assert(matrix.ndim == 2)
|
if matrix.ndim == 1:
|
||||||
|
matrix = matrix.reshape((matrix.size, 1))
|
||||||
if not isinstance(matrix[0][0], Mobject):
|
if not isinstance(matrix[0][0], Mobject):
|
||||||
matrix = matrix.astype("string")
|
matrix = matrix.astype("string")
|
||||||
matrix = self.string_matrix_to_mob_matrix(matrix)
|
matrix = self.string_matrix_to_mob_matrix(matrix)
|
||||||
@ -174,9 +180,6 @@ class Matrix(VMobject):
|
|||||||
mob.next_to(matrix[i-1][j], DOWN, self.v_buff)
|
mob.next_to(matrix[i-1][j], DOWN, self.v_buff)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_mob_matrix(self):
|
|
||||||
return self.mob_matrix
|
|
||||||
|
|
||||||
def add_brackets(self):
|
def add_brackets(self):
|
||||||
bracket_pair = TexMobject("\\big[ \\big]")
|
bracket_pair = TexMobject("\\big[ \\big]")
|
||||||
bracket_pair.scale(2)
|
bracket_pair.scale(2)
|
||||||
@ -185,8 +188,15 @@ class Matrix(VMobject):
|
|||||||
l_bracket.next_to(self, LEFT)
|
l_bracket.next_to(self, LEFT)
|
||||||
r_bracket.next_to(self, RIGHT)
|
r_bracket.next_to(self, RIGHT)
|
||||||
self.add(l_bracket, r_bracket)
|
self.add(l_bracket, r_bracket)
|
||||||
|
self.brackets = VMobject(l_bracket, r_bracket)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_mob_matrix(self):
|
||||||
|
return self.mob_matrix
|
||||||
|
|
||||||
|
def get_brackets(self):
|
||||||
|
return self.brackets
|
||||||
|
|
||||||
|
|
||||||
class NumericalMatrixMultiplication(Scene):
|
class NumericalMatrixMultiplication(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
@ -316,6 +326,100 @@ class NumericalMatrixMultiplication(Scene):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VectorCoordinateScene(Scene):
|
||||||
|
def position_x_coordinate(self, x_coord, x_line, vector):
|
||||||
|
x_coord.next_to(x_line, -vector[1]*UP)
|
||||||
|
x_coord.highlight(X_COLOR)
|
||||||
|
return x_coord
|
||||||
|
|
||||||
|
def position_y_coordinate(self, y_coord, y_line, vector):
|
||||||
|
y_coord.next_to(y_line, vector[0]*RIGHT)
|
||||||
|
y_coord.highlight(Y_COLOR)
|
||||||
|
return y_coord
|
||||||
|
|
||||||
|
def coords_to_vector(self, vector, coords_start = 2*RIGHT+2*UP, cleanup = True):
|
||||||
|
starting_mobjects = list(self.mobjects)
|
||||||
|
array = Matrix(vector)
|
||||||
|
array.shift(coords_start)
|
||||||
|
arrow = Vector(vector)
|
||||||
|
x_line = Line(ORIGIN, vector[0]*RIGHT)
|
||||||
|
y_line = Line(x_line.get_end(), arrow.get_end())
|
||||||
|
x_line.highlight(X_COLOR)
|
||||||
|
y_line.highlight(Y_COLOR)
|
||||||
|
x_coord, y_coord = array.get_mob_matrix().flatten()
|
||||||
|
|
||||||
|
self.play(Write(array, run_time = 1))
|
||||||
|
self.dither()
|
||||||
|
self.play(ApplyFunction(
|
||||||
|
lambda x : self.position_x_coordinate(x, x_line, vector),
|
||||||
|
x_coord
|
||||||
|
))
|
||||||
|
self.play(ShowCreation(x_line))
|
||||||
|
self.play(
|
||||||
|
ApplyFunction(
|
||||||
|
lambda y : self.position_y_coordinate(y, y_line, vector),
|
||||||
|
y_coord
|
||||||
|
),
|
||||||
|
FadeOut(array.get_brackets())
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(y_line))
|
||||||
|
self.play(ShowCreation(arrow, submobject_mode = "one_at_a_time"))
|
||||||
|
self.dither()
|
||||||
|
if cleanup:
|
||||||
|
self.clear()
|
||||||
|
self.add(*starting_mobjects)
|
||||||
|
|
||||||
|
def vector_to_coords(self, vector, integer_labels = True, cleanup = True):
|
||||||
|
starting_mobjects = list(self.mobjects)
|
||||||
|
show_creation = False
|
||||||
|
if isinstance(vector, Arrow):
|
||||||
|
arrow = vector
|
||||||
|
vector = arrow.get_end()[:2]
|
||||||
|
else:
|
||||||
|
arrow = Vector(vector)
|
||||||
|
show_creation = True
|
||||||
|
array = vector_coordinate_label(arrow, integer_labels = integer_labels)
|
||||||
|
x_line = Line(ORIGIN, vector[0]*RIGHT)
|
||||||
|
y_line = Line(x_line.get_end(), arrow.get_end())
|
||||||
|
x_line.highlight(X_COLOR)
|
||||||
|
y_line.highlight(Y_COLOR)
|
||||||
|
x_coord, y_coord = array.get_mob_matrix().flatten()
|
||||||
|
x_coord_start = self.position_x_coordinate(
|
||||||
|
x_coord.copy(), x_line, vector
|
||||||
|
)
|
||||||
|
y_coord_start = self.position_y_coordinate(
|
||||||
|
y_coord.copy(), y_line, vector
|
||||||
|
)
|
||||||
|
brackets = array.get_brackets()
|
||||||
|
|
||||||
|
if show_creation:
|
||||||
|
self.play(ShowCreation(arrow, submobject_mode = "one_at_a_time"))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(x_line),
|
||||||
|
Write(x_coord_start),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(y_line),
|
||||||
|
Write(y_coord_start),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(x_coord_start, x_coord),
|
||||||
|
Transform(y_coord_start, y_coord),
|
||||||
|
Write(brackets),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.remove(x_coord_start, y_coord_start)
|
||||||
|
self.add(x_coord, y_coord)
|
||||||
|
if cleanup:
|
||||||
|
self.clear()
|
||||||
|
self.add(*starting_mobjects)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ def z_to_vector(vector):
|
|||||||
v = np.array(vector) / norm
|
v = np.array(vector) / norm
|
||||||
phi = np.arccos(v[2])
|
phi = np.arccos(v[2])
|
||||||
if any(v[:2]):
|
if any(v[:2]):
|
||||||
#projection of vector to {x^2 + y^2 = 1}
|
#projection of vector to unit circle
|
||||||
axis_proj = v[:2] / np.linalg.norm(v[:2])
|
axis_proj = v[:2] / np.linalg.norm(v[:2])
|
||||||
theta = np.arccos(axis_proj[0])
|
theta = np.arccos(axis_proj[0])
|
||||||
if axis_proj[1] < 0:
|
if axis_proj[1] < 0:
|
||||||
|
@ -219,9 +219,14 @@ class Mobject(object):
|
|||||||
self.shift(target_point - anchor_point + buff*direction)
|
self.shift(target_point - anchor_point + buff*direction)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def stretch_to_fit(self, length, dim):
|
def stretch_to_fit(self, length, dim, stretch = True):
|
||||||
old_length = self.length_over_dim(dim)
|
old_length = self.length_over_dim(dim)
|
||||||
self.do_in_place(self.stretch, length/old_length, dim)
|
if old_length == 0:
|
||||||
|
return self
|
||||||
|
if stretch:
|
||||||
|
self.do_in_place(self.stretch, length/old_length, dim)
|
||||||
|
else:
|
||||||
|
self.do_in_place(self.scale, length/old_length)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def stretch_to_fit_width(self, width):
|
def stretch_to_fit_width(self, width):
|
||||||
@ -231,10 +236,19 @@ class Mobject(object):
|
|||||||
return self.stretch_to_fit(height, 1)
|
return self.stretch_to_fit(height, 1)
|
||||||
|
|
||||||
def scale_to_fit_width(self, width):
|
def scale_to_fit_width(self, width):
|
||||||
return self.scale(width/self.get_width())
|
return self.stretch_to_fit(width, 0, stretch = False)
|
||||||
|
|
||||||
def scale_to_fit_height(self, height):
|
def scale_to_fit_height(self, height):
|
||||||
return self.scale(height/self.get_height())
|
return self.stretch_to_fit(height, 1, stretch = False)
|
||||||
|
|
||||||
|
def move_to(self, point_or_mobject, side_to_align = ORIGIN):
|
||||||
|
if isinstance(point_or_mobject, Mobject):
|
||||||
|
target = point_or_mobject.get_critical_point(side_to_align)
|
||||||
|
else:
|
||||||
|
target = point_or_mobject
|
||||||
|
anchor_point = self.get_critical_point(side_to_align)
|
||||||
|
self.shift(target - anchor_point)
|
||||||
|
return self
|
||||||
|
|
||||||
def replace(self, mobject, stretch = False):
|
def replace(self, mobject, stretch = False):
|
||||||
if not mobject.get_num_points() and not mobject.submobjects:
|
if not mobject.get_num_points() and not mobject.submobjects:
|
||||||
@ -244,8 +258,8 @@ class Mobject(object):
|
|||||||
self.stretch_to_fit_width(mobject.get_width())
|
self.stretch_to_fit_width(mobject.get_width())
|
||||||
self.stretch_to_fit_height(mobject.get_height())
|
self.stretch_to_fit_height(mobject.get_height())
|
||||||
else:
|
else:
|
||||||
self.scale(mobject.get_width()/self.get_width())
|
self.scale_to_fit_width(mobject.get_width())
|
||||||
self.center().shift(mobject.get_center())
|
self.shift(mobject.get_center() - self.get_center())
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def position_endpoints_on(self, start, end):
|
def position_endpoints_on(self, start, end):
|
||||||
|
@ -74,6 +74,11 @@ class VMobject(Mobject):
|
|||||||
self.set_stroke(color = color)
|
self.set_stroke(color = color)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def fade(self, darkness = 0.5):
|
||||||
|
self.set_fill(opacity = 1-darkness)
|
||||||
|
Mobject.fade(self, darkness)
|
||||||
|
return self
|
||||||
|
|
||||||
def get_fill_color(self):
|
def get_fill_color(self):
|
||||||
try:
|
try:
|
||||||
self.fill_rgb[self.fill_rgb<0] = 0
|
self.fill_rgb[self.fill_rgb<0] = 0
|
||||||
|
@ -77,18 +77,36 @@ class PiCreature(SVGMobject):
|
|||||||
def change_mode(self, mode):
|
def change_mode(self, mode):
|
||||||
curr_center = self.get_center()
|
curr_center = self.get_center()
|
||||||
curr_height = self.get_height()
|
curr_height = self.get_height()
|
||||||
|
looking_direction = None
|
||||||
|
looking_direction = self.get_looking_direction()
|
||||||
should_be_flipped = self.is_flipped()
|
should_be_flipped = self.is_flipped()
|
||||||
self.__init__(mode)
|
self.__init__(mode)
|
||||||
self.scale_to_fit_height(curr_height)
|
self.scale_to_fit_height(curr_height)
|
||||||
self.shift(curr_center)
|
self.shift(curr_center)
|
||||||
if should_be_flipped^self.is_flipped():
|
self.look(looking_direction)
|
||||||
|
if should_be_flipped ^ self.is_flipped():
|
||||||
self.flip()
|
self.flip()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def look_left(self):
|
def look(self, direction):
|
||||||
self.change_mode(self.mode + "_looking_left")
|
x, y = direction[:2]
|
||||||
|
for pupil, eye in zip(self.pupils.split(), self.eyes.split()):
|
||||||
|
pupil.move_to(eye, side_to_align = direction)
|
||||||
|
if y > 0 and x != 0: # Look up and to a side
|
||||||
|
nudge_size = pupil.get_height()/4.
|
||||||
|
if x > 0:
|
||||||
|
nudge = nudge_size*(DOWN+LEFT)
|
||||||
|
else:
|
||||||
|
nudge = nudge_size*(DOWN+RIGHT)
|
||||||
|
pupil.shift(nudge)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_looking_direction(self):
|
||||||
|
return np.sign(np.round(
|
||||||
|
self.pupils.get_center() - self.eyes.get_center(),
|
||||||
|
decimals = 1
|
||||||
|
))
|
||||||
|
|
||||||
def is_flipped(self):
|
def is_flipped(self):
|
||||||
return self.eyes.submobjects[0].get_center()[0] > \
|
return self.eyes.submobjects[0].get_center()[0] > \
|
||||||
self.eyes.submobjects[1].get_center()[0]
|
self.eyes.submobjects[1].get_center()[0]
|
||||||
|
@ -172,6 +172,8 @@ class Vector(Arrow):
|
|||||||
"buff" : 0,
|
"buff" : 0,
|
||||||
}
|
}
|
||||||
def __init__(self, direction, **kwargs):
|
def __init__(self, direction, **kwargs):
|
||||||
|
if len(direction) == 2:
|
||||||
|
direction = np.append(np.array(direction), 0)
|
||||||
Arrow.__init__(self, ORIGIN, direction, **kwargs)
|
Arrow.__init__(self, ORIGIN, direction, **kwargs)
|
||||||
|
|
||||||
class DoubleArrow(Arrow):
|
class DoubleArrow(Arrow):
|
||||||
|
@ -28,7 +28,8 @@ class NumberLine(VMobject):
|
|||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
self.main_line = Line(self.x_min*RIGHT, self.x_max*RIGHT)
|
self.main_line = Line(self.x_min*RIGHT, self.x_max*RIGHT)
|
||||||
self.add(self.main_line)
|
self.tick_marks = VMobject()
|
||||||
|
self.add(self.main_line, self.tick_marks)
|
||||||
for x in self.get_tick_numbers():
|
for x in self.get_tick_numbers():
|
||||||
self.add_tick(x, self.tick_size)
|
self.add_tick(x, self.tick_size)
|
||||||
for x in self.numbers_with_elongated_ticks:
|
for x in self.numbers_with_elongated_ticks:
|
||||||
@ -37,12 +38,15 @@ class NumberLine(VMobject):
|
|||||||
self.shift(-self.number_to_point(self.number_at_center))
|
self.shift(-self.number_to_point(self.number_at_center))
|
||||||
|
|
||||||
def add_tick(self, x, size):
|
def add_tick(self, x, size):
|
||||||
self.add(Line(
|
self.tick_marks.add(Line(
|
||||||
x*RIGHT+size*DOWN,
|
x*RIGHT+size*DOWN,
|
||||||
x*RIGHT+size*UP,
|
x*RIGHT+size*UP,
|
||||||
))
|
))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_tick_marks(self):
|
||||||
|
return self.tick_marks
|
||||||
|
|
||||||
def get_tick_numbers(self):
|
def get_tick_numbers(self):
|
||||||
return np.arange(self.leftmost_tick, self.x_max, self.tick_frequency)
|
return np.arange(self.leftmost_tick, self.x_max, self.tick_frequency)
|
||||||
|
|
||||||
@ -160,6 +164,9 @@ class NumberPlane(VMobject):
|
|||||||
self.add(self.axes, self.main_lines, self.secondary_lines)
|
self.add(self.axes, self.main_lines, self.secondary_lines)
|
||||||
self.stretch(self.space_unit_to_x_unit, 0)
|
self.stretch(self.space_unit_to_x_unit, 0)
|
||||||
self.stretch(self.space_unit_to_y_unit, 1)
|
self.stretch(self.space_unit_to_y_unit, 1)
|
||||||
|
#Put x_axis before y_axis
|
||||||
|
y_axis, x_axis = self.axes.split()
|
||||||
|
self.axes = VMobject(x_axis, y_axis)
|
||||||
|
|
||||||
def init_colors(self):
|
def init_colors(self):
|
||||||
VMobject.init_colors(self)
|
VMobject.init_colors(self)
|
||||||
@ -206,6 +213,20 @@ class NumberPlane(VMobject):
|
|||||||
result.append(num)
|
result.append(num)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_axes(self):
|
||||||
|
return self.axes
|
||||||
|
|
||||||
|
def get_axis_labels(self, x_label = "x", y_label = "y"):
|
||||||
|
x_axis, y_axis = self.get_axes().split()
|
||||||
|
x_label_mob = TexMobject(x_label)
|
||||||
|
y_label_mob = TexMobject(y_label)
|
||||||
|
x_label_mob.next_to(x_axis, DOWN)
|
||||||
|
x_label_mob.to_edge(RIGHT)
|
||||||
|
y_label_mob.next_to(y_axis, RIGHT)
|
||||||
|
y_label_mob.to_edge(UP)
|
||||||
|
return VMobject(x_label_mob, y_label_mob)
|
||||||
|
|
||||||
|
|
||||||
def add_coordinates(self, x_vals = None, y_vals = None):
|
def add_coordinates(self, x_vals = None, y_vals = None):
|
||||||
self.add(*self.get_coordinate_labels(x_vals, y_vals))
|
self.add(*self.get_coordinate_labels(x_vals, y_vals))
|
||||||
return self
|
return self
|
||||||
|
Reference in New Issue
Block a user