# Genera sites//img/eje-*.svg: un símbolo por eje pintado con spray (relleno en zigzag, # trazos con pulso y chorreones), en el color de cada eje (los mismos que los regueros del dibujo). import sys, random, math, os OUT = sys.argv[1] EJES = {"hogar": "#f04e23", "clima": "#14965a", "fronteras": "#f2b705", "pueblos": "#3b5bdb", "igualdad": "#8e44c9"} DEFS = ('' '' '' '') def monigote(o, x, y, h, col, brazo=False, paso=False): sw = max(1.4, h * .016) pts, yy, i, top = [], y - h, 0, y - h while yy <= y: t = (yy - top) / h cx = x if t < .13: w = h * .055 * math.sin(math.pi * t / .13) ** .6 + sw * .3 elif t < .16: w = h * .01 else: u = (t - .16) / .84 w = h * (.07 * (1 - u) ** .8 + .016) if paso and u > .5: cx += (-1 if (i // 2) % 2 else 1) * h * .04 * (u - .5) / .5 w *= .6 pts.append((cx + (-1 if i % 2 else 1) * w * random.uniform(.75, 1.25), yy)) yy += sw * 2.1 * random.uniform(.85, 1.15) * (.55 if t < .13 else 1) i += 1 d = "M" + " L".join(f"{px:.1f},{py:.1f}" for px, py in pts) o.append(f'') if brazo: bx, by = x + h * .06, top + h * .2 p = [(bx + j / 9 * h * .06 + (-1 if j % 2 else 1) * h * .014, by - j / 9 * h * .3) for j in range(10)] o.append(f'') def j(v, a): return v + random.uniform(-a, a) def relleno(o, poly, col, paso=2.6, sw=3.6): # Zigzag horizontal que rellena un polígono convexo, como una pasada de spray. ys = [y for _, y in poly] pts, y, i = [], min(ys) + sw * .4, 0 while y <= max(ys) - sw * .4: xs = [] for (x1, y1), (x2, y2) in zip(poly, poly[1:] + poly[:1]): if (y1 <= y < y2) or (y2 <= y < y1): xs.append(x1 + (y - y1) * (x2 - x1) / (y2 - y1)) if len(xs) >= 2: a, b = min(xs), max(xs) pts.append((j(a if i % 2 else b, 1.2), y)) i += 1 y += paso * random.uniform(.85, 1.15) o.append(f'') def linea(o, pts, col, sw=5): # Trazo con pulso: dos pasadas ligeramente desplazadas. for k in range(2): d = "M" + " L".join(f"{j(x, 1.1):.1f},{j(y, 1.1):.1f}" for x, y in pts) o.append(f'') def chorreon(o, x, y, largo, col): y -= 6 o.append(f'') o.append(f'') def hogar(o, col): # Una casa: tejado, dos muros y el dintel; la puerta queda en blanco. relleno(o, [(70, 22), (128, 72), (12, 72)], col) relleno(o, [(24, 72), (54, 72), (54, 150), (24, 150)], col) relleno(o, [(86, 72), (116, 72), (116, 150), (86, 150)], col) relleno(o, [(54, 72), (86, 72), (86, 96), (54, 96)], col) linea(o, [(98, 50), (98, 26), (110, 26), (110, 60)], col, 5) for x, l in ((30, 22), (47, 14), (92, 28), (110, 16)): chorreon(o, x, 150, l, col) def clima(o, col): # El planeta que se derrite: anillo en zigzag, meridianos y chorreones. cx, cy, r, pts = 70, 72, 52, [] for i in range(220): a = 2 * math.pi * i / 219 rr = r - (0 if i % 2 else 11) + random.uniform(-1.5, 1.5) pts.append((cx + rr * math.cos(a), cy + rr * math.sin(a))) o.append(f'') linea(o, [(cx + 44 * math.cos(math.pi * k / 20), cy + 44 * math.sin(math.pi * k / 20) * .32) for k in range(21)], col, 4) linea(o, [(cx + 44 * math.cos(math.pi * k / 20) * .38, cy - 44 * math.sin(math.pi * k / 20)) for k in range(-10, 11)], col, 4) for x, l in ((40, 26), (55, 40), (72, 30), (88, 44), (102, 20)): y0 = cy + math.sqrt(max(0, r * r - (x - cx) ** 2)) - 4 chorreon(o, x, y0, l, col) def fronteras(o, col): # Una valla rota: barrotes que se abren en el centro y alambre de espino cortado. for x in (14, 32, 108, 126): linea(o, [(x, 40), (x, 150)], col, 6) linea(o, [(50, 150), (52, 100), (40, 56)], col, 6) linea(o, [(90, 150), (88, 100), (100, 56)], col, 6) linea(o, [(6, 62), (44, 66)], col, 5) linea(o, [(96, 66), (134, 62)], col, 5) linea(o, [(6, 112), (54, 114)], col, 5) linea(o, [(86, 114), (134, 112)], col, 5) for x, y in ((22, 64), (116, 64), (22, 113), (118, 113)): linea(o, [(x - 4, y - 4), (x + 4, y + 4)], col, 4) linea(o, [(x + 4, y - 4), (x - 4, y + 4)], col, 4) def igualdad(o, col): # El signo igual, en dos barras de spray con chorreones. relleno(o, [(14, 50), (126, 46), (126, 76), (14, 80)], col) relleno(o, [(14, 100), (126, 96), (126, 126), (14, 130)], col) for x, y, l in ((30, 79, 14), (100, 75, 10), (46, 129, 22), (112, 126, 14)): chorreon(o, x, y, l, col) def eslabon(o, cx, cy, ang, col, roto=False): # Un eslabón: óvalo a pulso; el roto se abre por un extremo. ca, sa, pts = math.cos(ang), math.sin(ang), [] for k in range(29 if roto else 37): t = 2 * math.pi * (k / 36 + (.12 if roto else 0)) x, y = 19 * math.cos(t), 11 * math.sin(t) pts.append((cx + x * ca - y * sa, cy + x * sa + y * ca)) linea(o, pts, col, 7) def pueblos(o, col): # Una cadena rota: dos tramos enlazados que se abren en el centro, con chispas en el corte. eslabon(o, 20, 118, -.3, col) eslabon(o, 48, 108, -.3, col, roto=True) eslabon(o, 92, 108, .3 + math.pi, col, roto=True) eslabon(o, 120, 118, .3, col) for a in (-2.5, -2.0, -1.57, -1.14, -.64): linea(o, [(70 + 16 * math.cos(a), 96 + 16 * math.sin(a)), (70 + 36 * math.cos(a), 96 + 36 * math.sin(a))], col, 5) os.makedirs(OUT, exist_ok=True) for n, (nombre, col) in enumerate(EJES.items()): random.seed(40 + n) o = [] globals()[nombre](o, col) open(f"{OUT}/eje-{nombre}.svg", "w").write(f'{DEFS}' + "".join(o) + "\n")