diff options
Diffstat (limited to 'scenes/v17_cicloide.py')
| -rw-r--r-- | scenes/v17_cicloide.py | 188 |
1 files changed, 94 insertions, 94 deletions
diff --git a/scenes/v17_cicloide.py b/scenes/v17_cicloide.py index 5e6d4b9..79b9281 100644 --- a/scenes/v17_cicloide.py +++ b/scenes/v17_cicloide.py @@ -1,30 +1,30 @@ # -*- coding: utf-8 -*- -"""La braquistocrona: la recta pierde contra la cicloide. -Todo el movimiento sale de la fisica real (caida libre sin rozamiento).""" +"""The brachistochrone: the straight line loses to the cycloid. +All motion comes from real physics (frictionless free fall).""" import sys, os, math sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from manim import * from tiktok import * -TH1 = 4.0553 # angulo final: da D/H = 3, la curva pasa por debajo +TH1 = 4.0553 # final angle: gives D/H = 3, the curve dips below DX = 7.0 RR = DX / (TH1 - math.sin(TH1)) HH = RR * (1 - math.cos(TH1)) X0, Y0 = -3.5, 3.15 -T_C = 1.55 # lo que tarda la cicloide en pantalla -G = RR * (TH1 / T_C) ** 2 # gravedad ajustada a ese tiempo +T_C = 1.55 # how long the cycloid takes on screen +G = RR * (TH1 / T_C) ** 2 # gravity tuned to that time LL = math.hypot(DX, HH) AA = G * HH / LL -T_L = math.sqrt(2 * LL / AA) # 2,18 s: la recta llega 40% mas tarde +T_L = math.sqrt(2 * LL / AA) # 2.18 s: the straight line arrives 40% later P0 = np.array([X0, Y0, 0.0]) P1 = np.array([X0 + DX, Y0 - HH, 0.0]) UU = (P1 - P0) / LL VMAX = math.sqrt(4 * G * RR) -RW = 1.12 # rueda de la bici +RW = 1.12 # bike wheel XW = -PI * RW YW = 0.55 -R2, BX, BY = 1.22, 0.0, 0.30 # cuenco de la tautocrona +R2, BX, BY = 1.22, 0.0, 0.30 # tautochrone bowl T_TAU = 2.0 WW = PI / (2 * T_TAU) @@ -33,11 +33,11 @@ def cyc(th): return np.array([X0 + RR * (th - math.sin(th)), Y0 - RR * (1 - math.cos(th)), 0.0]) -def marca(th): +def tick_m(th): return np.array([XW + RW * (th - math.sin(th)), YW + RW * (1 - math.cos(th)), 0.0]) -def cuenco(th): +def bowl(th): return np.array([BX + R2 * (th - math.sin(th)) - R2 * PI, BY + 2 * R2 - R2 * (1 - math.cos(th)), 0.0]) @@ -48,63 +48,63 @@ def poli(f, a, b, col, w=8, n=200): return m -class Cicloide(TikTok): +class Cycloid(TikTok): NAME = "cicloide" def construct(self): self.prepare() - chip = self.chip("¿Cuál gana?", AMBAR) + chip = self.chip("¿Cuál gana?", AMBER) - plata = DashedLine([X0 - 0.8, Y0 + 0.66, 0], [X0 + 1.7, Y0 + 0.66, 0], - stroke_width=3, color=GRIS, dash_length=0.1) - pc = Dot(radius=0.19, color=AMBAR).move_to([X0 - 0.4, Y0 + 0.66, 0]) - pr = Dot(radius=0.19, color=CELESTE).move_to([X0 + 0.08, Y0 + 0.66, 0]) + money = DashedLine([X0 - 0.8, Y0 + 0.66, 0], [X0 + 1.7, Y0 + 0.66, 0], + stroke_width=3, color=C_GRAY, dash_length=0.1) + pc = Dot(radius=0.19, color=AMBER).move_to([X0 - 0.4, Y0 + 0.66, 0]) + pr = Dot(radius=0.19, color=C_SKY).move_to([X0 + 0.08, Y0 + 0.66, 0]) meta = DashedLine(P1 + UP * 1.35, P1 + DOWN * 0.95, stroke_width=6, - color=VERDE, dash_length=0.14) - rotm = Text("META", font=FONT, font_size=32, weight=BOLD, color=VERDE) + color=C_GREEN, dash_length=0.14) + rotm = Text("META", font=FONT, font_size=32, weight=BOLD, color=C_GREEN) rotm.next_to(meta, UP, buff=0.14) - leyenda = VGroup( - VGroup(Dot(radius=0.15, color=AMBAR), + legend = VGroup( + VGroup(Dot(radius=0.15, color=AMBER), Text("curva", font=FONT, font_size=38, weight=BOLD, - color=AMBAR)).arrange(RIGHT, buff=0.22), - VGroup(Dot(radius=0.15, color=CELESTE), + color=AMBER)).arrange(RIGHT, buff=0.22), + VGroup(Dot(radius=0.15, color=C_SKY), Text("recta", font=FONT, font_size=38, weight=BOLD, - color=CELESTE)).arrange(RIGHT, buff=0.22), + color=C_SKY)).arrange(RIGHT, buff=0.22), ).arrange(RIGHT, buff=1.3).move_to([0, -1.3, 0]) with self.beat(0) as b: b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.4) - b.play(Create(plata), run_time=0.4) + b.play(Create(money), run_time=0.4) b.play(FadeIn(pc, scale=0.4), FadeIn(pr, scale=0.4), run_time=0.5) - b.play(Create(meta), FadeIn(rotm), FadeIn(leyenda), run_time=0.7) + b.play(Create(meta), FadeIn(rotm), FadeIn(legend), run_time=0.7) - recta = Line(P0, P1, stroke_width=8, color=CELESTE) - curva = poli(cyc, 0, TH1, AMBAR) + line_m = Line(P0, P1, stroke_width=8, color=C_SKY) + curve_obj = poli(cyc, 0, TH1, AMBER) with self.beat(1) as b: - b.play(Create(recta), run_time=0.9) - b.play(Create(curva), run_time=max(0.9, b.floor - 1.4)) + b.play(Create(line_m), run_time=0.9) + b.play(Create(curve_obj), run_time=max(0.9, b.floor - 1.4)) inter = Text("?", font=FONT, font_size=115, weight=BOLD, color=WHITE).move_to([0.0, 1.62, 0]) with self.beat(2) as b: b.play(FadeIn(inter, scale=0.5), run_time=0.5) - b.play(Indicate(inter, scale_factor=1.25, color=AMBAR), run_time=0.9) + b.play(Indicate(inter, scale_factor=1.25, color=AMBER), run_time=0.9) rot = Text("el más corto", font=FONT, font_size=40, weight=BOLD, - color=CELESTE).move_to([-0.15, 3.02, 0]) + color=C_SKY).move_to([-0.15, 3.02, 0]) with self.beat(3) as b: b.play(FadeOut(inter), run_time=0.3) - b.play(recta.animate.set_stroke(width=12), FadeIn(rot, shift=UP * 0.2), + b.play(line_m.animate.set_stroke(width=12), FadeIn(rot, shift=UP * 0.2), run_time=0.55) - b.play(ShowPassingFlash(recta.copy().set_stroke(WHITE, 13), time_width=0.5), + b.play(ShowPassingFlash(line_m.copy().set_stroke(WHITE, 13), time_width=0.5), run_time=1.0) - b.play(recta.animate.set_stroke(width=8), run_time=0.3) + b.play(line_m.animate.set_stroke(width=8), run_time=0.3) - # --- la carrera -------------------------------------------------------- + # --- the race ---------------------------------------------------------- T = ValueTracker(0.0) def up_c(m): @@ -115,16 +115,16 @@ class Cicloide(TikTok): t = min(T.get_value(), T_L) m.move_to(P0 + UU * (0.5 * AA * t * t)) - med = VGroup(Circle(radius=0.34, stroke_width=0, fill_color=AMBAR, fill_opacity=1), + med = VGroup(Circle(radius=0.34, stroke_width=0, fill_color=AMBER, fill_opacity=1), Text("1º", font=FONT, font_size=34, weight=BOLD, color="#0B0F1A")) med.move_to(P1 + UP * 0.72).set_opacity(0) med.add_updater(lambda m: m.set_opacity(1.0 if T.get_value() >= T_C else 0.0)) with self.beat(4) as b: - b.play(FadeOut(rot), FadeOut(plata), pc.animate.move_to(P0), + b.play(FadeOut(rot), FadeOut(money), pc.animate.move_to(P0), pr.animate.move_to(P0), run_time=0.5) ya = Text("¡LARGA!", font=FONT, font_size=66, weight=BOLD, - color=VERDE).move_to([0, 1.7, 0]) + color=C_GREEN).move_to([0, 1.7, 0]) b.play(FadeIn(ya, scale=1.7), run_time=0.3) b.play(FadeOut(ya), run_time=0.22) pc.add_updater(up_c) @@ -133,38 +133,38 @@ class Cicloide(TikTok): b.play(T.animate.set_value(T_L), run_time=T_L, rate_func=linear) pc.clear_updaters(); pr.clear_updaters(); med.clear_updaters() - nivel = DashedLine([X0 - 0.2, Y0 - HH, 0], [X0 + DX + 0.2, Y0 - HH, 0], - stroke_width=4, color=GRIS, dash_length=0.12) - fondo = cyc(PI) - nota = Text("pasa por debajo de la meta", font=FONT, font_size=36, weight=BOLD, - color=ROSA).move_to([0.3, -0.95, 0]) - flecha = Arrow(nota.get_top() + RIGHT * 0.9, fondo + DOWN * 0.22, buff=0.06, - color=ROSA, stroke_width=6, max_tip_length_to_length_ratio=0.2) + level = DashedLine([X0 - 0.2, Y0 - HH, 0], [X0 + DX + 0.2, Y0 - HH, 0], + stroke_width=4, color=C_GRAY, dash_length=0.12) + background = cyc(PI) + note_txt = Text("pasa por debajo de la meta", font=FONT, font_size=36, weight=BOLD, + color=C_PINK).move_to([0.3, -0.95, 0]) + arrow_m = Arrow(note_txt.get_top() + RIGHT * 0.9, background + DOWN * 0.22, buff=0.06, + color=C_PINK, stroke_width=6, max_tip_length_to_length_ratio=0.2) gap = VGroup( Text("la recta tardó", font=FONT, font_size=38, weight=BOLD, color=WHITE), - Text("40% más", font=FONT, font_size=64, weight=BOLD, color=CELESTE), + Text("40% más", font=FONT, font_size=64, weight=BOLD, color=C_SKY), ).arrange(RIGHT, buff=0.3).move_to([0.0, -2.15, 0]) with self.beat(5) as b: - b.play(FadeOut(leyenda), Create(nivel), run_time=0.45) - b.play(FadeIn(nota, shift=UP * 0.2), GrowArrow(flecha), run_time=0.6) + b.play(FadeOut(legend), Create(level), run_time=0.45) + b.play(FadeIn(note_txt, shift=UP * 0.2), GrowArrow(arrow_m), run_time=0.6) b.play(FadeIn(gap, shift=UP * 0.2), run_time=0.55) - # --- por que gana: velocidad temprana ---------------------------------- + # --- why it wins: early speed ------------------------------------------ riel_c = Rectangle(width=6.2, height=0.32, stroke_width=0, fill_color="#1B2233", fill_opacity=1).move_to([0.0, -1.30, 0]) riel_r = riel_c.copy().move_to([0.0, -2.20, 0]) - bar_c = Rectangle(width=0.02, height=0.32, stroke_width=0, fill_color=AMBAR, + bar_c = Rectangle(width=0.02, height=0.32, stroke_width=0, fill_color=AMBER, fill_opacity=1).move_to(riel_c.get_left(), LEFT) - bar_r = Rectangle(width=0.02, height=0.32, stroke_width=0, fill_color=CELESTE, + bar_r = Rectangle(width=0.02, height=0.32, stroke_width=0, fill_color=C_SKY, fill_opacity=1).move_to(riel_r.get_left(), LEFT) - lab_c = Text("curva", font=FONT, font_size=30, weight=BOLD, color=AMBAR) - lab_r = Text("recta", font=FONT, font_size=30, weight=BOLD, color=CELESTE) + lab_c = Text("curva", font=FONT, font_size=30, weight=BOLD, color=AMBER) + lab_r = Text("recta", font=FONT, font_size=30, weight=BOLD, color=C_SKY) lab_c.next_to(riel_c, LEFT, buff=0.18) lab_r.next_to(riel_r, LEFT, buff=0.18) - izq_c, izq_r = riel_c.get_left()[0], riel_r.get_left()[0] + left_c, left_r = riel_c.get_left()[0], riel_r.get_left()[0] - def barra(m, v, x0, y): + def bar_m(m, v, x0, y): w = max(0.02, 6.2 * v / VMAX) m.stretch_to_fit_width(w) m.move_to([x0 + w / 2, y, 0]) @@ -172,13 +172,13 @@ class Cicloide(TikTok): def ub_c(m): t = min(T.get_value(), T_C) th = t * math.sqrt(G / RR) - barra(m, math.sqrt(max(0.0, 2 * G * RR * (1 - math.cos(th)))), izq_c, -1.30) + bar_m(m, math.sqrt(max(0.0, 2 * G * RR * (1 - math.cos(th)))), left_c, -1.30) def ub_r(m): - barra(m, AA * min(T.get_value(), T_L), izq_r, -2.20) + bar_m(m, AA * min(T.get_value(), T_L), left_r, -2.20) with self.beat(6) as b: - b.play(FadeOut(VGroup(nivel, flecha, nota, gap, med)), run_time=0.35) + b.play(FadeOut(VGroup(level, arrow_m, note_txt, gap, med)), run_time=0.35) T.set_value(0.0) b.play(pc.animate.move_to(P0), pr.animate.move_to(P0), FadeIn(VGroup(riel_c, riel_r, lab_c, lab_r, bar_c, bar_r)), run_time=0.45) @@ -189,87 +189,87 @@ class Cicloide(TikTok): for m in (pc, pr, bar_c, bar_r): m.clear_updaters() - # --- la rueda de la bici ------------------------------------------------ - viejo = VGroup(recta, curva, meta, rotm, pc, pr, + # --- the bike wheel ----------------------------------------------------- + old_one = VGroup(line_m, curve_obj, meta, rotm, pc, pr, riel_c, riel_r, lab_c, lab_r, bar_c, bar_r) - piso = Line([-3.7, YW, 0], [3.7, YW, 0], stroke_width=6, color="#3A5487") + floor_obj = Line([-3.7, YW, 0], [3.7, YW, 0], stroke_width=6, color="#3A5487") TH = ValueTracker(0.0) - def dibujar_rueda(): + def draw_wheel(): th = TH.get_value() c = np.array([XW + RW * th, YW + RW, 0.0]) - g = VGroup(Circle(radius=RW, stroke_width=6, color=CELESTE).move_to(c)) + g = VGroup(Circle(radius=RW, stroke_width=6, color=C_SKY).move_to(c)) for k in range(3): a = -th - PI / 2 + k * TAU / 3 g.add(Line(c, c + RW * np.array([math.cos(a), math.sin(a), 0.0]), stroke_width=4, color="#3A5487")) return g - rueda = always_redraw(dibujar_rueda) - clavo = always_redraw(lambda: Dot(radius=0.14, color=AMBAR).move_to(marca(TH.get_value()))) - rastro = TracedPath(lambda: marca(TH.get_value()), stroke_color=AMBAR, stroke_width=8) - nom = Text("CICLOIDE", font=FONT, font_size=66, weight=BOLD, - color=AMBAR).move_to([0, -1.15, 0]) + wheel = always_redraw(draw_wheel) + peg = always_redraw(lambda: Dot(radius=0.14, color=AMBER).move_to(tick_m(TH.get_value()))) + trail = TracedPath(lambda: tick_m(TH.get_value()), stroke_color=AMBER, stroke_width=8) + nm_key = Text("CICLOIDE", font=FONT, font_size=66, weight=BOLD, + color=AMBER).move_to([0, -1.15, 0]) with self.beat(7) as b: - b.play(FadeOut(viejo), run_time=0.4) - b.play(Create(piso), run_time=0.3) - b.add(rastro, rueda, clavo) + b.play(FadeOut(old_one), run_time=0.4) + b.play(Create(floor_obj), run_time=0.3) + b.add(trail, wheel, peg) b.play(TH.animate.set_value(TAU), run_time=max(1.6, b.floor - 1.5), rate_func=linear) - b.remove(rueda, clavo, rastro) - arco = poli(marca, 0, TAU, AMBAR) - b.add(arco) - b.play(FadeIn(nom, shift=UP * 0.2), run_time=0.45) + b.remove(wheel, peg, trail) + arc_m = poli(tick_m, 0, TAU, AMBER) + b.add(arc_m) + b.play(FadeIn(nm_key, shift=UP * 0.2), run_time=0.45) # --- la tautocrona ------------------------------------------------------ - tazon = poli(cuenco, 0, TAU, AMBAR) + basin = poli(bowl, 0, TAU, AMBER) TH0 = [0.30 * PI, 0.56 * PI, 0.82 * PI] - cols = [ROSA, CELESTE, VERDE] - bolas = VGroup(*[Dot(radius=r, color=c).move_to(cuenco(t)) + cols = [C_PINK, C_SKY, C_GREEN] + bolas = VGroup(*[Dot(radius=r, color=c).move_to(bowl(t)) for t, c, r in zip(TH0, cols, (0.22, 0.175, 0.13))]) - guias = VGroup(*[DashedLine([-4.1, cuenco(t)[1], 0], cuenco(t), stroke_width=3, + guides = VGroup(*[DashedLine([-4.1, bowl(t)[1], 0], bowl(t), stroke_width=3, color=c, dash_length=0.1) for t, c in zip(TH0, cols)]) with self.beat(8) as b: - b.play(FadeOut(VGroup(nom, piso)), run_time=0.3) - b.play(Transform(arco, tazon), run_time=0.9) + b.play(FadeOut(VGroup(nm_key, floor_obj)), run_time=0.3) + b.play(Transform(arc_m, basin), run_time=0.9) b.play(LaggedStart(*[FadeIn(d, scale=0.5) for d in bolas], lag_ratio=0.25), run_time=0.8) - b.play(Create(guias), run_time=0.5) + b.play(Create(guides), run_time=0.5) TT = ValueTracker(0.0) - def soltar(th0): + def drop_at(th0): def u(m): c = math.cos(th0 / 2) * math.cos(WW * TT.get_value()) - m.move_to(cuenco(2 * math.acos(max(-1.0, min(1.0, c))))) + m.move_to(bowl(2 * math.acos(max(-1.0, min(1.0, c))))) return u with self.beat(9) as b: - b.play(FadeOut(guias), run_time=0.25) + b.play(FadeOut(guides), run_time=0.25) for d, t0 in zip(bolas, TH0): - d.add_updater(soltar(t0)) + d.add_updater(drop_at(t0)) b.play(TT.animate.set_value(T_TAU), run_time=T_TAU, rate_func=linear) for d in bolas: d.clear_updaters() juntas = Text("las tres, juntas", font=FONT, font_size=58, weight=BOLD, - color=VERDE).move_to([0, -1.5, 0]) + color=C_GREEN).move_to([0, -1.5, 0]) b.play(Flash(bolas[0], color=WHITE, flash_radius=0.9, num_lines=18), FadeIn(juntas, shift=UP * 0.25), run_time=0.7) - cierre = VGroup( - Text("1696", font=FONT, font_size=76, weight=BOLD, color=AMBAR), + closing = VGroup( + Text("1696", font=FONT, font_size=76, weight=BOLD, color=AMBER), Text("Bernoulli desafía", font=FONT, font_size=44, weight=BOLD, color=WHITE), Text("a los matemáticos", font=FONT, font_size=44, weight=BOLD, color=WHITE), - Text("Newton lo resuelve", font=FONT, font_size=46, weight=BOLD, color=VERDE), - Text("esa misma noche", font=FONT, font_size=46, weight=BOLD, color=VERDE), + Text("Newton lo resuelve", font=FONT, font_size=46, weight=BOLD, color=C_GREEN), + Text("esa misma noche", font=FONT, font_size=46, weight=BOLD, color=C_GREEN), ).arrange(DOWN, buff=0.26).move_to(UP * 0.75) with self.beat(10) as b: - b.play(FadeOut(VGroup(arco, bolas, juntas)), run_time=0.4) - b.play(FadeIn(cierre[:3], shift=UP * 0.25), run_time=0.7) - b.play(FadeIn(cierre[3:], shift=UP * 0.25), run_time=0.7) + b.play(FadeOut(VGroup(arc_m, bolas, juntas)), run_time=0.4) + b.play(FadeIn(closing[:3], shift=UP * 0.25), run_time=0.7) + b.play(FadeIn(closing[3:], shift=UP * 0.25), run_time=0.7) self.finish() |