Files

878 lines
24 KiB
Python

from manimlib.imports import *
from old_projects.lost_lecture import ShowWord
from old_projects.clacks.solution2.mirror_scenes import ReflectWorldThroughMirrorNew
from old_projects.clacks.question import Thumbnail
class WrapperScene(Scene):
CONFIG = {
"title": "Title",
"shade_of_grey": "#333333"
}
def construct(self):
title = TextMobject(self.title)
title.scale(1.5)
title.to_edge(UP)
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(
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 = always_redraw(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 = always_redraw(get_proj_v)
def get_proj_line():
return DashedLine(
v_vect.get_end(),
proj_v.get_end(),
stroke_width=1,
dash_length=0.025,
)
proj_line = always_redraw(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 = always_redraw(
lambda: get_vect_brace(w_vect)
)
proj_v_brace = always_redraw(
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 = always_redraw(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(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 = always_redraw(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(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(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(RIGHT, buff=MED_LARGE_BUFF)
pis.to_edge(DOWN, buff=SMALL_BUFF)
self.add(big_rect, title, pis)
self.play(
LaggedStartMap(
ShowCreation, screen_rects.copy().set_fill(opacity=0),
lag_ratio=0.8
),
LaggedStartMap(
FadeIn, screen_rects,
lag_ratio=0.8
),
LaggedStartMap(
ApplyMethod, pis,
lambda pi: (pi.change, "pondering", screen_rects[0])
),
)
self.play(Blink(random.choice(pis)))
self.play(LaggedStartMap(
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 = Arrow(
self.block_word.get_top(),
self.light_dot.get_bottom(),
tip_length=0.75,
rectangular_stem_width=0.2,
color=RED,
buff=0.5,
)
arrow.add_to_back(arrow.copy().set_stroke(BLACK, 20))
self.add(arrow)
return
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,
},
}
)
group = Group(*scene1.mobjects)
group.scale(0.75, about_point=ORIGIN)
group.shift(1.5 * DOWN + 3 * LEFT)
scene1.remove(scene1.question)
self.add(*scene1.mobjects)
black_rect = FullScreenFadeRectangle(fill_opacity=1)
black_rect.shift(3.5 * UP)
self.add(black_rect)
word = TextMobject("Blocks")
word.set_color(YELLOW)
word.scale(3)
word.to_corner(DR, buff=LARGE_BUFF)
word.shift(0.5 * LEFT)
self.block_word = word
self.add(word)
def add_scene2(self):
scene2 = ReflectWorldThroughMirrorNew(
skip_animations=True,
file_writer_config={
"write_to_movie": False,
},
end_at_animation_number=18,
# center=1.5 * DOWN,
center=ORIGIN,
)
worlds = VGroup(scene2.world, *scene2.reflected_worlds)
mirrors = VGroup(*[rw[1] for rw in worlds])
mirrors.set_stroke(width=5)
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 = self.light_dot = Dot(color=YELLOW, radius=0.1)
dot.move_to(flashes[0].get_left())
flashes.add(dot)
self.add(triangles, mirrors)
# self.add(randys)
self.add(trajectories[0].set_stroke(width=2))
self.add(flashes)
word = TextMobject("Light beam")
word.scale(3.5)
word.set_color(YELLOW)
# word.set_stroke(BLACK, 25, background=True)
word.add_to_back(word.copy().set_stroke(
BLACK, 25,
))
word.next_to(dot, UR)
word.shift(-word.get_center()[0] * RIGHT)
word.shift(SMALL_BUFF * RIGHT)
self.light_word = word
self.add(word)