Skip to content

Instantly share code, notes, and snippets.

@senapk
Last active July 19, 2025 23:33
Show Gist options
  • Select an option

  • Save senapk/e18a2de83e7a5bbbf28b9f9822fb4cdb to your computer and use it in GitHub Desktop.

Select an option

Save senapk/e18a2de83e7a5bbbf28b9f9822fb4cdb to your computer and use it in GitHub Desktop.
Gerador de porcentagens em cores no quadrado
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.colors import ListedColormap
import numpy as np
from PIL import Image
import random
class Cat:
def __init__(self, qtd: int, value: int):
self.qtd = qtd
self.value = value
self.corner: tuple[int, int] = (0, 0) # Ponto de destino para alocação
self.sorted_points: list[Point] = [] # Lista de pontos ordenados para alocação
class Point:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
self.free = True # Indica se o ponto está livre para alocação
def __repr__(self):
return f"Point({self.x}, {self.y})"
def get_distance(p1: tuple[int, int], p2: tuple[int, int]) -> float:
"""Calcula a distância euclidiana entre dois pontos."""
return np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
def allocate_colors_to_grid(values: list[float], factorx: int, factory: int) -> list[list[int]]:
if len(values) != 4:
raise ValueError("Devem ser exatamente 4 categorias.")
DX = factorx
DY = factory
grid: list[list[int]] = [[-1 for _ in range(DX)] for _ in range(DY)]
available_cells: list[Point] = [Point(i, j) for i in range(DX) for j in range(DY)]
groups: list[Cat] = []
for i, value in enumerate(values):
qtd=int(value * DX * DY / 100)
cat: Cat = Cat(qtd=qtd, value=i)
groups.append(cat)
# groups[0].corner = (0, 0) # Superior esquerdo
# groups[1].corner = (0, DY - 1) # Superior direito
# groups[2].corner = (DX - 1, 0) # Inferior esquerdo
# groups[3].corner = (DX - 1, DY - 1) # Inferior direito
groups[0].corner = (random.randint(0, DX // 2), random.randint(0, DY // 2)) # Superior esquerdo
groups[1].corner = (random.randint(0, DX // 2), random.randint(DY // 2, DY)) # Superior direito
groups[2].corner = (random.randint(DX // 2, DX), random.randint(0, DY // 2)) # Inferior esquerdo
groups[3].corner = (random.randint(DX // 2, DX), random.randint(DY // 2, DY)) # Inferior direito
# groups[0].corner = (random.randint(0, DX), random.randint(0, DY)) # Superior esquerdo
# groups[1].corner = (random.randint(0, DX), random.randint(0, DY)) # Superior esquerdo
# groups[2].corner = (random.randint(0, DX), random.randint(0, DY)) # Superior esquerdo
# groups[3].corner = (random.randint(0, DX), random.randint(0, DY)) # Superior esquerdo
for i in range(4):
# Gerar pontos ordenados para cada grupo
cat = groups[i]
cat.sorted_points = sorted(available_cells, key=lambda p: get_distance(cat.corner, (p.x, p.y)), reverse=True)
while True:
empty = True
random.shuffle(groups)
for i in range(4):
if groups[i].qtd <= 0:
continue
# Encontrar a célula mais próxima do alvo
while groups[i].sorted_points[-1].free is False:
groups[i].sorted_points.pop()
chosen_point = groups[i].sorted_points[-1]
chosen_point.free = False
grid[chosen_point.y][chosen_point.x] = groups[i].value
groups[i].qtd -= 1
empty = False
if empty:
break
return grid
# def create_image_from_grid(grid: list[list[int]], colors: list[str], path_to_save: str):
# plt.imshow(grid, cmap=cmap)
# plt.axis('off') # Remove os eixos para uma imagem limpa
# plt.savefig(path_to_save, bbox_inches='tight', pad_inches=0)
# plt.close() # Fecha a figura para liberar memória
def create_image_from_grid(grid: list[list[int]], colors: list[str], path_to_save: str, scale: int = 1):
height = len(grid)
width = len(grid[0]) if height > 0 else 0
# Cria uma nova imagem RGB
img = Image.new('RGB', (width, height))
pixels = img.load()
# Preenche os pixels com base no grid e na paleta
for y in range(height):
for x in range(width):
color_hex = colors[grid[y][x]]
pixels[x, y] = tuple(int(color_hex[i:i+2], 16) for i in (1, 3, 5)) # de '#RRGGBB' para (R, G, B)
# Se quiser ampliar a imagem com antialiasing
if scale > 1:
img = img.resize((width * scale, height * scale), resample=Image.NEAREST)
img.save(path_to_save)
def main():
factorx = 60
factory = 100
# values: list[float] = [random.randint(1, 100), random.randint(1, 100), random.randint(1, 100), random.randint(1, 100)]
values: list[float] = [10, 20, 20, 5]
total = sum(values)
for i in range(len(values)):
values[i] = round(values[i] / total * 100)
values[0] += 100 - sum(values) # Ajusta o primeiro valor para garantir que a soma seja 100
print(f"Valores normalizados: {values}")
grid = allocate_colors_to_grid(values, factorx, factory)
blue = '#0000FF'
green = '#00FF00'
yellow = '#FFFF00'
red = '#FF0000'
create_image_from_grid(grid, [blue, green, yellow, red], 'grid_image.png', 3)
if __name__ == "__main__":
main()
@senapk
Copy link
Author

senapk commented Jul 19, 2025

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment