mirror of
https://github.com/3b1b/videos.git
synced 2025-09-18 21:38:53 +00:00
Final inscribed rectangle animations
This commit is contained in:
parent
8f54648b19
commit
00edbe600b
3 changed files with 254 additions and 18 deletions
|
@ -96,7 +96,7 @@ class StateThePuzzle(LoopScene):
|
|||
loop = get_example_loop(4)
|
||||
loop.set_height(7)
|
||||
loop.move_to(2 * RIGHT)
|
||||
curve_words = Text("Closed\nContinus\nCurve", alignment="LEFT", font_size=72)
|
||||
curve_words = Text("Closed\nContinuous\nCurve", alignment="LEFT", font_size=72)
|
||||
curve_words.to_edge(LEFT)
|
||||
|
||||
self.play(
|
||||
|
@ -162,14 +162,17 @@ class StateThePuzzle(LoopScene):
|
|||
self.wait()
|
||||
|
||||
# Ambiently animate to various different loops
|
||||
def true_find_square(loop_func, trg_angle=90 * DEG, cost_tol=1e-2, max_tries=10):
|
||||
def true_find_square(loop_func, trg_angle=90 * DEG, cost_tol=1e-2, max_tries=8):
|
||||
ic = np.arange(0, 1, 0.25)
|
||||
min_params = ic
|
||||
min_cost = np.inf
|
||||
for x in range(max_tries):
|
||||
params, cost = find_rectangle(loop_func, target_angle=trg_angle, n_refinements=3, return_cost=True)
|
||||
if cost < cost_tol:
|
||||
break
|
||||
if cost < min_cost:
|
||||
min_params = params
|
||||
min_cost = cost
|
||||
ic = np.random.random(4)
|
||||
return params
|
||||
return min_params
|
||||
|
||||
new_loops = [
|
||||
get_example_loop(1),
|
||||
|
@ -188,15 +191,19 @@ class StateThePuzzle(LoopScene):
|
|||
dots.resume_updating()
|
||||
self.add(dots, polygon)
|
||||
for new_loop in new_loops:
|
||||
self.remove(dots, polygon)
|
||||
self.play(
|
||||
Transform(loop, new_loop),
|
||||
UpdateFromFunc(
|
||||
quad_tracker,
|
||||
lambda m: m.set_value(true_find_square(loop_func))
|
||||
),
|
||||
run_time=5
|
||||
# UpdateFromFunc(
|
||||
# quad_tracker,
|
||||
# lambda m: m.set_value(true_find_square(loop_func))
|
||||
# ),
|
||||
run_time=1
|
||||
)
|
||||
self.wait()
|
||||
self.add(dots, polygon)
|
||||
for _ in range(5):
|
||||
quad_tracker.set_value(find_rectangle(loop_func, np.random.random(4), target_angle=90 * DEG))
|
||||
self.wait(0.5)
|
||||
|
||||
# Change question to rectangle
|
||||
square_word = question["square"]
|
||||
|
@ -427,17 +434,18 @@ class ShowTheSurface(LoopScene):
|
|||
|
||||
# Pair of points
|
||||
uv_tracker = ValueTracker([0, 0.5])
|
||||
dots = self.get_movable_pair(uv_tracker, loop_func, radius=0.05)
|
||||
dots = self.get_movable_pair(uv_tracker, loop_func, radius=0.075)
|
||||
connecting_line = self.get_connecting_line(dots)
|
||||
midpoint_dot = self.get_midpoint_dot(dots)
|
||||
|
||||
self.add(uv_tracker)
|
||||
self.add(dots)
|
||||
self.add(connecting_line)
|
||||
|
||||
self.play(
|
||||
UpdateFromFunc(uv_tracker, lambda m: m.set_value(np.random.random(2))),
|
||||
)
|
||||
self.add(dots)
|
||||
self.add(dots, connecting_line)
|
||||
self.play(uv_tracker.animate.set_value([0.8, 0.5]), run_time=3)
|
||||
|
||||
# Add coordinates
|
||||
|
@ -2033,6 +2041,63 @@ class MapTheStripOntoTheSurface(ShowTheSurface):
|
|||
)
|
||||
|
||||
|
||||
class AmbientRectangleSearch(ShowTheSurface):
|
||||
def construct(self):
|
||||
# Setup loop
|
||||
frame = self.frame
|
||||
axes, plane = self.get_axes_and_plane()
|
||||
self.add(plane)
|
||||
|
||||
loop = get_example_loop(2)
|
||||
loop.insert_n_curves(50)
|
||||
loop.set_height(5)
|
||||
loop.set_stroke(WHITE, 3)
|
||||
loop.set_fill(opacity=0)
|
||||
loop_func = get_quick_loop_func(loop)
|
||||
self.add(loop)
|
||||
|
||||
# Dots
|
||||
abcd_tracker = ValueTracker(np.random.random(4))
|
||||
dots = self.get_movable_quad(abcd_tracker, loop_func, radius=0.1)
|
||||
polygon = self.get_dot_polygon(dots)
|
||||
polygon.set_stroke(YELLOW, 2)
|
||||
|
||||
self.add(dots, polygon)
|
||||
|
||||
# Various rectangles
|
||||
for _ in range(20):
|
||||
rect_params = find_rectangle(
|
||||
loop_func,
|
||||
initial_condition=np.random.random(4),
|
||||
target_angle=np.random.uniform(0, 90 * DEG),
|
||||
)
|
||||
self.play(abcd_tracker.animate.set_value(rect_params), run_time=2)
|
||||
self.wait()
|
||||
|
||||
|
||||
class GenericLoopPair(ShowTheSurface):
|
||||
def construct(self):
|
||||
loop = Circle(radius=2.5)
|
||||
loop.set_stroke(WHITE, 3)
|
||||
loop.set_fill(opacity=0)
|
||||
loop_func = get_quick_loop_func(loop)
|
||||
self.add(loop)
|
||||
|
||||
uv_tracker = ValueTracker([0, 0.5])
|
||||
# self.set_uv_tracker_in_motion(uv_tracker, velocity=(0.1 * PI / 2, -0.1))
|
||||
dots = self.get_movable_pair(uv_tracker, loop_func, radius=0.075, colors=[YELLOW, YELLOW])
|
||||
connecting_line = self.get_connecting_line(dots)
|
||||
connecting_line.set_stroke(YELLOW)
|
||||
pair_group = Group(dots, connecting_line)
|
||||
|
||||
self.add(uv_tracker, pair_group)
|
||||
|
||||
# Wait
|
||||
for _ in range(20):
|
||||
self.play(uv_tracker.animate.set_value(np.random.random(2)), run_time=2)
|
||||
self.wait(0.5)
|
||||
|
||||
|
||||
class SudaneseBand(InteractiveScene):
|
||||
def construct(self):
|
||||
# Tranform mobius to Sudanese
|
||||
|
@ -2044,7 +2109,10 @@ class SudaneseBand(InteractiveScene):
|
|||
sudanese_band.set_height(6)
|
||||
|
||||
frame.reorient(28, 75, 0, ORIGIN, 8)
|
||||
self.add(strip)
|
||||
# self.add(strip)
|
||||
self.add(sudanese_band)
|
||||
frame.add_ambient_rotation(6 * DEG)
|
||||
self.wait(60)
|
||||
self.play(frame.animate.increment_theta(180 * DEG), run_time=12)
|
||||
self.play(
|
||||
frame.animate.reorient(99, 102, 0),
|
||||
|
@ -2448,7 +2516,6 @@ class PuzzleOverMobiusDiagram(ConstructKleinBottle):
|
|||
)
|
||||
|
||||
|
||||
|
||||
class ShowAngleInformation(ShowTheSurface):
|
||||
def construct(self):
|
||||
# Setup (fairly heavily copied from above)
|
||||
|
|
|
@ -167,6 +167,28 @@ class WhatIsTopology(InteractiveScene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class ThreeShapes(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
v_lines = Line(DOWN, UP).replicate(2)
|
||||
v_lines.set_height(FRAME_HEIGHT)
|
||||
v_lines.arrange(RIGHT, buff=FRAME_WIDTH / 3)
|
||||
v_lines.set_stroke(WHITE, 3)
|
||||
|
||||
titles = VGroup(
|
||||
Text("Möbius Strip"),
|
||||
Text("Torus"),
|
||||
Text("Klein Bottle"),
|
||||
)
|
||||
for title, x in zip(titles, [-1, 0, 1]):
|
||||
title.scale(60 / 48)
|
||||
title.set_x(x * FRAME_WIDTH / 3)
|
||||
title.to_edge(UP)
|
||||
|
||||
self.add(v_lines)
|
||||
self.add(titles)
|
||||
|
||||
|
||||
class ThisIsTheSame(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
|
@ -264,6 +286,36 @@ class AskAboutProvingCollision(InteractiveScene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class GraphOfBellCurve(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
axes = ThreeDAxes((-3, 3), (-3, 3), (0, 1))
|
||||
axes.set_depth(2, stretch=True)
|
||||
surface = axes.get_graph(lambda x, y: np.exp(-x**2 - y**2))
|
||||
surface.set_opacity(0.7)
|
||||
surface.always_sort_to_camera(self.camera)
|
||||
mesh = SurfaceMesh(surface, resolution=(21, 21))
|
||||
mesh.set_stroke(WHITE, 0.5, 0.5)
|
||||
|
||||
self.frame.reorient(42, 67, 0, (0.42, 0.43, 0.1), 6.03)
|
||||
self.frame.add_ambient_rotation(3 * DEG)
|
||||
self.add(axes)
|
||||
self.add(surface, mesh)
|
||||
self.wait(30)
|
||||
|
||||
|
||||
class GraphLabel(InteractiveScene):
|
||||
def construct(self):
|
||||
group = VGroup(
|
||||
Text("Graph of"),
|
||||
Tex(R"f(x, y) = e^{-x^2 - y^2}"),
|
||||
)
|
||||
group.arrange(DOWN)
|
||||
group.to_edge(UP)
|
||||
self.play(Write(group))
|
||||
self.wait()
|
||||
|
||||
|
||||
class ChekhovsGun(InteractiveScene):
|
||||
def construct(self):
|
||||
# Add image
|
||||
|
@ -519,7 +571,7 @@ class AskAboutUnsolved(InteractiveScene):
|
|||
def construct(self):
|
||||
randy = Randolph()
|
||||
randy.to_corner(DL)
|
||||
self.play(randy.says("What about the\nunsolvd problem?", "maybe"))
|
||||
self.play(randy.says("What about the\nunsolved problem?", "maybe"))
|
||||
self.play(Blink(randy))
|
||||
self.wait(2)
|
||||
|
||||
|
@ -602,7 +654,7 @@ class GreeneLobbTheorem(InteractiveScene):
|
|||
Theorem by Greene and Lobb (2020):
|
||||
Every smooth closed curve contains
|
||||
inscribed rectangles of all possible
|
||||
aspect ratio.
|
||||
aspect ratios.
|
||||
""", t2s={"smooth": ITALIC}, alignment="LEFT")
|
||||
text.to_corner(UL)
|
||||
|
||||
|
@ -640,3 +692,121 @@ class SmoothImplication(InteractiveScene):
|
|||
FadeIn(tangent, 0.5 * DOWN),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class ProblemSolvingToRecreation(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
words = VGroup(
|
||||
Text("Solving\nproblems"),
|
||||
Text("Helpful\nconstructs"),
|
||||
Text("Recreational\nmath"),
|
||||
)
|
||||
words.arrange(RIGHT, buff=2.5)
|
||||
words.set_y(-1.5)
|
||||
mind_bending = Text("(Sometimes Mind-bending)", font_size=24)
|
||||
mind_bending.next_to(words[1], DOWN)
|
||||
|
||||
arrows = VGroup(
|
||||
Arrow(w1, w2, thickness=4, buff=0.45)
|
||||
for w1, w2 in zip(words, words[1:])
|
||||
)
|
||||
arrows.space_out_submobjects(1.1)
|
||||
|
||||
self.play(FadeIn(words[0], lag_ratio=0.1))
|
||||
self.wait()
|
||||
self.play(
|
||||
FadeIn(words[1], lag_ratio=0.1),
|
||||
GrowArrow(arrows[0]),
|
||||
)
|
||||
self.wait()
|
||||
self.play(FadeIn(mind_bending, 0.25 * DOWN))
|
||||
self.wait()
|
||||
|
||||
# Move mind-bending
|
||||
mb = mind_bending["Mind-bending"]
|
||||
helpful = words[1]["Helpful"]
|
||||
|
||||
self.play(
|
||||
mb.animate.scale(2).move_to(helpful),
|
||||
FadeOut(helpful, 0.25 * UP),
|
||||
FadeOut(mind_bending["(Sometimes"][0]),
|
||||
FadeOut(mind_bending[")"][0]),
|
||||
)
|
||||
self.play(
|
||||
FadeIn(words[2], lag_ratio=0.1),
|
||||
GrowArrow(arrows[1]),
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
words[0].animate.set_opacity(0.1),
|
||||
arrows[0].animate.set_opacity(0.1),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class WriteTopologicalSpace(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
text = Text("Topological Space", font_size=72)
|
||||
text.to_edge(UP)
|
||||
self.play(Write(text))
|
||||
self.wait()
|
||||
|
||||
|
||||
class AskAboutTopology(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
morty = self.teacher
|
||||
stds = self.students
|
||||
|
||||
self.play(
|
||||
stds[0].says("What is a\ntopological space?", "raise_left_hand"),
|
||||
stds[1].change("pondering", stds[0].eyes),
|
||||
stds[2].change("pondering", stds[0].eyes),
|
||||
morty.change("tease"),
|
||||
)
|
||||
self.wait(2)
|
||||
self.play(
|
||||
stds[1].animate.look_at(stds[2].eyes),
|
||||
stds[2].says("What is\ntopology?", "maybe", look_at=morty.eyes, bubble_direction=LEFT)
|
||||
)
|
||||
self.wait()
|
||||
self.play(morty.change("guilty"))
|
||||
self.play(stds[0].change('confused'))
|
||||
self.play(morty.change("hesitant"))
|
||||
self.wait(4)
|
||||
|
||||
|
||||
class PlaylistMention(InteractiveScene):
|
||||
def construct(self):
|
||||
# Test
|
||||
rects = ScreenRectangle().replicate(8)
|
||||
rects.set_fill(GREY_E, 1)
|
||||
rects.set_stroke(WHITE, 1)
|
||||
group = Group()
|
||||
for x, rect in zip(np.linspace(1, 0, len(rects)), rects):
|
||||
rect.shift(x * 0.75 * UR)
|
||||
group.add(rect)
|
||||
group.add(Point())
|
||||
|
||||
thumbnail = ImageMobject("https://img.youtube.com/vi/OkmNXy7er84/maxresdefault.jpg")
|
||||
thumbnail.replace(rects[-1])
|
||||
group.add(thumbnail)
|
||||
|
||||
group.set_height(2)
|
||||
group.to_edge(UP, buff=1.0)
|
||||
|
||||
words = Text("More neat proofs\nand puzzle solutions")
|
||||
words.next_to(group, DOWN, buff=2.5)
|
||||
arrow = Arrow(words, group)
|
||||
self.play(
|
||||
FadeIn(group, UP),
|
||||
Write(words),
|
||||
GrowArrow(arrow)
|
||||
)
|
||||
self.wait()
|
||||
self.play(FadeOut(words), FadeOut(arrow))
|
||||
|
||||
|
||||
class EndScreen(PatreonEndScreen):
|
||||
title_text = ""
|
||||
|
|
|
@ -53,7 +53,6 @@ def get_full_surface(band_func, x_range):
|
|||
bound.apply_depth_test()
|
||||
meshes.set_stroke(WHITE, 0.5, 0.5)
|
||||
return Group(surface, m1, m2, bound)
|
||||
return Group(surface, bound)
|
||||
|
||||
|
||||
def get_sudanese_band(circle_on_xy_plane=False):
|
||||
|
|
Loading…
Add table
Reference in a new issue