"""2024-04-02
Waves VI
Série de ondas, em tons de verde, criadas com funções trigonométricas.
png
Sketch,py5,CreativeCoding,waves
"""
from collections import defaultdict
from typing import List, Tuple
import numpy as np
import py5
from utils import helpers
sketch = helpers.info_for_sketch(__file__, __doc__)
MARGEM_X = 280
MARGEM_Y = 180
def calcula_circulo(
largura: int, altura: int, margem_x: int, margem_y: int
) -> List[Tuple[float, float]]:
"""Calcula circulo que toque as margens."""
raio_x = (largura - (2 * margem_x)) / 2
raio_y = (altura - (2 * margem_y)) / 2
x0 = margem_x + raio_x
y0 = margem_y + raio_y
pontos = []
for angulo in range(0, 360):
angulo_radianos = py5.radians(angulo)
x = x0 + (py5.cos(angulo_radianos) * raio_x)
y = y0 + (py5.sin(angulo_radianos) * raio_y)
pontos.append((x, y))
return pontos
def desenha_borda(h: int, margem_y: int) -> dict:
"""Desenha a borda para o sketch e retorna os limites para y."""
circulo = calcula_circulo(py5.width, py5.height, MARGEM_X, MARGEM_Y)
pontos_y = defaultdict(set)
with py5.push_style():
py5.stroke_weight(6)
py5.stroke(h, 60, 60)
for x, y in circulo:
py5.point(x, y)
pontos_y[int(y)].add(x)
limites = {k: (min(v), max(v)) for k, v in pontos_y.items()}
ymin = margem_y
ymax = py5.height - margem_y
for y in range(ymin, ymax + 1):
limites_y = limites.get(y)
if limites_y:
continue
for diff in (0, -1, 1, -2, 2, -3, 3):
limites_y = limites[y + diff] if y + diff in limites else None
if limites_y:
limites[y] = limites_y
break
return limites
def setup():
py5.size(helpers.LARGURA, helpers.ALTURA, py5.P3D)
py5.background(252, 249, 230)
py5.color_mode(py5.HSB, 360, 100, 100)
py5.no_fill()
py5.stroke_weight(2)
h = 160
limites_y = desenha_borda(h, MARGEM_Y)
passos = 40
lx = py5.width
ly = py5.height
x = np.linspace(0, lx, endpoint=False, num=lx)
y = np.linspace(10, ly, endpoint=False, num=passos)
base_multi = np.logspace(0.4, 1.6, num=int(passos / 2), endpoint=False)
multiplicadores = sorted(base_multi) + sorted(base_multi, reverse=True)
pesos = np.linspace(4, 2, num=passos, endpoint=False)
y = zip(y, multiplicadores, pesos)
for yb, mult_b, peso in y:
y0 = None
ybi = int(yb)
limites = limites_y.get(ybi, [py5.width + 100, py5.width + 100])
xi = limites[0]
x0 = xi
xf = limites[1]
py5.stroke_weight(peso)
s = py5.remap(mult_b, 0, 40, 60, 100)
for x1 in x:
if x1 >= xi and x1 <= xf:
x0 = xf
continue
xd = py5.remap(x1, 0, 800, -60, 60)
mult = mult_b * py5.cos(py5.radians(xd))
y1 = yb + (
mult * (abs(py5.cos(py5.radians(x0 + (4.1 * yb))) * py5.sin(1.4 * x1)))
)
b = py5.remap(xd, -60, 60, 80, 60)
py5.stroke(h, s, b)
if y0 is None:
y0 = y1
py5.line(x0, y0, x1, y1)
x0, y0 = x1, y1
helpers.write_legend(sketch=sketch, cor=py5.color(h, s, b))
def key_pressed():
key = py5.key
if key == " ":
save_and_close()
def save_and_close():
py5.no_loop()
helpers.save_sketch_image(sketch)
py5.exit_sketch()
if __name__ == "__main__":
py5.run_sketch()