Pueblos libres: la bala rota en horizontal, con contorno y volumen en negro

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
hacklab 2026-10-14 21:48:05 +02:00
parent 9afe769758
commit 1d0a86acbf
14 changed files with 40 additions and 34 deletions

View file

@ -120,27 +120,33 @@ def girar(pts, ang, ox, oy, dx, dy):
return [(ox + (x - ox) * ca - (y - oy) * sa + dx, oy + (x - ox) * sa + (y - oy) * ca + dy) for x, y in pts]
def pueblos(o, col):
# Una bala rota: la punta salta hacia un lado y el casquillo se queda, con chispas en el corte.
punta = [(70, 30), (76, 35), (81, 43), (84, 52), (85, 62), (85, 80), (78, 77), (72, 82), (64, 76), (55, 79), (55, 62), (56, 52), (59, 43), (64, 35)]
grieta_a = [(85, 80), (78, 77), (72, 82), (64, 76), (55, 79)]
casquillo = [(55, 90), (63, 86), (70, 92), (77, 86), (85, 90), (85, 128), (55, 128)]
grieta_b = [(55, 90), (63, 86), (70, 92), (77, 86), (85, 90)]
culote = [(52, 132), (88, 132), (88, 150), (52, 150)]
giro_a = lambda pts: girar(pts, -.38, 70, 80, -4, 6)
giro_b = lambda pts: girar(pts, .08, 70, 120, 6, 8)
relleno(o, giro_a(punta), col)
linea(o, giro_a(punta[10:] + punta[:6]), col, 3)
linea(o, giro_a(grieta_a), col, 3.5)
relleno(o, giro_b(casquillo), col)
relleno(o, giro_b(culote), col)
linea(o, giro_b([(55, 90), (55, 128), (52, 132), (52, 150), (88, 150), (88, 132), (85, 128), (85, 90)]), col, 3)
linea(o, giro_b(grieta_b), col, 3.5)
for a in (-.5, 0, .45):
linea(o, [(96 + 6 * math.cos(a), 92 + 6 * math.sin(a)), (96 + 20 * math.cos(a), 92 + 20 * math.sin(a))], col, 4)
for a in (2.7, 3.2):
linea(o, [(46 + 6 * math.cos(a), 96 + 6 * math.sin(a)), (46 + 18 * math.cos(a), 96 + 18 * math.sin(a))], col, 4)
for x, l in ((60, 12), (74, 18), (84, 8)):
chorreon(o, x, 160, l, col)
# Una bala rota en horizontal: el casquillo a la izquierda y la punta que salta hacia la derecha.
# Contorno y líneas de volumen en negro para que tenga relieve.
ink = "#111"
o.append('<g transform="translate(0 -30) scale(1 1.35)">')
casquillo = [(14, 74), (60, 74), (64, 80), (59, 86), (65, 93), (60, 100), (62, 106), (14, 106)]
culote = [(6, 70), (14, 70), (14, 110), (6, 110)]
punta = [(76, 77), (98, 77), (112, 79), (124, 84), (132, 91), (124, 98), (112, 103), (98, 105), (76, 105), (80, 99), (74, 92), (79, 86), (73, 80)]
giro = lambda pts: girar(pts, -.16, 76, 91, 2, -10)
relleno(o, casquillo, col)
relleno(o, culote, col)
relleno(o, giro(punta), col)
linea(o, casquillo + casquillo[:1], ink, 3)
linea(o, culote + culote[:1], ink, 3)
linea(o, giro(punta + punta[:1]), ink, 3)
# Volumen: ranura del casquillo, sombra abajo y brillo arriba
linea(o, [(20, 75), (20, 105)], ink, 2.5)
linea(o, [(24, 100), (56, 100)], ink, 2.5)
linea(o, giro([(98, 78), (98, 104)]), ink, 2.5)
linea(o, giro([(84, 100), (112, 100), (124, 95)]), ink, 2.5)
linea(o, [(26, 80), (50, 80)], "#fff", 2.5)
linea(o, giro([(86, 82), (110, 83)]), "#fff", 2.5)
# Chispas en el corte
for a in (-1.9, -1.4, 1.5, 2.0):
linea(o, [(69 + 8 * math.cos(a), 90 + 8 * math.sin(a)), (69 + 22 * math.cos(a), 90 + 22 * math.sin(a))], col, 4)
for x, l in ((24, 14), (40, 22), (54, 10)):
chorreon(o, x, 110, l, col)
o.append('</g>')
os.makedirs(OUT, exist_ok=True)
for n, (nombre, col) in enumerate(EJES.items()):