diff --git a/docs/bocetos/boceto-10.svg b/docs/bocetos/boceto-10.svg
new file mode 100644
index 0000000..a467e1d
--- /dev/null
+++ b/docs/bocetos/boceto-10.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/bocetos/boceto-6.svg b/docs/bocetos/boceto-6.svg
new file mode 100644
index 0000000..7d9cd9d
--- /dev/null
+++ b/docs/bocetos/boceto-6.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/bocetos/boceto-7.svg b/docs/bocetos/boceto-7.svg
new file mode 100644
index 0000000..9a33f21
--- /dev/null
+++ b/docs/bocetos/boceto-7.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/bocetos/boceto-8.svg b/docs/bocetos/boceto-8.svg
new file mode 100644
index 0000000..a5b235e
--- /dev/null
+++ b/docs/bocetos/boceto-8.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/bocetos/boceto-9.svg b/docs/bocetos/boceto-9.svg
new file mode 100644
index 0000000..4124805
--- /dev/null
+++ b/docs/bocetos/boceto-9.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/plaza.svg b/docs/plaza.svg
new file mode 100644
index 0000000..9e648f1
--- /dev/null
+++ b/docs/plaza.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sites/takethestreet/en/index.html b/sites/takethestreet/en/index.html
deleted file mode 100644
index d354310..0000000
--- a/sites/takethestreet/en/index.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
-
-
-Take the Street · One street, every struggle
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- We were born in Madrid's Puerta del Sol on 26 September , fighting for housing. Today housing groups, environmentalists, anti-racists, anti-militarists and feminists share the squares, and the camps are spreading to Portugal and Italy.
- They don't take our homes, the planet, our papers and our peace one at a time. It's the same system, putting the profit of a few above everyone's lives. That's why we take to the same street together.
-
-
-
- Four axes
-
-
-
- Home
- Housing is a right, not a business.
- Against evictions, speculation, vulture funds and touristification. For public housing and neighbourhoods people can actually live in.
-
-
-
- Land
- The planet is our home too.
- Climate justice: polluters pay, not neighbourhoods. Green cities, public transport and an end to the destruction of the land.
-
-
-
- No borders
- No one is illegal.
- Regularisation, an end to racist raids and detention centres, and equal rights for everyone who lives here.
-
-
-
- Peace
- More homes, fewer tanks.
- Money for life, not for war. An end to the arms trade and solidarity with peoples living under war and occupation: with Palestine, loud and clear.
-
-
-
-
-
Feminisms throughout. The women hit hardest by evictions, the women who carry the care work, the women who cross borders: we look at all four axes through purple glasses.
-
-
-
-
- Camps
-
-
-
-
-
Italy
-
Milano · Statale Roma · piazza Bologna Tents at a dozen universities
-
-
-
What about your city?
-
If there's a camp where you live, or you want to start one, write to us at acampada26s@riseup.net and we'll add it to the network.
-
-
-
-
-
- How we organise
-
- Assembly. Decisions are made in the squares. No one speaks for everyone without a mandate.
- Autonomy. No parties or acronyms out front. Groups come with their own names, but the street belongs to everyone.
- Mutual aid and care. No one gets left behind: food, shelter, legal support and health care.
- A network of networks. Each camp owns its voice. What we share is coordinated on OASIS.
- The street as a tool. Taking public space openly and peacefully, with joy and without fear.
-
-
-
-
- Spread the word
- #takethestreet #unacalletodaslasluchas #26s
- On the 26th of every month , every square at once. Post in your language with the common hashtag and your city's.
- Logos and drawing for posters and social media: logotype · symbol · drawing
-
-
-
-
- Take the Street · international network of protest camps · 26S
- Text and drawing CC BY-SA 4.0 · Code AGPL-3.0
-
-
-
diff --git a/sites/takethestreet/img/calle.svg b/sites/takethestreet/img/calle.svg
index e14b7cf..9e648f1 100644
--- a/sites/takethestreet/img/calle.svg
+++ b/sites/takethestreet/img/calle.svg
@@ -1,405 +1,13 @@
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
diff --git a/sites/tomalacalle/img/calle.svg b/sites/tomalacalle/img/calle.svg
index e14b7cf..9e648f1 100644
--- a/sites/tomalacalle/img/calle.svg
+++ b/sites/tomalacalle/img/calle.svg
@@ -1,405 +1,13 @@
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/bocetos.py b/tools/bocetos.py
index 349a76a..ee0191f 100644
--- a/tools/bocetos.py
+++ b/tools/bocetos.py
@@ -3,7 +3,6 @@
# De cada portal sale un reguero de un color (cada lucha) y todos se juntan en la piña,
# que en el centro arde en colores de fuego.
import sys, random, math, os
-OUT = sys.argv[1]
INK = "#111"
FUEGO = ["#fffbe6", "#ffe066", "#ffb627", "#ff7b1c", "#f04e23", "#c8102e"] # del centro hacia fuera
LUCHAS = ["#8e44c9", "#3b5bdb", "#14965a", "#d6336c", "#2a9d8f", "#5b2a86"] # un color por reguero
@@ -19,6 +18,8 @@ DEFS = '''
+
+
'''
class Calle:
@@ -200,6 +201,8 @@ def b5():
c.gente((-.5, 12.5, 2.2, 3.5, 9000, 2.8), regueros(c, (4.0, 7.0, 17.0)), extra=lateral)
return c
-os.makedirs(OUT, exist_ok=True)
-for n, f in enumerate([b1, b2, b3, b4, b5], 1):
- open(f"{OUT}/boceto-{n}.svg", "w").write(f().svg())
+if __name__ == "__main__":
+ OUT = sys.argv[1]
+ os.makedirs(OUT, exist_ok=True)
+ for n, f in enumerate([b1, b2, b3, b4, b5], 1):
+ open(f"{OUT}/boceto-{n}.svg", "w").write(f().svg())
diff --git a/tools/plazas.py b/tools/plazas.py
new file mode 100644
index 0000000..18687fb
--- /dev/null
+++ b/tools/plazas.py
@@ -0,0 +1,320 @@
+# Genera la portada (la plaza que nace del cruce del boceto 5) y los bocetos 6 a 10:
+# plazas y cruces con el mismo acabado a mano que tools/bocetos.py.
+import sys, random, math, os
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+from bocetos import Calle, INK, FUEGO, FRIO, LUCHAS
+
+EJES = ["#f04e23", "#14965a", "#f2b705", "#3b5bdb", "#8e44c9"]
+
+
+class Escena(Calle):
+ def zn(s):
+ return s.EYE * s.F / (s.H + s.Y0 - s.VY) * .8
+
+ def seg(s, a, b, w=None, op=.95):
+ zn = s.zn()
+ if a[2] < zn and b[2] < zn:
+ return
+ if a[2] > b[2]:
+ a, b = b, a
+ if a[2] < zn:
+ t = (zn - a[2]) / (b[2] - a[2])
+ a = tuple(a[i] + (b[i] - a[i]) * t for i in range(3))
+ if w is None:
+ w = 34 / ((a[2] + b[2]) / 2) + 1.6
+ s.linea(s.P(*a), s.P(*b), w, op)
+
+ def poli(s, pts, w=None, op=.95):
+ for a, b in zip(pts, pts[1:]):
+ s.seg(a, b, w, op)
+
+ def abrir(s, *mascaras):
+ for m in mascaras:
+ s.o.append(f'')
+ s.o.append('')
+ s.cierre = ' ' + ' ' * len(mascaras)
+
+ def cerrar(s):
+ s.o.append(s.cierre)
+
+ def portal(s, a, b, alto=2.5, cornisa=True):
+ s.poli([(a[0], 0, a[1]), (a[0], alto, a[1]), (b[0], alto, b[1]), (b[0], 0, b[1])])
+ if cornisa:
+ dx, dz = b[0] - a[0], b[1] - a[1]
+ s.seg((a[0] - dx * .2, alto + .35, a[1] - dz * .2), (b[0] + dx * .2, alto + .35, b[1] + dz * .2), None, .6)
+
+ def fachada(s, a, b, portales=(), alto=2.5):
+ s.seg((a[0], 0, a[1]), (b[0], 0, b[1]))
+ L = math.hypot(b[0] - a[0], b[1] - a[1])
+ ux, uz = (b[0] - a[0]) / L, (b[1] - a[1]) / L
+ for d in portales:
+ s.portal((a[0] + ux * d, a[1] + uz * d), (a[0] + ux * (d + 1.5), a[1] + uz * (d + 1.5)), alto)
+
+ def esquina(s, X, Z, alto=3.2):
+ s.seg((X, 0, Z), (X, alto, Z), None, .7)
+
+ def farola(s, X, Z, h=4.2):
+ s.seg((X, 0, Z), (X, h, Z), None, .9)
+ s.seg((X, h, Z), (X + .6, h - .1, Z), None, .9)
+ c = s.P(X + .6, h - .35, Z)
+ s.o.append(f' ')
+
+ def tienda(s, X, Z, col, a=2.0, f=2.2, alto=1.2):
+ x0, x1, xm = X - a / 2, X + a / 2, X
+ fr = [(x0, 0, Z), (xm, alto, Z), (x1, 0, Z)]
+ s.poli(fr, None, .9)
+ s.seg((xm, alto, Z), (xm, alto, Z + f), None, .6)
+ s.seg((x0, 0, Z), (x0, 0, Z + f), None, .5)
+ s.seg((x1, 0, Z), (x1, 0, Z + f), None, .5)
+ p = [s.P(*q) for q in fr]
+ d = f"M{p[0][0]:.1f},{p[0][1]:.1f} L{p[1][0]:.1f},{p[1][1]:.1f} L{p[2][0]:.1f},{p[2][1]:.1f} Z"
+ s.tiendas.append(f' ')
+
+ def gente(s, pina, regueros, extra=(), puños=.1, zona=None, zmax=40, ejes=None):
+ CX, CZ, sx, sz, n, R = pina
+ zmin = s.EYE * s.F / (s.H + s.Y0 - s.VY) + .3
+ zona = zona or (lambda X, Z: True)
+ g = []
+
+ def cabe(X, Z):
+ return all(math.hypot(X - a, (Z - b) * .8) > .42 + .022 * Z for a, b, _ in g)
+ for X0, Z0, col, k in regueros:
+ for j in range(k):
+ t = (j + .5) / k
+ X = X0 + (CX - X0) * t + random.uniform(-.3, .3)
+ Z = Z0 + (CZ - Z0) * t + random.uniform(-.3, .3)
+ if Z > zmin and cabe(X, Z):
+ g.append((X, Z, col))
+ for _ in range(n):
+ X, Z = random.gauss(CX, sx), random.gauss(CZ, sz)
+ if zmin < Z < zmax and zona(X, Z) and cabe(X, Z):
+ g.append((X, Z, None))
+ g += list(extra)
+ c = s.P(CX, 1.0, CZ)
+ r0 = 2600 / CZ
+ s.o.append(f' ')
+ for _ in range(700):
+ ang, rr = random.uniform(0, 2 * math.pi), abs(random.gauss(0, r0 * .55))
+ k = min(len(FUEGO) - 1, int(rr / r0 * len(FUEGO)))
+ s.o.append(f' ')
+ s.o += s.tiendas
+ for X, Z, col in sorted(g, key=lambda q: -q[1]):
+ x, y = s.P(X, 0, Z)
+ h = 1.7 * s.F / Z * random.uniform(.9, 1.08)
+ d = math.hypot(X - CX, Z - CZ) / R
+ if d < 1:
+ col = FUEGO[min(len(FUEGO) - 1, int(max(0, d + random.uniform(-.12, .12)) * len(FUEGO)))]
+ elif col is None:
+ col = random.choice(ejes or FRIO) if ejes and random.random() < .35 else random.choice(FRIO)
+ s.monigote(x, y, h, col, random.uniform(-.06, .04), random.random() < .35, random.random() < puños)
+ return len(g)
+
+ def __init__(s, **k):
+ super().__init__(**k)
+ s.tiendas = []
+
+
+def llegan(X0, Z0, col, n):
+ return (X0, Z0, col, n)
+
+
+def portada():
+ # El cruce del boceto 5 se abre en una plaza: la calle llega desde abajo y la gente entra por todas partes
+ random.seed(15)
+ c = Escena(VX=1000, VY=60, EYE=9.0, F=600, Y0=100)
+ FA, FD, KI, KD = -6.5, 6.6, -4.2, 3.6
+ z1, z2, xl, xr = 11.0, 25.0, -24.0, 17.0
+ c.abrir("lados", "arriba")
+ c.fachada((FA, 3.0), (FA, z1), (4.0,))
+ c.fachada((FD, z1), (FD, 3.0), (3.0,))
+ c.seg((KI, 0, 3.0), (KI, 0, z1 - 1), 9)
+ c.seg((KI + .18, 0, 3.0), (KI + .18, 0, z1 - 1), 3, .7)
+ c.seg((KD, 0, 3.0), (KD, 0, z1 - 1), 7, .8)
+ for z in (4.0, 9.0):
+ c.seg((-.3, 0, z), (-.3, 0, z + 2.2), None, .8)
+ c.esquina(FA, z1); c.esquina(FD, z1)
+ c.fachada((FA, z1), (xl, z1), (6.0, 12.0))
+ c.fachada((xr, z1), (FD, z1), (4.0,))
+ c.fachada((xl, z1), (xl, 15.5), ())
+ c.fachada((xl, 19.5), (xl, z2), ())
+ for z in (15.5, 19.5):
+ c.esquina(xl, z)
+ c.seg((xl, 0, z), (-70, 0, z))
+ c.fachada((xr, z2), (xr, z1), (3.0, 9.0))
+ c.fachada((xl, z2), (-4.5, z2), (4.0, 10.0, 15.0))
+ c.fachada((4.5, z2), (xr, z2), (3.0, 8.0))
+ for x in (-4.5, 4.5):
+ c.esquina(x, z2)
+ c.seg((x, 0, z2), (x, 0, 90))
+ c.esquina(xl, z1); c.esquina(xr, z1); c.esquina(xl, z2); c.esquina(xr, z2)
+ for x, z in ((-8, 13.5), (8, 13.5), (-8, 22.5), (8, 22.5)):
+ c.farola(x, z)
+ c.cerrar()
+ c.tienda(-19.5, 12.5, "#14965a")
+ c.tienda(-16.0, 21.0, "#f2b705")
+ c.tienda(13.0, 12.8, "#3b5bdb")
+ c.tienda(13.5, 20.0, "#8e44c9")
+ zona = lambda X, Z: (KI - 1.4 < X < KD - .3 and Z < z1) or (xl + .8 < X < xr - .8 and z1 + .5 < Z < z2 - .5) or (abs(X) < 4 and Z >= z2)
+ c.gente((-1.0, 16.0, 3.4, 2.8, 4200, 3.4),
+ [llegan(FA + .5, 4.75, LUCHAS[0], 6), llegan(-60, 17.5, EJES[1], 14),
+ llegan(-.3, 60, EJES[3], 12), llegan(xr - 1, 16, EJES[2], 6), llegan(.3, 3.2, EJES[0], 9)],
+ zona=zona, ejes=EJES, puños=.14, zmax=80)
+ return c
+
+
+def b6():
+ # La plaza: de frente, fachadas en U y la gente llenándola
+ random.seed(21)
+ c = Escena(VX=800, VY=120, EYE=6.0, F=560, Y0=80)
+ zf, xl, xr = 26.0, -15.0, 15.0
+ c.abrir("lados", "arriba")
+ c.fachada((xl, 3.0), (xl, zf), (5.0, 10.0, 15.0))
+ c.fachada((xr, zf), (xr, 3.0), (4.0, 9.0, 14.0))
+ c.fachada((xl, zf), (-4.0, zf), (2.0, 6.0))
+ c.fachada((4.0, zf), (xr, zf), (2.5, 6.5))
+ for x in (-4.0, 4.0):
+ c.esquina(x, zf)
+ c.seg((x, 0, zf), (x, 0, 70))
+ c.esquina(xl, zf); c.esquina(xr, zf)
+ for x in (-10.0, 10.0):
+ c.farola(x, 9.0); c.farola(x, 20.0)
+ c.cerrar()
+ c.gente((0, 15, 3.2, 2.6, 3500, 3.0),
+ [llegan(0, 40, LUCHAS[0], 10), llegan(xl + .6, 8.0, LUCHAS[1], 5), llegan(xr - .6, 7.0, LUCHAS[3], 5)],
+ zona=lambda X, Z: xl + .8 < X < xr - .8 and Z < zf - .5 or abs(X) < 3.5, ejes=EJES, puños=.15)
+ return c
+
+
+def b7():
+ # Dos calles que se cruzan en X: de cada esquina llega un eje con su color
+ random.seed(22)
+ c = Escena(VX=800, VY=110, EYE=7.0, F=560, Y0=80)
+ cz, a = 16.0, 4.5
+ r = math.sqrt(.5)
+
+ def W(u, v):
+ return ((u - v) * r, (u + v) * r + cz)
+ c.abrir("lados", "arriba")
+ for su in (-1, 1):
+ for sv in (-1, 1):
+ p0 = W(su * a, sv * a)
+ pu = W(su * 60, sv * a)
+ pv = W(su * a, sv * 60)
+ c.esquina(*p0)
+ for q in (pu, pv):
+ c.seg((p0[0], 0, p0[1]), (q[0], 0, q[1]))
+ for d in (6.0, 12.0):
+ for (u, v) in ((su * (a + d), sv * a), (su * a, sv * (a + d))):
+ x, z = W(u, v)
+ x2, z2 = W(u + su * 1.5 * (v == sv * a), v + sv * 1.5 * (u == su * a))
+ c.portal((x, z), (x2, z2))
+ for k in range(-8, 9, 3):
+ for u, v in ((k, 0), (0, k)):
+ if abs(k) > a + 1:
+ p, q = W(u, v), W(u + (1.6 if v == 0 else 0), v + (1.6 if u == 0 else 0))
+ c.seg((p[0], 0, p[1]), (q[0], 0, q[1]), None, .7)
+ c.cerrar()
+ llegadas = []
+ for (u, v), col in zip(((-30, 0), (30, 0), (0, -9), (0, 30)), EJES):
+ x, z = W(u, v)
+ llegadas.append(llegan(x, z, col, 12))
+ zona = lambda X, Z: abs((X / r + (Z - cz) / r) / 2) < a - .3 or abs(((Z - cz) / r - X / r) / 2) < a - .3
+ c.gente((0, cz, 1.8, 1.8, 2500, 2.6), llegadas, zona=zona, puños=.15)
+ return c
+
+
+def b8():
+ # La acampada: tiendas de colores en la plaza y la asamblea en el centro
+ random.seed(23)
+ c = Escena(VX=800, VY=120, EYE=6.5, F=560, Y0=80)
+ zf, xl, xr = 28.0, -16.0, 16.0
+ c.abrir("lados", "arriba")
+ c.fachada((xl, 3.0), (xl, zf), (6.0, 12.0, 18.0))
+ c.fachada((xr, zf), (xr, 3.0), (5.0, 11.0, 17.0))
+ c.fachada((xl, zf), (xr, zf), (4.0, 9.0, 14.0, 19.5, 25.0))
+ c.esquina(xl, zf); c.esquina(xr, zf)
+ c.farola(-6, 10); c.farola(6, 10); c.farola(0, 24)
+ c.cerrar()
+ random.seed(230)
+ tiendas = []
+ for fila, z in enumerate((10.5, 13.0, 22.0, 24.8)):
+ for x in range(-13, 14, 4):
+ if abs(x) > 5 or z > 20:
+ tiendas.append((x + random.uniform(-.6, .6) + (fila % 2) * 2, z + random.uniform(-.4, .4)))
+ for k, (x, z) in enumerate(sorted(tiendas, key=lambda t: -t[1])):
+ c.tienda(x, z, EJES[k % len(EJES)])
+ lejos = lambda X, Z: all(math.hypot(X - x, Z - (z + 1.1)) > 1.6 for x, z in tiendas)
+ c.gente((0, 17, 2.6, 1.8, 3000, 2.6), [], zona=lambda X, Z: xl < X < xr and Z < zf - .5 and lejos(X, Z), ejes=EJES, puños=.2)
+ return c
+
+
+def b9():
+ # Sol: cinco calles llegan a la misma plaza, cada una con su reguero
+ random.seed(24)
+ c = Escena(VX=800, VY=120, EYE=8.0, F=560, Y0=80)
+ cz, R = 22.0, 11.0
+ angs = [-70, -35, 0, 35, 70]
+ c.abrir("lados", "arriba")
+ pts = []
+ for k in range(-90, 91, 6):
+ t = math.radians(k)
+ pts.append((R * math.sin(t), cz + R * math.cos(t) * .9))
+ huecos = [math.radians(a) for a in angs]
+ tramo = []
+ for k, (x, z) in zip(range(-90, 91, 6), pts):
+ dentro = any(abs(math.radians(k) - h) < math.radians(8) for h in huecos)
+ if dentro:
+ if len(tramo) > 1:
+ s0 = [(px, 0, pz) for px, pz in tramo]
+ c.poli(s0)
+ tramo = []
+ else:
+ tramo.append((x, z))
+ if len(tramo) > 1:
+ c.poli([(px, 0, pz) for px, pz in tramo])
+ for h in huecos:
+ for d in (-1, 1):
+ t = h + d * math.radians(8)
+ x0, z0 = R * math.sin(t), cz + R * math.cos(t) * .9
+ x1, z1 = x0 + math.sin(h) * 40, z0 + math.cos(h) * 40
+ c.esquina(x0, z0)
+ c.seg((x0, 0, z0), (x1, 0, z1))
+ c.seg((-R, 0, cz), (-R, 0, 4)); c.seg((R, 0, cz), (R, 0, 4))
+ c.farola(0, cz - 3)
+ c.cerrar()
+ llegadas = [llegan(math.sin(math.radians(a)) * (R + 14), cz + math.cos(math.radians(a)) * (R + 14) * .9, col, 10)
+ for a, col in zip(angs, EJES)]
+ c.gente((0, cz - 1, 2.8, 2.6, 3500, 3.0), llegadas, zona=lambda X, Z: math.hypot(X, (Z - cz) / .9) < R - .6 or Z < cz, ejes=EJES, puños=.15, zmax=60)
+ return c
+
+
+def b10():
+ # Desde el balcón: la plaza vista desde arriba, la piña como una hoguera de gente
+ random.seed(25)
+ c = Escena(VX=800, VY=40, EYE=16.0, F=520, Y0=100)
+ zf, xl, xr = 34.0, -18.0, 18.0
+ c.abrir("lados")
+ c.fachada((xl, 8.0), (xl, zf), (8.0, 16.0))
+ c.fachada((xr, zf), (xr, 8.0), (6.0, 14.0))
+ c.fachada((xl, zf), (-4.0, zf), (3.0, 9.0))
+ c.fachada((4.0, zf), (xr, zf), (3.0, 9.0))
+ for x in (-4.0, 4.0):
+ c.seg((x, 0, zf), (x, 0, 80))
+ for x, z in ((-12, 14), (12, 14), (-12, 28), (12, 28)):
+ c.farola(x, z)
+ c.cerrar()
+ c.gente((0, 21, 3.6, 3.2, 4500, 3.8),
+ [llegan(0, 60, EJES[3], 12), llegan(xl + .6, 12, EJES[1], 6), llegan(xr - .6, 30, EJES[2], 6)],
+ zona=lambda X, Z: (xl + .8 < X < xr - .8 and Z < zf - .5) or abs(X) < 3.5, ejes=EJES, puños=.12, zmax=70)
+ return c
+
+
+if __name__ == "__main__":
+ salidas = sys.argv[1:]
+ bocetos = salidas.pop(0)
+ os.makedirs(bocetos, exist_ok=True)
+ for n, f in zip(range(6, 11), [b6, b7, b8, b9, b10]):
+ open(f"{bocetos}/boceto-{n}.svg", "w").write(f().svg())
+ p = portada().svg()
+ for ruta in salidas:
+ open(ruta, "w").write(p)