"""2026-05-07
Counting 01
Grade com polígonos regulares a partir de 3 lados.
ericof.com|https://ericof.com/en/sketches/2023-11-06
png
Sketch,py5,CreativeCoding,Poligonos
"""
from sketches.utils.draw import canvas
from sketches.utils.draw.formas import _gera_forma
from sketches.utils.draw.grade import cria_grade
from sketches.utils.helpers import sketches as helpers
import py5
sketch = helpers.info_for_sketch(__file__, __doc__)
cor_fundo = py5.color(0)
celula_x = 100
m_celula_x = celula_x / 2
celula_y = 100
m_celula_y = celula_y / 2
GRADE = cria_grade(*helpers.DIMENSOES.internal, 0, 0, celula_x, celula_y, False)
FORMAS: dict[int, py5.Py5Shape] = {}
total_celulas = len(GRADE)
lado_min = 3
lado_max = lado_min + total_celulas
mult = 0.75
def calcula_cor(lado: int, total_células: int) -> list[int]:
"""Gera ``lado`` variações da mesma cor base, alterando S e B.
A cor base é derivada do número de lados via módulos coprimos,
garantindo distribuição diversa em faixa cromática vibrante
(sem extremos brancos ou pretos):
- ``h = (lado · 36) mod 360`` — matiz que percorre o círculo
cromático completo a cada 10 incrementos de lados;
- ``s_base = 60 + (lado · 7) mod 41`` — saturação base em
``[60, 100]``;
- ``b_base = 50 + (lado · 11) mod 41`` — brilho base em
``[50, 90]``.
Os multiplicadores 7 e 11 e o módulo 41 são coprimos entre si e
com 36, evitando bandas onde matiz, saturação e brilho coincidam
ciclicamente.
Para cada índice ``i`` em ``[0, lado)``, S e B recebem um
deslocamento normalizado por ``lado`` (``delta_norm = (i -
(lado-1)/2) / lado``, sempre em ``[-0.5, +0.5]``), com ganho
``±15`` em S e ``∓10`` em B — produzindo o mesmo "spread"
visual independentemente do número de lados. O resultado é uma
sequência monocromática progressiva, adequada para aplicar como
``set_fills`` em um shape de ``lado`` vértices.
:param lado: número de lados do polígono (também o tamanho da
lista retornada).
:returns: lista de ``lado`` valores ``py5.color`` com matiz
comum e variações progressivas de saturação e brilho.
"""
passo = 360 / total_células
h = (lado * passo) % 360
s_base = 60 + (lado * 7) % 41
b_base = 50 + (lado * 11) % 41
cores: list[int] = []
for i in range(lado):
delta_norm = (i - (lado - 1) / 2) / lado
s = s_base + delta_norm * 30
b = b_base - delta_norm * 20
cores.append(py5.color(h, s, b))
return cores
def setup():
py5.size(*helpers.DIMENSOES.external, py5.P3D)
py5.rect_mode(py5.CORNERS)
py5.shape_mode(py5.CORNERS)
py5.color_mode(py5.HSB, 360, 100, 100)
for lados in range(lado_min, lado_max):
forma = _gera_forma(lados)
rotacao = float(py5.radians(360 / lados / 2))
forma.set_fills(calcula_cor(lados, total_celulas))
forma.rotate(rotacao)
FORMAS[lados] = forma
def draw():
py5.background(cor_fundo)
with py5.push():
py5.translate(*helpers.DIMENSOES.pos_interno)
for idx, (x, y) in enumerate(GRADE, start=lado_min):
xb, yb = x, y
with py5.push():
py5.no_fill()
py5.stroke("#FFFFFF")
py5.stroke_weight(3)
py5.rect(x, y, x + celula_x, y + celula_y)
forma = FORMAS[idx]
x += m_celula_x
y += m_celula_y / 4
py5.shape(forma, x, y, x + celula_x * mult, y + celula_y * mult)
with py5.push():
py5.fill("#FFFFFF")
py5.text_size(15)
py5.text_align(py5.CORNER, py5.CORNER)
py5.text(f"{idx}", xb + 5, yb + 5 + m_celula_y / 4)
# Credits and go
canvas.sketch_frame(
sketch,
cor_fundo,
"large_transparent_white",
"transparent_white",
version=2,
)
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()