Final animations for the clacks solution

This commit is contained in:
Grant Sanderson 2019-02-03 12:14:22 -08:00
parent 536639188c
commit 610103f92c
8 changed files with 3170 additions and 89 deletions

View file

@ -1,28 +1,62 @@
# from active_projects.clacks import question
# from active_projects.clacks import solution1
from active_projects.clacks import question
from active_projects.clacks.solution2 import block_collision_scenes
from active_projects.clacks.solution2 import simple_scenes
from active_projects.clacks.solution2 import wordy_scenes
from active_projects.clacks.solution2 import mirror_scenes
from active_projects.clacks.solution2 import pi_creature_scenes
from active_projects.clacks.solution2 import position_phase_space
from active_projects.clacks.solution2 import simple_scenes
from active_projects.clacks.solution2 import wordy_scenes
OUTPUT_DIRECTORY = "clacks_solution2"
ALL_SCENE_CLASSES = [
question.NameIntro,
block_collision_scenes.IntroducePreviousTwoVideos,
block_collision_scenes.PreviousTwoVideos,
simple_scenes.ComingUpWrapper,
wordy_scenes.ConnectionToOptics,
pi_creature_scenes.OnAnsweringTwice,
simple_scenes.LastVideoWrapper,
simple_scenes.Rectangle,
simple_scenes.ShowRectangleCreation,
simple_scenes.LeftEdge,
simple_scenes.RightEdge,
position_phase_space.IntroducePositionPhaseSpace,
position_phase_space.UnscaledPositionPhaseSpaceMass100,
simple_scenes.FourtyFiveDegreeLine,
position_phase_space.EqualMassCase,
pi_creature_scenes.AskAboutEqualMassMomentumTransfer,
position_phase_space.FailedAngleRelation,
position_phase_space.UnscaledPositionPhaseSpaceMass10,
pi_creature_scenes.ComplainAboutRelevanceOfAnalogy,
simple_scenes.LastVideoWrapper,
simple_scenes.NoteOnEnergyLostToSound,
position_phase_space.RescaleCoordinates,
wordy_scenes.ConnectionToOpticsTransparent,
position_phase_space.RescaleCoordinatesMass16,
position_phase_space.RescaleCoordinatesMass64,
position_phase_space.RescaleCoordinatesMass100,
position_phase_space.IntroduceVelocityVector,
position_phase_space.IntroduceVelocityVectorWithoutZoom,
position_phase_space.ShowMomentumConservation,
wordy_scenes.RearrangeMomentumEquation,
simple_scenes.DotProductVideoWrapper,
simple_scenes.ShowDotProductMeaning,
position_phase_space.JustTheProcessNew,
mirror_scenes.ShowTrajectoryWithChangingTheta,
pi_creature_scenes.ReplaceOneTrickySceneWithAnother,
mirror_scenes.MirrorAndWiresOverlay,
pi_creature_scenes.NowForTheGoodPart,
mirror_scenes.ReflectWorldThroughMirrorNew,
mirror_scenes.ReflectWorldThroughMirrorThetaPoint2,
mirror_scenes.ReflectWorldThroughMirrorThetaPoint1,
simple_scenes.AskAboutAddingThetaToItself,
simple_scenes.AskAboutAddingThetaToItselfThetaPoint1,
simple_scenes.AskAboutAddingThetaToItselfThetaPoint2,
simple_scenes.FinalFormula,
simple_scenes.ArctanSqrtPoint1Angle,
simple_scenes.ReviewWrapper,
simple_scenes.SurprisedRandy,
simple_scenes.TwoSolutionsWrapper,
simple_scenes.FinalQuote,
simple_scenes.EndScreen,
simple_scenes.ClacksSolution2Thumbnail,
]

View file

@ -13,7 +13,7 @@ class Block(Square):
"stroke_color": WHITE,
"fill_color": None,
"sheen_direction": UL,
"sheen": 0.5,
"sheen_factor": 0.5,
"sheen_direction": UL,
}
@ -43,7 +43,7 @@ class Block(Square):
def mass_to_color(self, mass):
colors = [
LIGHT_GREY,
BLUE_B,
BLUE_D,
BLUE_D,
BLUE_E,
BLUE_E,
@ -225,7 +225,7 @@ class ClackFlashes(ContinualAnimation):
ContinualAnimation.__init__(self, group, **kwargs)
def update_mobject(self, dt):
total_time = self.external_time
total_time = self.get_time()
group = self.mobject
for flash in self.flashes:
if flash.start_time < total_time < flash.end_time:
@ -238,6 +238,9 @@ class ClackFlashes(ContinualAnimation):
if flash.mobject in group:
group.remove(flash.mobject)
def get_time(self):
return self.external_time
class Wall(Line):
CONFIG = {
@ -410,6 +413,10 @@ class NameIntro(Scene):
rate_func=None,
)
)
self.play(
Flash(brown.get_right(), run_time=flash_time),
Restore(brown, rate_func=None)
)
class MathAndPhysicsConspiring(Scene):
@ -1558,16 +1565,16 @@ class Thumbnail(BlocksAndWallExample, MovingCameraScene):
BlocksAndWallExample.setup(self)
def construct(self):
# self.camera_frame.shift(0.9 * UP)
self.mobjects.insert(
0,
FullScreenFadeRectangle(
color=DARK_GREY,
opacity=0.5,
sheen_direction=UL,
sheen=0.5,
),
)
self.camera_frame.shift(0.9 * UP)
# self.mobjects.insert(
# 0,
# FullScreenFadeRectangle(
# color=DARK_GREY,
# opacity=0.5,
# sheen_direction=UL,
# sheen=0.5,
# ),
# )
self.thicken_lines()
self.grow_labels()
self.add_vector()
@ -1587,7 +1594,7 @@ class Thumbnail(BlocksAndWallExample, MovingCameraScene):
def add_vector(self):
blocks = self.blocks
arrow = Vector(
arrow = self.arrow = Vector(
2.5 * LEFT,
color=RED,
rectangular_stem_width=1.5,
@ -1600,7 +1607,9 @@ class Thumbnail(BlocksAndWallExample, MovingCameraScene):
self.add(arrow)
def add_text(self):
question = TextMobject("How many\\\\collisions?")
question = self.question = TextMobject(
"How many\\\\collisions?"
)
question.scale(2.5)
question.to_edge(UP)
question.set_color(YELLOW)

View file

@ -7,7 +7,7 @@ class PreviousTwoVideos(BlocksAndWallExample):
"sliding_blocks_config": {
"block1_config": {
"mass": 1e2,
"velocity": -1,
"velocity": -2,
"width": 4,
"distance": 8,
},

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,16 @@ class OnAnsweringTwice(TeacherStudentsScene):
class AskAboutEqualMassMomentumTransfer(TeacherStudentsScene):
def construct(self):
pass
self.student_says("Why?")
self.change_student_modes("confused", "confused")
self.wait()
self.play(
RemovePiCreatureBubble(self.students[2]),
self.teacher.change, "raise_right_hand"
)
self.change_all_student_modes("pondering")
self.look_at(self.hold_up_spot + 2 * UP)
self.wait(5)
class ComplainAboutRelevanceOfAnalogy(TeacherStudentsScene):
@ -76,3 +85,34 @@ class ComplainAboutRelevanceOfAnalogy(TeacherStudentsScene):
self.hold_up_spot + UP,
)
self.wait(3)
class ReplaceOneTrickySceneWithAnother(TeacherStudentsScene):
def construct(self):
self.student_says(
"This replaces one tricky\\\\problem with another",
student_index=1,
target_mode="sassy",
added_anims=[self.teacher.change, "happy"],
)
self.change_student_modes("erm", "sassy", "angry")
self.wait(4)
self.play(
RemovePiCreatureBubble(self.students[1]),
self.teacher.change, "raise_right_hand",
self.get_student_changes(*3 * ["pondering"])
)
self.look_at(self.hold_up_spot + 2 * UP)
self.wait(5)
class NowForTheGoodPart(TeacherStudentsScene):
def construct(self):
self.teacher_says(
r"Now for the \\ good part!",
target_mode="hooray",
added_anims=[self.get_student_changes(
"hooray", "surprised", "happy"
)],
)
self.wait(2)

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,841 @@
from big_ol_pile_of_manim_imports import *
from old_projects.lost_lecture import ShowWord
from active_projects.clacks.solution2.mirror_scenes import ReflectWorldThroughMirrorNew
from active_projects.clacks.question import Thumbnail
class LastVideoWrapper(Scene):
class WrapperScene(Scene):
CONFIG = {
"title": "Title",
"shade_of_grey": "#333333"
}
def construct(self):
title = TextMobject("Last time...")
title = TextMobject(self.title)
title.scale(1.5)
title.to_edge(UP)
rect = ScreenRectangle(height=6)
rect.next_to(title, DOWN)
big_rect = self.get_big_rect()
screen_rect = self.get_screen_rect()
screen_rect.next_to(title, DOWN)
self.add(big_rect, screen_rect)
self.play(
FadeInFromDown(title),
ShowCreation(rect)
FadeIn(big_rect),
FadeInFrom(title, DOWN),
FadeInFrom(screen_rect, UP),
)
self.wait()
def get_big_rect(self):
big_rect = FullScreenFadeRectangle()
big_rect.set_fill(self.shade_of_grey, 1)
return big_rect
def get_screen_rect(self, height=6):
screen_rect = ScreenRectangle(height=height)
screen_rect.set_fill(BLACK, 1)
return screen_rect
class ComingUpWrapper(WrapperScene):
CONFIG = {"title": "Coming up..."}
class LastVideoWrapper(WrapperScene):
CONFIG = {"title": "Last time..."}
class LeftEdge(Scene):
CONFIG = {
"text": "Left edge",
"vect": LEFT,
}
def construct(self):
words = TextMobject(self.text)
arrow = Vector(self.vect)
arrow.match_width(words)
arrow.next_to(words, DOWN)
self.play(
FadeInFromDown(words),
GrowArrow(arrow)
)
self.wait()
class RightEdge(LeftEdge):
CONFIG = {
"text": "Right edge",
"vect": RIGHT,
}
class NoteOnEnergyLostToSound(Scene):
def construct(self):
self.add(TextMobject(
"Yeah yeah, the clack sound\\\\"
"would require energy, but\\\\"
"don't let accuracy get in the\\\\"
"way of delight!",
alignment="",
))
class DotProductVideoWrapper(WrapperScene):
CONFIG = {"title": "Dot product"}
class Rectangle(Scene):
def construct(self):
rect = ScreenRectangle(height=FRAME_HEIGHT - 0.25)
rect.set_stroke(WHITE, 6)
self.add(rect)
class ShowRectangleCreation(Scene):
def construct(self):
rect = ScreenRectangle(height=2)
rect.set_stroke(YELLOW, 6)
self.play(ShowCreation(rect))
self.play(FadeOut(rect))
class ShowDotProductMeaning(Scene):
def construct(self):
v_vect = Vector(2 * RIGHT, color=YELLOW)
w_vect = Vector(3 * RIGHT, color=PINK)
dot = Dot(color=RED)
dot.shift(DOWN)
v_vect.angle_tracker = ValueTracker()
w_vect.angle_tracker = ValueTracker()
def update_vect(vect):
target = vect.angle_tracker.get_value()
vect.rotate(target - vect.get_angle())
vect.shift(dot.get_center() - vect.get_start())
v_vect.add_updater(update_vect)
w_vect.add_updater(update_vect)
v_label = TexMobject("\\vec{\\textbf{v}}")
v_label.vect = v_vect
w_label = TexMobject("\\vec{\\textbf{w}}")
w_label.vect = w_vect
for label in v_label, w_label:
label.match_color(label.vect)
label.set_stroke(BLACK, 5, background=True)
def update_label(label):
target = np.array(label.vect.get_end())
target += 0.25 * normalize(label.vect.get_vector())
label.move_to(target)
v_label.add_updater(update_label)
w_label.add_updater(update_label)
title = TexMobject(
"\\vec{\\textbf{w}}",
"\\cdot",
"\\vec{\\textbf{v}}",
"=",
"||", "\\vec{\\textbf{w}}", "||",
"\\cdot",
"||", "\\vec{\\textbf{v}}", "||",
"\\cdot",
"\\cos(\\theta)"
)
title.set_color_by_tex_to_color_map({
"textbf{v}": v_vect.get_color(),
"textbf{w}": w_vect.get_color(),
})
title.to_edge(UP)
def get_w_line():
center = dot.get_center()
direction = w_vect.get_vector()
return Line(
center - 3 * direction,
center + 3 * direction,
stroke_color=LIGHT_GREY,
stroke_width=1,
)
w_line = updating_mobject_from_func(get_w_line)
def get_proj_v():
center = dot.get_center()
v = v_vect.get_vector()
w = w_vect.get_vector()
w_unit = normalize(w)
result = Vector(np.dot(v, w_unit) * w_unit)
result.set_fill(v_vect.get_color(), 0.5)
result.shift(center - result.get_start())
return result
proj_v = updating_mobject_from_func(get_proj_v)
def get_proj_line():
return DashedLine(
v_vect.get_end(),
proj_v.get_end(),
stroke_width=1,
dashed_segment_length=0.025,
)
proj_line = updating_mobject_from_func(get_proj_line)
template_line = Line(LEFT, RIGHT)
def get_vect_brace(vect):
brace = Brace(template_line, UP, buff=SMALL_BUFF)
brace.set_width(vect.get_length(), stretch=True)
angle = vect.get_angle() % TAU
if angle < PI:
angle += PI
brace.rotate(angle, about_point=ORIGIN)
brace.shift(vect.get_center())
return brace
w_brace = updating_mobject_from_func(
lambda: get_vect_brace(w_vect)
)
proj_v_brace = updating_mobject_from_func(
lambda: get_vect_brace(proj_v)
)
def get_arc():
center = dot.get_center()
a1 = w_vect.get_angle()
a2 = v_vect.get_angle()
arc = Arc(
start_angle=a1,
angle=a2 - a1,
radius=0.5,
arc_center=center,
)
theta = TexMobject("\\theta")
p = arc.point_from_proportion(0.5)
theta.move_to(
center + 1.5 * (p - center)
)
return VGroup(arc, theta)
arc = updating_mobject_from_func(get_arc)
self.add(
title[:3],
w_vect, v_vect, dot,
w_label, v_label,
)
self.play(
v_vect.angle_tracker.set_value, 170 * DEGREES,
w_vect.angle_tracker.set_value, 45 * DEGREES,
run_time=2,
)
self.wait()
w_brace.update()
self.play(
GrowFromCenter(w_brace),
Write(title[3:7])
)
self.add(w_line, w_vect, w_label, dot)
self.play(ShowCreation(w_line))
proj_v.update()
self.play(
ShowCreation(proj_line),
TransformFromCopy(v_vect, proj_v),
)
self.add(proj_v, proj_line, dot)
proj_v_brace.update()
self.play(
GrowFromCenter(proj_v_brace),
FadeInFromDown(title[7:])
)
arc.update()
self.play(Write(arc))
self.wait()
for angle in [135, 225, 270, 90, 150]:
self.play(
v_vect.angle_tracker.set_value, angle * DEGREES,
run_time=2
)
self.wait()
class FinalComment(Scene):
def construct(self):
self.add(TextMobject(
"Thoughts on what ending should go here?\\\\"
"See the Patreon post."
))
class FourtyFiveDegreeLine(Scene):
CONFIG = {
"angle": 45 * DEGREES,
"label_config": {
"num_decimal_places": 0,
"unit": "^\\circ",
"label_height": 0.3,
},
"degrees": True
}
def construct(self):
angle = self.angle
arc = Arc(angle, radius=1)
label = DecimalNumber(0, **self.label_config)
label.set_height(self.label_config["label_height"])
label.next_to(arc, RIGHT)
label.shift(0.5 * SMALL_BUFF * UP)
line1 = Line(ORIGIN, 3 * RIGHT)
line2 = line1.copy()
if self.degrees:
target_value = int(angle / DEGREES)
else:
target_value = angle
self.add(line1, label)
self.play(
ChangeDecimalToValue(label, target_value),
ShowCreation(arc),
Rotate(line2, angle, about_point=ORIGIN)
)
self.wait()
class ArctanSqrtPoint1Angle(FourtyFiveDegreeLine):
CONFIG = {
"angle": np.arctan(np.sqrt(0.1)),
}
class AskAboutAddingThetaToItself(Scene):
CONFIG = {
"theta": np.arctan(0.25),
"wait_time": 0.25,
"wedge_radius": 3,
"theta_symbol_scale_val": 0.5,
"number_height": 0.2,
}
def construct(self):
theta = self.theta
groups = self.get_groups(theta)
horizon = self.get_horizon()
counter = ValueTracker(0)
dynamic_ineq = self.get_dynamic_inequality(counter)
semicircle = self.get_semicircle()
self.add(horizon)
self.add(dynamic_ineq)
for n in range(len(groups)):
counter.set_value(n + 1)
if n < len(groups) - 1:
groups[n][-1].set_color(YELLOW)
if n > 0:
groups[n - 1][-1].set_color(WHITE)
self.add(groups[:n + 1])
self.add_sound("pen_click", gain=-20)
self.wait(self.wait_time)
self.wait(0.5)
counter.set_value(counter.get_value() - 1)
self.remove(groups[-1])
self.add_sound("pen_click", gain=-20)
self.wait()
self.play(ShowCreation(semicircle))
self.play(FadeOut(semicircle))
self.wait(3)
def get_group(self, theta):
# Define group
wedge_radius = self.wedge_radius
wedge = VGroup(
Line(ORIGIN, wedge_radius * RIGHT),
Line(ORIGIN, wedge_radius * RIGHT).rotate(
theta, about_point=ORIGIN
),
)
wedge.set_stroke((WHITE, GREY), 2)
arc = Arc(theta, radius=1)
theta_symbol = TexMobject("\\theta")
tssv = self.theta_symbol_scale_val
theta_symbol.scale(tssv)
theta_symbol.next_to(arc, RIGHT, tssv / 2)
theta_symbol.shift(tssv * SMALL_BUFF * UP)
return VGroup(wedge, arc, theta_symbol)
def get_groups(self, theta):
group = self.get_group(theta)
angles = [k * theta for k in range(int(PI / theta) + 1)]
groups = VGroup(*[
group.copy().rotate(angle, about_point=ORIGIN)
for angle in angles
])
# colors = it.cycle([BLUE_D, BLUE_B, BLUE_C, GREY_BROWN])
colors = it.cycle([BLUE_D, GREY_BROWN])
for n, angle, group, color in zip(it.count(1), angles, groups, colors):
wedge, arc, symbol = group
symbol.rotate(-angle)
arc.set_color(color)
number = Integer(n)
number.set_height(self.number_height)
number.move_to(center_of_mass([
wedge[0].get_end(),
wedge[1].get_end(),
]))
group.add(number)
groups[-1][-1].set_color(RED)
return groups
def get_horizon(self):
horizon = DashedLine(5 * LEFT, 5 * RIGHT)
horizon.set_stroke(WHITE, 1)
return horizon
def get_semicircle(self):
return Arc(
start_angle=0,
angle=PI,
radius=self.wedge_radius / 2,
color=YELLOW,
stroke_width=4,
)
def get_inequality(self):
ineq = TexMobject(
"N", "\\cdot", "\\theta", "<",
"\\pi", "=", "3.1415926\\dots"
)
N = ineq.get_part_by_tex("N")
self.pi_symbol = ineq.get_part_by_tex("\\pi")
N.set_color(YELLOW)
# ineq[-3:].set_color(BLUE)
brace = Brace(N, UP, buff=SMALL_BUFF)
text = brace.get_text("Maximum", buff=SMALL_BUFF)
group = VGroup(ineq, brace, text)
group.next_to(ORIGIN, DOWN, MED_LARGE_BUFF)
return group
def get_dynamic_inequality(self, counter):
multiple = Integer(0)
dot = TexMobject("\\cdot")
theta_tex = TexMobject("({:.2f})".format(self.theta))
eq = TexMobject("=")
value = DecimalNumber(0)
ineq = TexMobject("<")
pi = TexMobject("\\pi", "=", "3.1415926\\dots")
# pi.set_color(BLUE)
group = VGroup(
multiple, dot, theta_tex,
eq, value,
ineq, pi
)
group.arrange_submobjects(RIGHT, buff=0.2)
group.next_to(ORIGIN, DOWN, buff=LARGE_BUFF)
theta_brace = Brace(group[2], DOWN, buff=SMALL_BUFF)
theta_symbol = theta_brace.get_tex("\\theta")
group.add(theta_brace, theta_symbol)
# group.align_to(self.pi_symbol, RIGHT)
def get_count():
return int(counter.get_value())
def get_product():
return get_count() * self.theta
def is_greater_than_pi():
return get_product() > PI
def get_color():
return RED if is_greater_than_pi() else YELLOW
def get_ineq():
result = TexMobject(
">" if is_greater_than_pi() else "<"
)
result.set_color(get_color())
result.move_to(ineq)
return result
dynamic_ineq = updating_mobject_from_func(get_ineq)
group.remove(ineq)
group.add(dynamic_ineq)
multiple.add_updater(lambda m: m.set_value(get_count()))
multiple.add_updater(lambda m: m.next_to(dot, LEFT, 0.2))
multiple.add_updater(lambda m: m.set_color(get_color()))
value.add_updater(lambda m: m.set_value(get_product()))
return group
class AskAboutAddingThetaToItselfThetaPoint1(AskAboutAddingThetaToItself):
CONFIG = {
"theta": 0.1,
"wait_time": 0.1,
"theta_symbol_scale_val": 0.25,
"number_height": 0.15,
}
class AskAboutAddingThetaToItselfThetaPoint2(AskAboutAddingThetaToItself):
CONFIG = {
"theta": 0.2,
"wait_time": 0.1,
}
class FinalFormula(Scene):
def construct(self):
text = TextMobject("Final answer: ")
t2c_map = {
"\\theta": BLUE,
"m_1": GREEN,
"m_2": RED,
}
formula = TexMobject(
"\\left\\lfloor",
"{\\pi", "\\over", "\\theta}",
"\\right\\rfloor"
)
formula.set_color_by_tex_to_color_map(t2c_map)
group = VGroup(text, formula)
group.arrange_submobjects(RIGHT)
group.scale(1.5)
group.to_edge(UP)
self.play(Write(text))
self.play(FadeInFrom(formula))
self.play(ShowCreationThenFadeAround(formula))
self.wait()
theta_eq = TexMobject(
"\\theta", "=", "\\arctan", "\\left(",
"\\sqrt",
"{{m_2", "\\over", "m_1}}",
"\\right)"
)
theta_eq.set_color_by_tex_to_color_map(t2c_map)
theta_eq.scale(1.5)
theta_eq.next_to(group, DOWN, MED_LARGE_BUFF)
self.play(TransformFromCopy(
formula.get_part_by_tex("\\theta"),
theta_eq.get_part_by_tex("\\theta"),
))
self.play(Write(theta_eq[1:]))
self.wait()
class ReviewWrapper(WrapperScene):
CONFIG = {"title": "To review:"}
class SurprisedRandy(Scene):
def construct(self):
randy = Randolph()
self.play(randy.change, "surprised", 3 * UR)
self.play(Blink(randy))
self.play(randy.change, "confused")
self.play(Blink(randy))
self.wait()
class TwoSolutionsWrapper(WrapperScene):
def construct(self):
big_rect = self.get_big_rect()
screen_rects = VGroup(*[
self.get_screen_rect(height=3)
for x in range(2)
])
screen_rects.arrange_submobjects(RIGHT, buff=LARGE_BUFF)
title = TextMobject("Two solutions")
title.scale(1.5)
title.to_edge(UP)
screen_rects.next_to(title, DOWN, LARGE_BUFF)
# pi creatures
pis = VGroup(
Randolph(color=BLUE_D),
Randolph(color=BLUE_E),
Randolph(color=BLUE_B),
Mortimer().scale(1.2)
)
pis.set_height(2)
pis.arrange_submobjects(RIGHT, buff=MED_LARGE_BUFF)
pis.to_edge(DOWN, buff=SMALL_BUFF)
self.add(big_rect, title, pis)
self.play(
LaggedStart(
ShowCreation, screen_rects.copy().set_fill(opacity=0),
lag_ratio=0.8
),
LaggedStart(
FadeIn, screen_rects,
lag_ratio=0.8
),
LaggedStart(
ApplyMethod, pis,
lambda pi: (pi.change, "pondering", screen_rects[0])
),
)
self.play(Blink(random.choice(pis)))
self.play(LaggedStart(
ApplyMethod, pis,
lambda pi: (pi.change, "thinking", screen_rects[1])
))
self.play(Blink(random.choice(pis)))
self.wait()
class FinalQuote(Scene):
def construct(self):
quote_text = """
A change of perspective\\\\
is worth 80 IQ points.
"""
quote_parts = [s for s in quote_text.split(" ") if s]
quote = TextMobject(
*quote_parts,
)
quote.scale(1.2)
quote.shift(2 * RIGHT + UP)
image = ImageMobject("AlanKay")
image.set_height(6)
image.to_corner(UL)
image.shift(2 * LEFT + 0.5 * UP)
name = TextMobject("Alan Kay")
name.scale(1.5)
name.next_to(image, DOWN)
name.shift_onto_screen()
self.play(
FadeInFromDown(image),
Write(name),
)
self.wait()
for word in quote:
self.play(ShowWord(word))
self.wait(0.005 * len(word)**1.5)
self.wait()
class EndScreen(PatreonEndScreen):
CONFIG = {
"specific_patrons": [
"1stViewMaths",
"Adam Kozak",
"Adrian Robinson",
"Alexis Olson",
"Ali Yahya",
"Andreas Benjamin Brössel",
"Andrew Busey",
"Ankalagon",
"Antonio Juarez",
"Arjun Chakroborty",
"Art Ianuzzi",
"Arthur Zey",
"Awoo",
"Bernd Sing",
"Bob Sanderson",
"Boris Veselinovich",
"Brian Staroselsky",
"Britt Selvitelle",
"Burt Humburg",
"Chad Hurst",
"Charles Southerland",
"Chris Connett",
"Christian Kaiser",
"Clark Gaebel",
"Cooper Jones",
"D. Sivakumar",
"Danger Dai",
"Dave B",
"Dave Kester",
"dave nicponski",
"David Clark",
"David Gow",
"Delton Ding",
"Devarsh Desai",
"eaglle",
"emptymachine",
"Eric Younge",
"Eryq Ouithaqueue",
"Evan Phillips",
"Federico Lebron",
"Florian Chudigiewitsch",
"Giovanni Filippi",
"Graham",
"Hal Hildebrand",
"Hitoshi Yamauchi",
"J",
"j eduardo perez",
"Jacob Magnuson",
"Jameel Syed",
"James Hughes",
"Jan Pijpers",
"Jason Hise",
"Jeff Linse",
"Jeff Straathof",
"John Griffith",
"John Haley",
"John Shaughnessy",
"John V Wertheim",
"Jonathan Eppele",
"Jonathan Wilson",
"Jordan Scales",
"Joseph John Cox",
"Joseph Kelly",
"Juan Benet",
"Kai-Siang Ang",
"Kanan Gill",
"Kaustuv DeBiswas",
"L0j1k",
"Lee Redden",
"Linh Tran",
"Luc Ritchie",
"Ludwig Schubert",
"Lukas -krtek.net- Novy",
"Lukas Biewald",
"Magister Mugit",
"Magnus Dahlström",
"Magnus Lysfjord",
"Mark B Bahu",
"Mark Heising",
"Mathew Bramson",
"Mathias Jansson",
"Matt Langford",
"Matt Roveto",
"Matt Russell",
"Matthew Cocke",
"Mauricio Collares",
"Michael Faust",
"Michael Hardel",
"Mike Coleman",
"Mustafa Mahdi",
"Márton Vaitkus",
"Nathan Jessurun",
"Nero Li",
"Omar Zrien",
"Owen Campbell-Moore",
"Peter Ehrnstrom",
"Peter Mcinerney",
"Quantopian",
"Randy C. Will",
"Richard Barthel",
"Richard Burgmann",
"Richard Comish",
"Ripta Pasay",
"Rish Kundalia",
"Robert Teed",
"Roobie",
"Roy Larson",
"Ryan Atallah",
"Ryan Williams",
"Samuel D. Judge",
"Scott Gray",
"Scott Walter, Ph.D.",
"Sindre Reino Trosterud",
"soekul",
"Solara570",
"Song Gao",
"Stevie Metke",
"Ted Suzman",
"Tihan Seale",
"Valeriy Skobelev",
"Vassili Philippov",
"Xavier Bernard",
"Yana Chernobilsky",
"Yaw Etse",
"YinYangBalance.Asia",
"Yu Jun",
"Zach Cardwell",
],
}
class ClacksSolution2Thumbnail(Scene):
def construct(self):
self.add_scene1()
self.add_scene2()
arrow = TexMobject("\\Updownarrow")
arrow.set_height(2)
arrow.set_color(YELLOW)
arrow.set_stroke(Color("red"), 2, background=True)
self.add(arrow)
def add_scene1(self):
scene1 = Thumbnail(
sliding_blocks_config={
"block1_config": {
"label_text": "$100^{d}$ kg",
"distance": 8,
},
}
)
VGroup(*scene1.mobjects).shift(0.9 * DOWN)
scene1.remove(scene1.question)
self.add(*scene1.mobjects)
rect = FullScreenFadeRectangle(fill_opacity=1)
rect.shift(FRAME_HEIGHT * UP / 2)
self.add(rect)
def add_scene2(self):
scene2 = ReflectWorldThroughMirrorNew(
skip_animations=True,
file_writer_config={
"write_to_movie": False,
},
end_at_animation_number=18,
center=1.5 * UP,
)
worlds = VGroup(scene2.world, *scene2.reflected_worlds)
mirrors = VGroup(*[rw[1] for rw in worlds])
mirrors.set_stroke(width=5)
randys = VGroup(*[rw[-1] for rw in worlds])
triangles = VGroup(*[rw[0] for rw in worlds])
trajectories = VGroup(
scene2.trajectory,
*scene2.reflected_trajectories
)
trajectories.set_stroke(YELLOW, 1)
beams1, beams2 = [
scene2.get_shooting_beam_anims(
path,
max_stroke_width=20,
max_time_width=1,
num_flashes=50,
)
for path in [
scene2.trajectory,
scene2.ghost_trajectory,
]
]
beams = beams1 + beams2
beams = beams2
flashes = VGroup()
for beam in beams:
beam.update(0.5)
flashes.add(beam.mobject)
dot = Dot(color=YELLOW, radius=0.1)
dot.move_to(flashes[0].get_left())
flashes.add(dot)
self.add(mirrors, triangles, randys)
self.add(trajectories[0].set_stroke(width=3))
self.add(flashes)

View file

@ -1,4 +1,5 @@
from big_ol_pile_of_manim_imports import *
from active_projects.clacks.solution2.position_phase_space import ShowMomentumConservation
class ConnectionToOptics(Scene):
@ -145,7 +146,7 @@ class ConnectionToOptics(Scene):
title = VGroup(*map(TextMobject, [
"Angle of\\\\Incidence",
"=",
"Angle of\\\\Refraction",
"Angle of\\\\Reflection",
])).arrange_submobjects(RIGHT)
title.set_color(YELLOW)
h_line = Line(LEFT, RIGHT)
@ -203,3 +204,115 @@ class ConnectionToOptics(Scene):
class ConnectionToOpticsTransparent(ConnectionToOptics):
pass
class RearrangeMomentumEquation(ShowMomentumConservation):
def setup(self):
pass # Don't build all the things
def construct(self):
self.add(FullScreenFadeRectangle(
fill_color=BLACK,
fill_opacity=0.95,
))
self.show_initial_dot_product()
self.show_with_x_and_y()
def show_initial_dot_product(self):
equation = self.get_momentum_equation()
dot_product = self.get_dot_product(
"m_1", "m_2", "v_1", "v_2"
)
dot_product.next_to(equation, DOWN, LARGE_BUFF)
m_array, dot, v_array, rhs = dot_product
m_array.get_entries().set_color(BLUE)
v_array.get_entries().set_color(RED)
self.add(equation)
self.play(FadeInFromDown(VGroup(
m_array.get_brackets(), dot,
v_array.get_brackets(), rhs,
)))
self.play(TransformFromCopy(
equation.get_parts_by_tex("m_"),
m_array.get_entries(),
))
self.play(TransformFromCopy(
equation.get_parts_by_tex("v_"),
v_array.get_entries(),
))
self.wait()
self.simple_dot_product = dot_product
self.momentum_equation = equation
def show_with_x_and_y(self):
simple_dot_product = self.simple_dot_product
momentum_equation = self.momentum_equation
new_equation = TexMobject(
"\\sqrt{m_1}",
"\\left(", "\\sqrt{m_1}", "v_1", "\\right)",
"+", "\\sqrt{m_2}",
"\\left(", "\\sqrt{m_2}", "v_2", "\\right)",
"=", "\\text{const.}",
)
new_equation.set_color_by_tex_to_color_map({
"m_": BLUE,
"v_": RED,
})
new_equation.next_to(momentum_equation, DOWN, MED_LARGE_BUFF)
x_term = new_equation[1:5]
y_term = new_equation[7:11]
x_brace = Brace(x_term, DOWN)
y_brace = Brace(y_term, DOWN)
dx_dt = x_brace.get_tex("dx / dt")
dy_dt = y_brace.get_tex("dy / dt")
new_eq_group = VGroup(
new_equation, x_brace, y_brace, dx_dt, dy_dt
)
new_eq_group.generate_target()
new_dot_product = self.get_dot_product()
m_array, dot, d_array, rhs = new_dot_product
new_dot_product.next_to(momentum_equation, DOWN)
new_eq_group.target.next_to(new_dot_product, DOWN, LARGE_BUFF)
self.play(
FadeInFrom(new_equation, UP),
simple_dot_product.to_edge, DOWN, LARGE_BUFF,
)
self.wait()
self.play(
GrowFromCenter(x_brace),
GrowFromCenter(y_brace),
FadeInFrom(dx_dt, UP),
FadeInFrom(dy_dt, UP),
)
self.wait()
self.play(
FadeIn(VGroup(
m_array.get_brackets(), dot,
d_array.get_brackets(), rhs
)),
MoveToTarget(new_eq_group)
)
self.play(TransformFromCopy(
VGroup(
VGroup(new_equation[0]),
VGroup(new_equation[6]),
),
m_array.get_entries(),
))
self.play(TransformFromCopy(
VGroup(dx_dt, dy_dt),
d_array.get_entries(),
))
self.wait()
class NewSceneName(Scene):
def construct(self):
pass