SP, 472 years

2026-01-25

"""2026-01-25
SP, 472 years
Homenagem aos 472 anos da cidade de São Paulo.
ericof.com
png
Sketch,py5,CreativeCoding
"""

from pathlib import Path
from PIL import Image
from sketches.utils.draw import canvas
from sketches.utils.draw.cores.paletas import gera_paleta
from sketches.utils.helpers import sketches as helpers
from sketches.utils.helpers.recursos import caminho_arquivo

import numpy as np
import py5


sketch = helpers.info_for_sketch(__file__, __doc__)


def carregar_mascara(imagem: Path, escala: float = 1):
    """Carrega imagem e retorna a máscara."""
    img = Image.open(imagem)
    img_ = np.array(img.getdata()).reshape(img.height, img.width, 4)
    mask = []
    for y in img_:
        for x in y:
            mask.append(x[3])
    img_ = np.array(mask).reshape(img.height, img.width).transpose()
    return img_


def dentro_mascara(x: float, y: float, mascara: np.array, centrado: bool = True):
    if centrado:
        x += helpers.DIMENSOES.internal[0] // 2
        y += helpers.DIMENSOES.internal[1] // 2
    x = int(x)
    y = int(y)
    try:
        dentro = bool(mascara[x][y])
    except IndexError:
        dentro = False
    return dentro


def pinta_mascara(mascara: np.array, cor: str):
    with py5.push():
        py5.stroke(cor)
        py5.stroke_weight(2)
        for x in range(0, py5.width):
            for y in range(0, py5.height):
                if dentro_mascara(x, y, mascara, True):
                    py5.point(x, y)


def setup():
    py5.size(*helpers.DIMENSOES.external, py5.P3D)
    cor_fundo = py5.color(0)
    with py5.push():
        py5.background("#222222")
        paleta = gera_paleta("south-africa", True)
        py5.rect_mode(py5.CORNERS)
        py5.stroke_weight(2)
        py5.no_fill()
        caminho = caminho_arquivo("sampa.png")
        mascara = carregar_mascara(caminho)
        passos = 80
        lx = helpers.DIMENSOES.internal[0] // 2
        ly = helpers.DIMENSOES.internal[1] // 2
        x = np.linspace(-lx, lx, endpoint=False, num=helpers.DIMENSOES.internal[0])
        y = np.linspace(-ly, ly + 40, endpoint=True, num=passos)
        multiplicadores = np.logspace(0.9, 1.5, num=passos // 2, endpoint=False)
        multiplicadores = sorted(multiplicadores) + sorted(
            multiplicadores, reverse=True
        )
        pesos = np.linspace(1.2, 2.4, num=passos // 2, endpoint=False)
        pesos = sorted(pesos) + sorted(pesos, reverse=True)
        y = zip(y, multiplicadores, pesos, strict=False)
        pinta_mascara(mascara=mascara, cor="#FCF9E6")
        with py5.push():
            py5.translate(*helpers.DIMENSOES.centro, -20)
            for yb, mult_b, peso in y:
                y0 = None
                x0 = 0
                for idx, x1 in enumerate(x):
                    xd = py5.remap(x1, -lx, lx, -100, 120)
                    mult = mult_b * py5.sin(py5.radians(xd))
                    yd = mult * (
                        abs(
                            py5.sin(py5.radians(x0 + (2 * yb)))
                            * py5.sin(py5.radians(x1 + yb))
                            * py5.sin(py5.radians(x0))
                        )
                    )
                    y1 = yb + yd if (idx % 2) else yb - yd

                    if y0 is None:
                        y0 = y1
                    py5.stroke(paleta[0])
                    py5.stroke_weight(peso)
                    if dentro_mascara(x0, y0, mascara):
                        py5.stroke(paleta[-1])
                        py5.line(x0, y0, x1, y1)
                    else:
                        py5.stroke_weight(1)
                        py5.circle(x1, y1, peso)
                    x0, y0 = x1, y1
                paleta.rotate(1)

    # Credits and go
    canvas.sketch_frame(
        sketch, cor_fundo, "large_transparent_white", "transparent_white"
    )


def key_pressed():
    key = py5.key
    if key == " ":
        save_and_close()


def save_and_close():
    py5.no_loop()
    canvas.save_sketch_image(sketch)
    py5.exit_sketch()


if __name__ == "__main__":
    py5.run_sketch()