mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 17:29:06 +08:00
End of brachistochrone problem
This commit is contained in:
@ -203,8 +203,12 @@ class PathSlidingScene(Scene):
|
||||
theta = angle_of_vector(point_b - point_a)
|
||||
mobject.rotate(theta)
|
||||
mobject.shift(points[index])
|
||||
self.midslide_action(point_a, theta)
|
||||
return mobject
|
||||
|
||||
def midslide_action(self, point, angle):
|
||||
pass
|
||||
|
||||
def write_time(self, time):
|
||||
if hasattr(self, "time_mob"):
|
||||
self.remove(self.time_mob)
|
||||
@ -594,10 +598,112 @@ class WhatGovernsSpeed(PathSlidingScene):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ThetaTInsteadOfXY(Scene):
|
||||
def construct(self):
|
||||
cycloid = Cycloid()
|
||||
index = cycloid.get_num_points()/3
|
||||
point = cycloid.points[index]
|
||||
vect = cycloid.points[index+1]-point
|
||||
vect /= np.linalg.norm(vect)
|
||||
vect *= 3
|
||||
vect_mob = Vector(point, vect)
|
||||
dot = Dot(point)
|
||||
xy = TexMobject("\\big( x(t), y(t) \\big)")
|
||||
xy.next_to(dot, UP+RIGHT, buff = 0.1)
|
||||
vert_line = Line(2*DOWN, 2*UP)
|
||||
vert_line.shift(point)
|
||||
angle = vect_mob.get_angle() + np.pi/2
|
||||
arc = Arc(angle, radius = 1, start_angle = -np.pi/2)
|
||||
arc.shift(point)
|
||||
theta = TexMobject("\\theta(t)")
|
||||
theta.next_to(arc, DOWN, buff = 0.1, aligned_edge = LEFT)
|
||||
theta.shift(0.2*RIGHT)
|
||||
|
||||
self.play(ShowCreation(cycloid))
|
||||
self.play(ShowCreation(dot))
|
||||
self.play(ShimmerIn(xy))
|
||||
self.dither()
|
||||
self.play(
|
||||
FadeOut(xy),
|
||||
ShowCreation(vect_mob)
|
||||
)
|
||||
self.play(
|
||||
ShowCreation(arc),
|
||||
ShowCreation(vert_line),
|
||||
ShimmerIn(theta)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class DefineCurveWithKnob(PathSlidingScene):
|
||||
def construct(self):
|
||||
self.knob = Circle(color = BLUE_D)
|
||||
self.knob.add_line(UP, DOWN)
|
||||
self.knob.to_corner(UP+RIGHT)
|
||||
self.knob.shift(0.5*DOWN)
|
||||
self.last_angle = np.pi/2
|
||||
arrow = Vector(ORIGIN, RIGHT)
|
||||
arrow.next_to(self.knob, LEFT)
|
||||
words = TextMobject("Turn this knob over time to define the curve")
|
||||
words.next_to(arrow, LEFT)
|
||||
self.path = self.get_path()
|
||||
self.path.shift(1.5*DOWN)
|
||||
self.path.show()
|
||||
self.path.highlight(BLACK)
|
||||
|
||||
randy = Randolph()
|
||||
randy.scale(RANDY_SCALE_VAL)
|
||||
randy.shift(-randy.get_bottom())
|
||||
|
||||
self.play(ShimmerIn(words))
|
||||
self.play(ShowCreation(arrow))
|
||||
self.play(ShowCreation(self.knob))
|
||||
self.dither()
|
||||
self.add(self.path)
|
||||
|
||||
self.slide(randy, self.path)
|
||||
self.dither()
|
||||
|
||||
|
||||
def get_path(self):
|
||||
return Cycloid(end_theta = 2*np.pi)
|
||||
|
||||
def midslide_action(self, point, angle):
|
||||
d_angle = angle-self.last_angle
|
||||
self.knob.rotate_in_place(d_angle)
|
||||
self.last_angle = angle
|
||||
self.path.highlight(BLUE_D, lambda p : p[0] < point[0])
|
||||
|
||||
|
||||
|
||||
class WonkyDefineCurveWithKnob(DefineCurveWithKnob):
|
||||
def get_path(self):
|
||||
return ParametricFunction(
|
||||
lambda t : t*RIGHT + (-0.2*t-np.sin(2*np.pi*t/6))*UP,
|
||||
start = -7,
|
||||
end = 10
|
||||
)
|
||||
|
||||
|
||||
class SlowDefineCurveWithKnob(DefineCurveWithKnob):
|
||||
def get_path(self):
|
||||
return ParametricFunction(
|
||||
lambda t : t*RIGHT + (np.exp(-(t+2)**2)-0.2*np.exp(t-2)),
|
||||
start = -4,
|
||||
end = 4
|
||||
)
|
||||
|
||||
|
||||
class BumpyDefineCurveWithKnob(DefineCurveWithKnob):
|
||||
def get_path(self):
|
||||
|
||||
result = FunctionGraph(
|
||||
lambda x : 0.05*(x**2)+0.1*np.sin(2*x)
|
||||
)
|
||||
result.rotate(-np.pi/20)
|
||||
result.scale(0.7)
|
||||
result.shift(DOWN)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
|
@ -502,34 +502,61 @@ class LeviSolution(CycloidScene):
|
||||
class EquationsForCycloid(CycloidScene):
|
||||
def construct(self):
|
||||
CycloidScene.construct(self)
|
||||
equations = TexMobject("""
|
||||
x(t) &= Rt - R\\sin(t) \\\\
|
||||
y(t) &= -R + R\\cos(t)
|
||||
""")
|
||||
equations.shift(2*UP)
|
||||
equations = TexMobject([
|
||||
"x(t) = Rt - R\\sin(t)",
|
||||
"y(t) = -R + R\\cos(t)"
|
||||
])
|
||||
top, bottom = equations.split()
|
||||
bottom.next_to(top, DOWN)
|
||||
equations.center()
|
||||
equations.to_edge(UP, buff = 1.3)
|
||||
|
||||
self.play(ShimmerIn(equations))
|
||||
self.grow_parts()
|
||||
self.draw_cycloid(rate_func = None, run_time = 5)
|
||||
self.dither()
|
||||
|
||||
|
||||
class SlidingObject(CycloidScene, PathSlidingScene):
|
||||
CONFIG = {
|
||||
"show_time" : False,
|
||||
"dither_and_add" : False
|
||||
}
|
||||
def construct(self):
|
||||
|
||||
args_list = [(True,), (False,)]
|
||||
|
||||
@staticmethod
|
||||
def args_to_string(with_words):
|
||||
return "WithWords" if with_words else "WithoutWords"
|
||||
|
||||
@staticmethod
|
||||
def string_to_args(string):
|
||||
return string == "WithWords"
|
||||
|
||||
def construct(self, with_words):
|
||||
CycloidScene.construct(self)
|
||||
|
||||
randy = Randolph()
|
||||
randy.scale(RANDY_SCALE_VAL)
|
||||
randy.shift(-randy.get_bottom())
|
||||
central_randy = randy.copy()
|
||||
start_randy = self.adjust_mobject_to_index(
|
||||
randy.copy(), 1, self.cycloid.points
|
||||
)
|
||||
|
||||
self.play(ShowCreation(self.cycloid))
|
||||
if with_words:
|
||||
words1 = TextMobject("Trajectory due to gravity")
|
||||
arrow = TexMobject("\\leftrightarrow")
|
||||
words2 = TextMobject("Trajectory due \\emph{constantly} rotating wheel")
|
||||
words1.next_to(arrow, LEFT)
|
||||
words2.next_to(arrow, RIGHT)
|
||||
words = Mobject(words1, arrow, words2)
|
||||
words.scale_to_fit_width(2*SPACE_WIDTH-1)
|
||||
words.to_edge(UP, buff = 0.2)
|
||||
words.to_edge(LEFT)
|
||||
|
||||
self.play(ShowCreation(self.cycloid.copy()))
|
||||
self.slide(randy, self.cycloid)
|
||||
self.add(self.slider)
|
||||
self.dither()
|
||||
self.grow_parts()
|
||||
self.draw_cycloid()
|
||||
@ -538,12 +565,26 @@ class SlidingObject(CycloidScene, PathSlidingScene):
|
||||
self.dither()
|
||||
self.roll_back()
|
||||
self.dither()
|
||||
radial_line = self.circle.sub_mobjects[0]
|
||||
self.circle.add(self.slider)
|
||||
self.circle.get_center = lambda : radial_line.get_start_and_end()[0]
|
||||
self.draw_cycloid()
|
||||
if with_words:
|
||||
self.play(*map(ShimmerIn, [words1, arrow, words2]))
|
||||
self.dither()
|
||||
self.remove(self.circle)
|
||||
start_time = len(self.frames)*self.frame_duration
|
||||
self.remove(self.slider)
|
||||
self.slide(central_randy, self.cycloid)
|
||||
end_time = len(self.frames)*self.frame_duration
|
||||
self.play_over_time_range(
|
||||
start_time,
|
||||
end_time,
|
||||
RollAlongVector(
|
||||
self.circle,
|
||||
self.cycloid.points[-1]-self.cycloid.points[0],
|
||||
run_time = end_time-start_time,
|
||||
rate_func = None
|
||||
)
|
||||
)
|
||||
self.add(self.circle, self.slider)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -317,28 +317,28 @@ class JohannThinksOfFermat(Scene):
|
||||
|
||||
class MathematiciansOfEurope(Scene):
|
||||
def construct(self):
|
||||
europe = ImageMobject("1700_Europe", invert = False)
|
||||
europe = ImageMobject("Europe", use_cache = False)
|
||||
self.add(europe)
|
||||
self.freeze_background()
|
||||
|
||||
mathematicians = [
|
||||
("Newton", [-1.6, 0.6, 0]),
|
||||
("Jacob_Bernoulli",[-1, -0.75, 0]),
|
||||
("Ehrenfried_von_Tschirnhaus",[-0.5, 0.2, 0]),
|
||||
("Gottfried_Wilhelm_von_Leibniz",[-0.1, -0.75, 0]),
|
||||
("Guillaume_de_L'Hopital", [-1.5, -0.5, 0]),
|
||||
("Newton", [-1.75, -0.75, 0]),
|
||||
("Jacob_Bernoulli",[-0.75, -1.75, 0]),
|
||||
("Ehrenfried_von_Tschirnhaus",[0.5, -0.5, 0]),
|
||||
("Gottfried_Wilhelm_von_Leibniz",[0.2, -1.75, 0]),
|
||||
("Guillaume_de_L'Hopital", [-1.75, -1.25, 0]),
|
||||
]
|
||||
|
||||
for name, point in mathematicians:
|
||||
man = ImageMobject(name, invert = False)
|
||||
if name == "Newton":
|
||||
name = "Isaac_Newton"
|
||||
name_mob = TextMobject(name.replace("_", " "))
|
||||
name_mob.to_corner(UP+LEFT, buff=0.75)
|
||||
self.add(name_mob)
|
||||
man.scale_to_fit_height(4)
|
||||
mobject = Point(man.get_corner(UP+LEFT))
|
||||
self.play(
|
||||
DelayByOrder(Transform(mobject, man)),
|
||||
ShimmerIn(name_mob)
|
||||
)
|
||||
self.play(Transform(mobject, man))
|
||||
man.scale(0.2)
|
||||
man.shift(point)
|
||||
self.play(Transform(mobject, man))
|
||||
|
@ -878,7 +878,59 @@ class WhichPathWouldLightTake(PhotonScene, TryManyPaths):
|
||||
|
||||
|
||||
|
||||
|
||||
class StateSnellsLaw(PhotonScene):
|
||||
def construct(self):
|
||||
point_a = 3*LEFT+3*UP
|
||||
point_b = 1.5*RIGHT+3*DOWN
|
||||
midpoint = ORIGIN
|
||||
|
||||
lines, arcs, thetas = [], [], []
|
||||
counter = it.count(1)
|
||||
for point in point_a, point_b:
|
||||
line = Line(point, midpoint, color = RED_D)
|
||||
angle = np.pi/2-np.abs(np.arctan(line.get_slope()))
|
||||
arc = Arc(angle, radius = 0.5).rotate(np.pi/2)
|
||||
if point is point_b:
|
||||
arc.rotate(np.pi)
|
||||
line.reverse_points()
|
||||
theta = TexMobject("\\theta_%d"%counter.next())
|
||||
theta.scale(0.5)
|
||||
theta.shift(2*arc.get_center())
|
||||
arc.shift(midpoint)
|
||||
theta.shift(midpoint)
|
||||
|
||||
lines.append(line)
|
||||
arcs.append(arc)
|
||||
thetas.append(theta)
|
||||
vert_line = Line(2*UP, 2*DOWN)
|
||||
vert_line.shift(midpoint)
|
||||
path = Mobject(*lines).ingest_sub_mobjects()
|
||||
glass = Region(lambda x, y : y < 0, color = BLUE_E)
|
||||
self.add(glass)
|
||||
equation = TexMobject([
|
||||
"\\dfrac{\\sin(\\theta_1)}{v_{\\text{air}}}",
|
||||
"=",
|
||||
"\\dfrac{\\sin(\\theta_2)}{v_{\\text{water}}}",
|
||||
])
|
||||
equation.to_corner(UP+RIGHT)
|
||||
exp1, equals, exp2 = equation.split()
|
||||
snells_law = TextMobject("Snell's Law:")
|
||||
snells_law.highlight(YELLOW)
|
||||
snells_law.to_edge(UP)
|
||||
|
||||
self.play(ShimmerIn(snells_law))
|
||||
self.dither()
|
||||
self.play(ShowCreation(path))
|
||||
self.play(self.photon_run_along_path(path))
|
||||
self.dither()
|
||||
self.play(ShowCreation(vert_line))
|
||||
self.play(*map(ShowCreation, arcs))
|
||||
self.play(*map(GrowFromCenter, thetas))
|
||||
self.dither()
|
||||
self.play(ShimmerIn(exp1))
|
||||
self.dither()
|
||||
self.play(*map(ShimmerIn, [equals, exp2]))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
@ -17,8 +17,10 @@ from topics.characters import *
|
||||
from topics.functions import ParametricFunction, FunctionGraph
|
||||
from topics.number_line import *
|
||||
from mobject.region import Region, region_from_polygon_vertices
|
||||
from topics.three_dimensions import Stars
|
||||
from scene import Scene
|
||||
|
||||
from brachistochrone.curves import Cycloid
|
||||
|
||||
class PhysicalIntuition(Scene):
|
||||
def construct(self):
|
||||
@ -232,11 +234,266 @@ class StayedUpAllNight(Scene):
|
||||
self.dither()
|
||||
|
||||
|
||||
class ThetaTSigmoidGraph(Scene):
|
||||
class ThetaTGraph(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
||||
|
||||
t_axis = NumberLine()
|
||||
theta_axis = NumberLine().rotate(np.pi/2)
|
||||
theta_mob = TexMobject("\\theta(t)")
|
||||
t_mob = TexMobject("t")
|
||||
theta_mob.next_to(theta_axis, RIGHT)
|
||||
theta_mob.to_edge(UP)
|
||||
t_mob.next_to(t_axis, UP)
|
||||
t_mob.to_edge(RIGHT)
|
||||
graph = ParametricFunction(
|
||||
lambda t : 4*t*RIGHT + 2*smooth(t)*UP
|
||||
)
|
||||
line = Line(graph.points[0], graph.points[-1], color = WHITE)
|
||||
q_mark = TextMobject("?")
|
||||
q_mark.next_to(Point(graph.get_center()), LEFT)
|
||||
stars = Stars(color = BLACK)
|
||||
stars.scale(0.1).shift(q_mark.get_center())
|
||||
|
||||
|
||||
squiggle = ParametricFunction(
|
||||
lambda t : t*RIGHT + 0.2*t*(5-t)*(np.sin(t)**2)*UP,
|
||||
start = 0,
|
||||
end = 5
|
||||
)
|
||||
|
||||
self.play(
|
||||
ShowCreation(t_axis),
|
||||
ShowCreation(theta_axis),
|
||||
ShimmerIn(theta_mob),
|
||||
ShimmerIn(t_mob)
|
||||
)
|
||||
self.play(
|
||||
ShimmerIn(q_mark),
|
||||
ShowCreation(graph)
|
||||
)
|
||||
self.dither()
|
||||
self.play(
|
||||
Transform(q_mark, stars),
|
||||
Transform(graph, line)
|
||||
)
|
||||
self.dither()
|
||||
self.play(Transform(graph, squiggle))
|
||||
self.dither()
|
||||
|
||||
|
||||
class SolutionsToTheBrachistochrone(Scene):
|
||||
def construct(self):
|
||||
r_range = np.arange(0.5, 2, 0.25)
|
||||
cycloids = Mobject(*[
|
||||
Cycloid(radius = r, end_theta=2*np.pi)
|
||||
for r in r_range
|
||||
])
|
||||
lower_left = 2*DOWN+6*LEFT
|
||||
lines = Mobject(*[
|
||||
Line(
|
||||
lower_left,
|
||||
lower_left+5*r*np.cos(np.arctan(r))*RIGHT+2*r*np.sin(np.arctan(r))*UP
|
||||
)
|
||||
for r in r_range
|
||||
])
|
||||
nl = NumberLine(numbers_with_elongated_ticks = [])
|
||||
x_axis = nl.copy().shift(3*UP)
|
||||
y_axis = nl.copy().rotate(np.pi/2).shift(6*LEFT)
|
||||
t_axis = nl.copy().shift(2*DOWN)
|
||||
x_label = TexMobject("x")
|
||||
x_label.next_to(x_axis, DOWN)
|
||||
x_label.to_edge(RIGHT)
|
||||
y_label = TexMobject("y")
|
||||
y_label.next_to(y_axis, RIGHT)
|
||||
y_label.shift(2*DOWN)
|
||||
t_label = TexMobject("t")
|
||||
t_label.next_to(t_axis, UP)
|
||||
t_label.to_edge(RIGHT)
|
||||
theta_label = TexMobject("\\theta")
|
||||
theta_label.next_to(y_axis, RIGHT)
|
||||
theta_label.to_edge(UP)
|
||||
words = TextMobject("Boundary conditions?")
|
||||
words.next_to(lines, RIGHT)
|
||||
words.shift(2*UP)
|
||||
|
||||
self.play(ShowCreation(x_axis), ShimmerIn(x_label))
|
||||
self.play(ShowCreation(y_axis), ShimmerIn(y_label))
|
||||
self.play(ShowCreation(cycloids))
|
||||
self.dither()
|
||||
self.play(
|
||||
Transform(cycloids, lines),
|
||||
Transform(x_axis, t_axis),
|
||||
Transform(x_label, t_label),
|
||||
Transform(y_label, theta_label),
|
||||
run_time = 2
|
||||
)
|
||||
self.dither()
|
||||
self.play(ShimmerIn(words))
|
||||
self.dither()
|
||||
|
||||
|
||||
class VideoLayout(Scene):
|
||||
def construct(self):
|
||||
left, right = 5*LEFT, 5*RIGHT
|
||||
top_words = TextMobject("The next 15 minutes of your life:")
|
||||
top_words.to_edge(UP)
|
||||
line = Line(left, right, color = BLUE_D)
|
||||
for a in np.arange(0, 4./3, 1./3):
|
||||
vect = interpolate(left, right, a)
|
||||
line.add_line(vect+0.2*DOWN, vect+0.2*UP)
|
||||
left_brace = Brace(
|
||||
Mobject(
|
||||
Point(left),
|
||||
Point(interpolate(left, right, 2./3))
|
||||
),
|
||||
DOWN
|
||||
)
|
||||
right_brace = Brace(
|
||||
Mobject(
|
||||
Point(interpolate(left, right, 2./3)),
|
||||
Point(right)
|
||||
),
|
||||
UP
|
||||
)
|
||||
left_brace.words = map(TextMobject, [
|
||||
"Problem statement",
|
||||
"History",
|
||||
"Johann Bernoulli's cleverness"
|
||||
])
|
||||
curr = left_brace
|
||||
right_brace.words = map(TextMobject, [
|
||||
"Challenge",
|
||||
"Mark Levi's cleverness",
|
||||
])
|
||||
for brace in left_brace, right_brace:
|
||||
curr = brace
|
||||
direction = DOWN if brace is left_brace else UP
|
||||
for word in brace.words:
|
||||
word.next_to(curr, direction)
|
||||
curr = word
|
||||
right_brace.words.reverse()
|
||||
|
||||
self.play(ShimmerIn(top_words))
|
||||
self.play(ShowCreation(line))
|
||||
for brace in left_brace, right_brace:
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.dither()
|
||||
for word in brace.words:
|
||||
self.play(ShimmerIn(word))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
class ShortestPathProblem(Scene):
|
||||
def construct(self):
|
||||
point_a, point_b = 3*LEFT, 3*RIGHT
|
||||
dots = []
|
||||
for point, char in [(point_a, "A"), (point_b, "B")]:
|
||||
dot = Dot(point)
|
||||
letter = TexMobject(char)
|
||||
letter.next_to(dot, UP+LEFT)
|
||||
dot.add(letter)
|
||||
dots.append(dot)
|
||||
|
||||
path = ParametricFunction(
|
||||
lambda t : (t/2 + np.cos(t))*RIGHT + np.sin(t)*UP,
|
||||
start = -2*np.pi,
|
||||
end = 2*np.pi
|
||||
)
|
||||
path.scale(6/(2*np.pi))
|
||||
path.shift(point_a - path.points[0])
|
||||
path.highlight(RED)
|
||||
line = Line(point_a, point_b)
|
||||
words = TextMobject("Shortest path from $A$ to $B$")
|
||||
words.to_edge(UP)
|
||||
|
||||
self.play(
|
||||
ShimmerIn(words),
|
||||
*map(GrowFromCenter, dots)
|
||||
)
|
||||
self.play(ShowCreation(path))
|
||||
self.play(Transform(
|
||||
path, line,
|
||||
path_func = path_along_arc(np.pi)
|
||||
))
|
||||
self.dither()
|
||||
|
||||
|
||||
class MathBetterThanTalking(Scene):
|
||||
def construct(self):
|
||||
mathy = Mathematician()
|
||||
mathy.to_corner(DOWN+LEFT)
|
||||
bubble = ThoughtBubble()
|
||||
bubble.pin_to(mathy)
|
||||
bubble.write("Math $>$ Talking about math")
|
||||
|
||||
self.add(mathy)
|
||||
self.play(ShowCreation(bubble))
|
||||
self.play(ShimmerIn(bubble.content))
|
||||
self.dither()
|
||||
self.play(ApplyMethod(
|
||||
mathy.blink,
|
||||
rate_func = squish_rate_func(there_and_back, 0.4, 0.6)
|
||||
))
|
||||
|
||||
|
||||
class DetailsOfProofBox(Scene):
|
||||
def construct(self):
|
||||
rect = Rectangle(height = 4, width = 6, color = WHITE)
|
||||
words = TextMobject("Details of proof")
|
||||
words.to_edge(UP)
|
||||
|
||||
self.play(
|
||||
ShowCreation(rect),
|
||||
ShimmerIn(words)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class TalkedAboutSnellsLaw(Scene):
|
||||
def construct(self):
|
||||
randy = Randolph()
|
||||
randy.to_corner(DOWN+LEFT)
|
||||
morty = Mortimer()
|
||||
morty.to_edge(DOWN+RIGHT)
|
||||
randy.bubble = SpeechBubble().pin_to(randy)
|
||||
morty.bubble = SpeechBubble().pin_to(morty)
|
||||
|
||||
phrases = [
|
||||
"Let's talk about Snell's law",
|
||||
"I love Snell's law",
|
||||
"It's like running from \\\\ a beach into the ocean",
|
||||
"It's like two constant \\\\ tension springs",
|
||||
]
|
||||
|
||||
self.add(randy, morty)
|
||||
talkers = it.cycle([randy, morty])
|
||||
for talker, phrase in zip(talkers, phrases):
|
||||
talker.bubble.write(phrase)
|
||||
self.play(
|
||||
FadeIn(talker.bubble),
|
||||
ShimmerIn(talker.bubble.content)
|
||||
)
|
||||
self.play(ApplyMethod(
|
||||
talker.blink,
|
||||
rate_func = squish_rate_func(there_and_back)
|
||||
))
|
||||
self.dither()
|
||||
self.remove(talker.bubble, talker.bubble.content)
|
||||
|
||||
|
||||
class YetAnotherMarkLevi(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject("Yet another bit of Mark Levi cleverness")
|
||||
words.to_edge(UP)
|
||||
levi = ImageMobject("Mark_Levi", invert = False)
|
||||
levi.scale_to_fit_width(6)
|
||||
levi.show()
|
||||
|
||||
self.add(levi)
|
||||
self.play(ShimmerIn(words))
|
||||
self.dither(2)
|
||||
|
||||
|
||||
|
||||
|
@ -387,7 +387,7 @@ class ContinuouslyObeyingSnellsLaw(MultilayeredScene):
|
||||
|
||||
def snells_law_at_every_point(self, cycloid, chopped_cycloid):
|
||||
square = Square(side_length = 0.2, color = WHITE)
|
||||
words = TextMobject(["Snell's law ", " at every point"])
|
||||
words = TextMobject(["Snell's law ", "everywhere"])
|
||||
snells, rest = words.split()
|
||||
colon = TextMobject(":")
|
||||
words.next_to(square)
|
||||
|
@ -469,6 +469,100 @@ class BalanceCompetingFactors(Scene):
|
||||
|
||||
|
||||
|
||||
class Challenge(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("""
|
||||
Can you find a new solution to the
|
||||
Brachistochrone problem by finding
|
||||
an intuitive reason that time-minimizing
|
||||
curves look like straight lines in
|
||||
$t$-$\\theta$ space?
|
||||
"""))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class Section1(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("Section 1: Johann Bernoulli's insight"))
|
||||
self.dither()
|
||||
|
||||
class Section2(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject(
|
||||
"Section 2: Mark Levi's insight, and a challenge",
|
||||
size = "\\large"
|
||||
))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class NarratorInterjection(Scene):
|
||||
def construct(self):
|
||||
words1 = TexMobject("<\\text{Narrator interjection}>")
|
||||
words2 = TexMobject("<\\!/\\text{Narrator interjection}>")
|
||||
self.add(words1)
|
||||
self.dither()
|
||||
self.clear()
|
||||
self.add(words2)
|
||||
self.dither()
|
||||
|
||||
|
||||
class ThisCouldBeTheEnd(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject([
|
||||
"This could be the end\\dots",
|
||||
"but\\dots"
|
||||
])
|
||||
for part in words.split():
|
||||
self.play(ShimmerIn(part))
|
||||
self.dither()
|
||||
|
||||
|
||||
class MyOwnChallenge(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("My own challenge:"))
|
||||
self.dither()
|
||||
|
||||
|
||||
class WarmupChallenge(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("\\large Warm-up challenge: Confirm this for yourself"))
|
||||
self.dither()
|
||||
|
||||
class FindAnotherSolution(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("Find another brachistochrone solution\\dots"))
|
||||
self.dither()
|
||||
|
||||
|
||||
class ProofOfSnellsLaw(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("Proof of Snell's law:"))
|
||||
self.dither()
|
||||
|
||||
|
||||
class CondensedVersion(Scene):
|
||||
def construct(self):
|
||||
snells = TextMobject("Snell's")
|
||||
snells.shift(-snells.get_left())
|
||||
snells.to_edge(UP)
|
||||
for vect in [RIGHT, RIGHT, LEFT, DOWN, DOWN, DOWN]:
|
||||
snells.add(snells.copy().next_to(snells, vect))
|
||||
snells.ingest_sub_mobjects()
|
||||
snells.show()
|
||||
condensed = TextMobject("condensed")
|
||||
|
||||
self.add(snells)
|
||||
self.dither()
|
||||
self.play(DelayByOrder(
|
||||
Transform(snells, condensed, run_time = 2)
|
||||
))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -188,7 +188,6 @@ class Scene(object):
|
||||
self.frames[index] = self.get_frame()
|
||||
for animation in animations:
|
||||
animation.clean_up()
|
||||
self.repaint_mojects()
|
||||
return self
|
||||
|
||||
def dither(self, duration = DEFAULT_DITHER_TIME):
|
||||
|
@ -130,8 +130,6 @@ class Mortimer(PiCreature):
|
||||
}
|
||||
def __init__(self, **kwargs):
|
||||
PiCreature.__init__(self, **kwargs)
|
||||
# self.highlight(DARK_BROWN)
|
||||
self.give_straight_face()
|
||||
self.rotate(np.pi, UP)
|
||||
|
||||
|
||||
@ -139,10 +137,6 @@ class Mathematician(PiCreature):
|
||||
CONFIG = {
|
||||
"color" : GREY,
|
||||
}
|
||||
def __init__(self, **kwargs):
|
||||
PiCreature.__init__(self, **kwargs)
|
||||
self.give_straight_face()
|
||||
|
||||
|
||||
class Bubble(Mobject):
|
||||
CONFIG = {
|
||||
|
Reference in New Issue
Block a user