From fafaebb051907a848a9406f9da19669c81a83a3b Mon Sep 17 00:00:00 2001 From: Elvis Claros Castro Date: Sat, 26 Sep 2026 20:50:41 -0300 Subject: Translate code, comments and logs to English; English README; configurable paths and env vars Identifiers, docstrings, comments and console messages are now in English. Narration, subtitles and on-screen text stay in Spanish (they are the video content). The Blender <-> Godot physics protocol uses English keys and body prefixes chosen to keep the original creation order, so cached simulations and renders stay bit-identical. The old Spanish environment variable names are still accepted. --- scenes/v15_mobius.py | 138 +++++++++++++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) (limited to 'scenes/v15_mobius.py') diff --git a/scenes/v15_mobius.py b/scenes/v15_mobius.py index a921c6b..bc00227 100644 --- a/scenes/v15_mobius.py +++ b/scenes/v15_mobius.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Cinta de Mobius renderizada como superficie reglada: se generan quads en 3D, -se proyectan con una camara fija y se dibujan de atras hacia adelante.""" +"""Möbius strip rendered as a ruled surface: quads are generated in 3D, +projected with a fixed camera and drawn back to front.""" import sys, os, math sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from manim import * @@ -11,7 +11,7 @@ CARA_A, CARA_B = "#FFD166", "#2F6FD0" def geom(tau, beta, L=9.4, w=0.62, nu=170, smax=1.0): - """Punto central y direccion transversal de la cinta para s en [0, smax].""" + """Centre point and transverse direction of the strip for s in [0, smax].""" s = np.linspace(0.0, smax, max(int(nu * smax), 2) + 1) th = max(beta * TAU, 1e-3) Rr = L / th @@ -30,11 +30,11 @@ def proj(P): c, sn = math.cos(YAW), math.sin(YAW) x2, y2 = x * c - y * sn, x * sn + y * c ct, st = math.cos(TILT), math.sin(TILT) - return x2, y2 * ct - z * st, y2 * st + z * ct # X, Y, profundidad + return x2, y2 * ct - z * st, y2 * st + z * ct # X, Y, depth def quads(tau, beta, L=9.4, w=0.62, nu=170, scale=1.0, center=ORIGIN): - """Lista de (poligono_screen, profundidad, color) sin ordenar.""" + """Unsorted list of (screen_polygon, depth, color).""" p, d, _ = geom(tau, beta, L, w, nu) A = p - w * d Bv = p + w * d @@ -56,19 +56,19 @@ def quads(tau, beta, L=9.4, w=0.62, nu=170, scale=1.0, center=ORIGIN): def draw(items): - """Painter's algorithm: lo mas lejos (profundidad mayor) se dibuja primero.""" + """Painter's algorithm: the farthest (greatest depth) is drawn first.""" items = sorted(items, key=lambda t: -t[1]) return VGroup(*[Polygon(*pts, stroke_width=0, fill_color=col, fill_opacity=1) for pts, _, col in items]) -def cinta(tau, beta, **kw): +def strip_obj(tau, beta, **kw): return draw(quads(tau, beta, **kw)) -def camino(tau, beta, off, smax=1.0, L=9.4, w=0.62, nu=170, scale=1.0, +def path_line(tau, beta, off, smax=1.0, L=9.4, w=0.62, nu=170, scale=1.0, center=ORIGIN, **kw): - """Poligonal sobre la cinta a distancia 'off' del centro (off en [-w, w]).""" + """Polyline on the strip at distance 'off' from the centre (off in [-w, w]).""" p, d, _ = geom(tau, beta, L, w, nu, smax=smax) P = p + off * d X, Y, _ = proj(P) @@ -83,94 +83,94 @@ class Mobius(TikTok): def construct(self): self.prepare() - chip = self.chip("Hacelo en casa", VERDE) + chip = self.chip("Hacelo en casa", C_GREEN) C = UP * 1.85 SC = 1.30 P = dict(L=9.4, w=0.62, nu=130, scale=SC, center=C) tau = ValueTracker(0.0) beta = ValueTracker(0.0) - sc = ValueTracker(0.60) # la tira plana mide L*scale: tiene que entrar + sc = ValueTracker(0.60) # the flat strip measures L*scale: it has to fit def actual(): - return cinta(tau.get_value(), beta.get_value(), + return strip_obj(tau.get_value(), beta.get_value(), **{**P, "scale": sc.get_value()}) - banda = actual() + band = actual() with self.beat(0) as b: b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45) - b.play(FadeIn(banda, shift=UP * 0.2), run_time=0.7) + b.play(FadeIn(band, shift=UP * 0.2), run_time=0.7) with self.beat(1) as b: - banda.add_updater(lambda m: m.become(actual())) + band.add_updater(lambda m: m.become(actual())) b.play(tau.animate.set_value(1.0), run_time=max(1.0, b.floor * 0.45), rate_func=smooth) b.play(beta.animate.set_value(1.0), sc.animate.set_value(SC), run_time=max(1.0, b.floor * 0.45), rate_func=smooth) - banda.clear_updaters() - banda.become(cinta(1.0, 1.0, **P)) + band.clear_updaters() + band.become(strip_obj(1.0, 1.0, **P)) with self.beat(2) as b: - nom = VGroup( + nm_key = VGroup( self.fit(Text("cinta de M\u00f6bius", font=FONT, font_size=58, - weight=BOLD, color=AMBAR), 8.0), + weight=BOLD, color=AMBER), 8.0), self.fit(Text("una sola cara", font=FONT, font_size=50, weight=BOLD, color=WHITE), 8.0), ).arrange(DOWN, buff=0.3).move_to(DOWN * 2.6) - b.play(Write(nom[0]), run_time=0.8) - b.play(FadeIn(nom[1], shift=UP * 0.15), run_time=0.6) + b.play(Write(nm_key[0]), run_time=0.8) + b.play(FadeIn(nm_key[1], shift=UP * 0.15), run_time=0.6) - def recorrido(off, color, prog): - m = camino(1.0, 1.0, off, smax=max(prog.get_value(), 0.004), + def route(off, color, prog): + m = path_line(1.0, 1.0, off, smax=max(prog.get_value(), 0.004), stroke_color=color, stroke_width=9, **P) return m with self.beat(3) as b: - b.play(FadeOut(nom), run_time=0.25) + b.play(FadeOut(nm_key), run_time=0.25) prog = ValueTracker(0.004) - traza = recorrido(0.72 * P["w"], ROSA, prog) - traza.add_updater(lambda m: m.become(recorrido(0.72 * P["w"], ROSA, prog))) - punta = Dot(radius=0.16, color=ROSA) - punta.add_updater(lambda m: m.move_to(traza.get_end())) - b.add(traza, punta) + trace = route(0.72 * P["w"], C_PINK, prog) + trace.add_updater(lambda m: m.become(route(0.72 * P["w"], C_PINK, prog))) + tip_pt = Dot(radius=0.16, color=C_PINK) + tip_pt.add_updater(lambda m: m.move_to(trace.get_end())) + b.add(trace, tip_pt) b.play(prog.animate.set_value(2.0), run_time=max(1.6, b.floor - 0.5), rate_func=linear) - traza.clear_updaters(); punta.clear_updaters() + trace.clear_updaters(); tip_pt.clear_updaters() with self.beat(4) as b: - b.play(FadeOut(VGroup(traza, punta)), run_time=0.3) + b.play(FadeOut(VGroup(trace, tip_pt)), run_time=0.3) prog2 = ValueTracker(0.004) - borde = recorrido(P["w"], VERDE, prog2) - borde.add_updater(lambda m: m.become(recorrido(P["w"], VERDE, prog2))) - b.add(borde) + edge = route(P["w"], C_GREEN, prog2) + edge.add_updater(lambda m: m.become(route(P["w"], C_GREEN, prog2))) + b.add(edge) b.play(prog2.animate.set_value(2.0), run_time=max(1.4, b.floor - 0.9), rate_func=linear) - borde.clear_updaters() - uno = self.fit(Text("un solo borde", font=FONT, font_size=50, - weight=BOLD, color=VERDE), 8.0).move_to(DOWN * 2.6) - b.play(FadeIn(uno, shift=UP * 0.15), run_time=0.6) + edge.clear_updaters() + one_val = self.fit(Text("un solo borde", font=FONT, font_size=50, + weight=BOLD, color=C_GREEN), 8.0).move_to(DOWN * 2.6) + b.play(FadeIn(one_val, shift=UP * 0.15), run_time=0.6) with self.beat(5) as b: - b.play(FadeOut(VGroup(borde, uno)), run_time=0.3) - corte = camino(1.0, 1.0, 0.0, smax=1.0, stroke_color=ROSA, + b.play(FadeOut(VGroup(edge, one_val)), run_time=0.3) + cut = path_line(1.0, 1.0, 0.0, smax=1.0, stroke_color=C_PINK, stroke_width=8, **P) - corte = DashedVMobject(corte, num_dashes=90, color=ROSA) - b.play(Create(corte), run_time=max(1.2, b.floor - 0.8)) - tij = self.fit(Text("cortala al medio", font=FONT, font_size=50, - weight=BOLD, color=ROSA), 8.0).move_to(DOWN * 2.6) - b.play(FadeIn(tij, shift=UP * 0.15), run_time=0.6) + cut = DashedVMobject(cut, num_dashes=90, color=C_PINK) + b.play(Create(cut), run_time=max(1.2, b.floor - 0.8)) + scissors = self.fit(Text("cortala al medio", font=FONT, font_size=50, + weight=BOLD, color=C_PINK), 8.0).move_to(DOWN * 2.6) + b.play(FadeIn(scissors, shift=UP * 0.15), run_time=0.6) with self.beat(6) as b: - b.play(FadeOut(VGroup(corte, tij)), run_time=0.3) - b.remove(banda) - larga = cinta(4.0, 1.0, L=18.0, w=0.30, nu=260, scale=0.92, center=C) - b.play(FadeIn(larga), run_time=0.7) + b.play(FadeOut(VGroup(cut, scissors)), run_time=0.3) + b.remove(band) + long_one = strip_obj(4.0, 1.0, L=18.0, w=0.30, nu=260, scale=0.92, center=C) + b.play(FadeIn(long_one), run_time=0.7) t = VGroup( self.fit(Text("no salen dos", font=FONT, font_size=50, weight=BOLD, color=WHITE), 8.0), self.fit(Text("sale UNA, el doble de larga", font=FONT, font_size=46, - weight=BOLD, color=AMBAR), 8.2), + weight=BOLD, color=AMBER), 8.2), ).arrange(DOWN, buff=0.3).move_to(DOWN * 2.6) b.play(FadeIn(t[0], shift=UP * 0.15), run_time=0.5) b.play(FadeIn(t[1], shift=UP * 0.15), run_time=0.6) @@ -181,28 +181,28 @@ class Mobius(TikTok): self.fit(Text("y esa ya tiene", font=FONT, font_size=48, weight=BOLD, color=WHITE), 8.0), self.fit(Text("DOS caras", font=FONT, font_size=62, - weight=BOLD, color=CELESTE), 8.0), + weight=BOLD, color=C_SKY), 8.0), ).arrange(DOWN, buff=0.28).move_to(DOWN * 2.7) b.play(FadeIn(dc[0], shift=UP * 0.15), run_time=0.5) b.play(FadeIn(dc[1], scale=0.75), run_time=0.7) with self.beat(8) as b: - b.play(FadeOut(VGroup(larga, dc)), run_time=0.35) - c1 = DashedVMobject(camino(1.0, 1.0, P["w"] / 3, stroke_color=VERDE, + b.play(FadeOut(VGroup(long_one, dc)), run_time=0.35) + c1 = DashedVMobject(path_line(1.0, 1.0, P["w"] / 3, stroke_color=C_GREEN, stroke_width=7, **P), - num_dashes=80, color=VERDE) - c2 = DashedVMobject(camino(1.0, 1.0, -P["w"] / 3, stroke_color=VERDE, + num_dashes=80, color=C_GREEN) + c2 = DashedVMobject(path_line(1.0, 1.0, -P["w"] / 3, stroke_color=C_GREEN, stroke_width=7, **P), - num_dashes=80, color=VERDE) - b.play(FadeIn(banda), run_time=0.35) + num_dashes=80, color=C_GREEN) + b.play(FadeIn(band), run_time=0.35) b.play(Create(c1), Create(c2), run_time=max(1.1, b.floor - 1.1)) tt = self.fit(Text("ahora cortá a 1/3 del borde", font=FONT, font_size=44, - weight=BOLD, color=VERDE), 8.2).move_to(DOWN * 2.7) + weight=BOLD, color=C_GREEN), 8.2).move_to(DOWN * 2.7) b.play(FadeIn(tt, shift=UP * 0.15), run_time=0.55) with self.beat(9) as b: b.play(FadeOut(VGroup(c1, c2, tt)), run_time=0.3) - b.remove(banda) + b.remove(band) q1 = quads(1.0, 1.0, L=9.4, w=0.22, nu=170, scale=0.95, center=C + LEFT * 1.15) q2 = quads(4.0, 1.0, L=18.0, w=0.22, nu=260, scale=0.72, @@ -210,32 +210,32 @@ class Mobius(TikTok): r1, r2 = draw(q1), draw(q2) dep = np.array([q[1] for q in q1]) med = float(np.median(dep)) - frente = draw([q for q in q1 # eslabon que pasa encima + front_side = draw([q for q in q1 # link that goes over if np.mean([pt[0] for pt in q[0]]) > C[0] - 1.15 and q[1] < med]) - cadena = VGroup(r1, r2, frente) - b.play(FadeIn(cadena), run_time=0.8) + chain = VGroup(r1, r2, front_side) + b.play(FadeIn(chain), run_time=0.8) t2 = VGroup( self.fit(Text("dos cintas distintas", font=FONT, font_size=48, weight=BOLD, color=WHITE), 8.2), self.fit(Text("y quedan enganchadas", font=FONT, font_size=48, - weight=BOLD, color=AMBAR), 8.2), + weight=BOLD, color=AMBER), 8.2), ).arrange(DOWN, buff=0.3).move_to(DOWN * 2.7) b.play(FadeIn(t2[0], shift=UP * 0.15), run_time=0.5) b.play(FadeIn(t2[1], shift=UP * 0.15), run_time=0.6) with self.beat(10) as b: - b.play(FadeOut(VGroup(cadena, t2)), run_time=0.4) - cta = VGroup( + b.play(FadeOut(VGroup(chain, t2)), run_time=0.4) + count_txt = VGroup( self.fit(Text("una hoja y cinta", font=FONT, font_size=52, weight=BOLD, color=WHITE), 8.0), self.fit(Text("hacelo ahora", font=FONT, font_size=66, - weight=BOLD, color=VERDE), 8.0), + weight=BOLD, color=C_GREEN), 8.0), self.fit(Text("contame cómo te fue", font=FONT, font_size=42, weight=BOLD, color=WHITE), 8.0), ).arrange(DOWN, buff=0.32).move_to(UP * 1.4) - b.play(FadeIn(cta[0], shift=UP * 0.12), run_time=0.5) - b.play(Write(cta[1]), run_time=0.8) - b.play(FadeIn(cta[2], shift=UP * 0.12), run_time=0.5) + b.play(FadeIn(count_txt[0], shift=UP * 0.12), run_time=0.5) + b.play(Write(count_txt[1]), run_time=0.8) + b.play(FadeIn(count_txt[2], shift=UP * 0.12), run_time=0.5) self.finish() -- cgit v1.2.3