mirror of
https://github.com/3b1b/manim.git
synced 2025-07-29 21:12:35 +08:00
Reorganized files for 3b1b videos into a 3b1b_projects folder
This commit is contained in:
877
3b1b_projects/old/clacks/solution2/simple_scenes.py
Normal file
877
3b1b_projects/old/clacks/solution2/simple_scenes.py
Normal file
@ -0,0 +1,877 @@
|
||||
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)
|
Reference in New Issue
Block a user