aboutsummaryrefslogtreecommitdiffstats
path: root/scenes/v15_mobius.py
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
commitfafaebb051907a848a9406f9da19669c81a83a3b (patch)
treec30ea26e6b549e5523af2bae5c39569e9a946b12 /scenes/v15_mobius.py
parent59355909f2de9236af8168a26c70bcf6caa3b285 (diff)
download100cia-videos-fafaebb051907a848a9406f9da19669c81a83a3b.tar.gz
100cia-videos-fafaebb051907a848a9406f9da19669c81a83a3b.zip
Translate code, comments and logs to English; English README; configurable paths and env varsHEADmain
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.
Diffstat (limited to 'scenes/v15_mobius.py')
-rw-r--r--scenes/v15_mobius.py138
1 files changed, 69 insertions, 69 deletions
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()