diff --git a/dataset/scenarios/scenario1.py b/dataset/scenarios/scenario1.py new file mode 100644 index 0000000..52c7ca6 --- /dev/null +++ b/dataset/scenarios/scenario1.py @@ -0,0 +1,96 @@ +import pygame +import pymunk +import pymunk.pygame_util +import cv2 +import datetime +import os + +def setup_pygame(): + """Inicializa o Pygame e a tela.""" + pygame.init() + screen = pygame.display.set_mode((800, 600)) + pygame.display.set_caption("Cenario 1") + return screen, pygame.time.Clock() + +def create_scenario(space): + """Cria o chão estático do cenário.""" + body_chao = pymunk.Body(body_type=pymunk.Body.STATIC) + segment_chao = pymunk.Segment(body_chao, (0, 550), (800, 550), 5) + segment_chao.elasticity = 0.9 + segment_chao.friction = 1.0 + space.add(body_chao, segment_chao) + +def add_ball_at_mouse_position(space, pos): + """Adiciona uma nova bola no espaço, na posição do mouse.""" + massa = 1 + raio = 15 + inercia = pymunk.moment_for_circle(massa, 0, raio) + bola_body = pymunk.Body(massa, inercia) + bola_body.position = pos + bola_shape = pymunk.Circle(bola_body, raio) + bola_shape.elasticity = 0.9 + bola_shape.friction = 0.8 + space.add(bola_body, bola_shape) + +def run_simulation_and_record(): + """Roda a simulação e grava um vídeo.""" + screen, clock = setup_pygame() + + # Gerar um nome de arquivo unico com data e hora + timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + video_filename = f"cenario1:{timestamp}.mp4" + + # Salva o vídeo na pasta 'videos', um nivel acima da atual + video_path = os.path.join(os.path.dirname(__file__), '..', 'videos', video_filename) + + FPS = 60 + fourcc = cv2.VideoWriter_fourcc(*'mp4v') + out = cv2.VideoWriter(video_path, fourcc, FPS, (800, 600)) + + # Configurar o espaço do Pymunk + space = pymunk.Space() + space.gravity = 0, 980 + draw_options = pymunk.pygame_util.DrawOptions(screen) + + # Criar o cenário (o chão) + create_scenario(space) + + running = True + while running: + # Gerenciamento de eventos + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.MOUSEBUTTONDOWN: + if event.button == 1: + # Ao clicar, adiciona uma bola + add_ball_at_mouse_position(space, event.pos) + + # Limpar a tela + screen.fill((255, 255, 255)) + + # Desenhar os objetos do Pymunk + space.debug_draw(draw_options) + + # Atualizar a simulação + space.step(1 / 60.0) + + # Atualizar a tela do Pygame + pygame.display.flip() + + # Gravar o quadro atual para o vídeo + img_array = pygame.surfarray.array3d(screen) + img_array = cv2.cvtColor(img_array.swapaxes(0, 1), cv2.COLOR_RGB2BGR) + out.write(img_array) + + # Controlar o FPS + clock.tick(60) + + # Liberar o gravador e fechar o Pygame + out.release() + pygame.quit() + print(f"Vídeo salvo como {video_path}") + +# Executar a simulação e a gravação +if __name__ == "__main__": + run_simulation_and_record() \ No newline at end of file diff --git a/dataset/scenarios/scenario2.py b/dataset/scenarios/scenario2.py new file mode 100644 index 0000000..e79eda7 --- /dev/null +++ b/dataset/scenarios/scenario2.py @@ -0,0 +1,136 @@ +import pygame +import pymunk +import pymunk.pygame_util +import cv2 +import numpy as np +import datetime +import os + +def setup_pygame(): + """Inicializa o Pygame e a tela.""" + pygame.init() + screen = pygame.display.set_mode((800, 600)) + pygame.display.set_caption("Cenario 2") + return screen, pygame.time.Clock() + +def add_ball(space, pos): + """Adiciona uma nova bola no espaco.""" + massa = 1 + raio = 15 + inercia = pymunk.moment_for_circle(massa, 0, raio) + bola_body = pymunk.Body(massa, inercia) + bola_body.position = pos + bola_shape = pymunk.Circle(bola_body, raio) + bola_shape.elasticity = 0.9 + bola_shape.friction = 0.8 + space.add(bola_body, bola_shape) + +def add_box(space, pos): + """Adiciona uma nova caixa no espaco.""" + massa = 1 + size = 30 + inercia = pymunk.moment_for_box(massa, (size, size)) + caixa_body = pymunk.Body(massa, inercia) + caixa_body.position = pos + caixa_shape = pymunk.Poly.create_box(caixa_body, (size, size)) + caixa_shape.elasticity = 0.5 + caixa_shape.friction = 0.7 + space.add(caixa_body, caixa_shape) + +def create_static_segment(space, points): + """Cria uma superficie estatica a partir de uma lista de pontos.""" + if len(points) < 2: + return + + for i in range(len(points) - 1): + p1 = points[i] + p2 = points[i+1] + static_body = pymunk.Body(body_type=pymunk.Body.STATIC) + segment = pymunk.Segment(static_body, p1, p2, 5) + segment.elasticity = 0.95 + segment.friction = 0.8 + space.add(static_body, segment) + +# --- Loop Principal de Simulação e Gravação --- +def run_simulation_and_record(): + """Roda a simulação e grava um vídeo.""" + screen, clock = setup_pygame() + + timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + video_filename = f"cenario2:{timestamp}.mp4" + video_path = os.path.join(os.path.dirname(__file__), '..', 'videos', video_filename) + + FPS = 60 + fourcc = cv2.VideoWriter_fourcc(*'mp4v') + out = cv2.VideoWriter(video_path, fourcc, FPS, (800, 600)) + + space = pymunk.Space() + space.gravity = 0, 980 + draw_options = pymunk.pygame_util.DrawOptions(screen) + + drawing_mode = False + drawing_points = [] + current_object_type = 'ball' + + running = True + while running: + # Gerenciamento de eventos + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.MOUSEBUTTONDOWN: + if event.button == 1: + if current_object_type == 'ball': + add_ball(space, event.pos) + elif current_object_type == 'box': + add_box(space, event.pos) + elif event.button == 3: + drawing_mode = True + drawing_points.append(event.pos) + elif event.type == pygame.MOUSEBUTTONUP: + if event.button == 3: + drawing_mode = False + if len(drawing_points) > 1: + create_static_segment(space, drawing_points) + drawing_points = [] + elif event.type == pygame.MOUSEMOTION: + if drawing_mode: + drawing_points.append(event.pos) + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_b: + current_object_type = 'ball' + elif event.key == pygame.K_q: + current_object_type = 'box' + + # Adiciona multiplos objetos + mouse_buttons = pygame.mouse.get_pressed() + keys = pygame.key.get_mods() + if mouse_buttons[0] and keys & pygame.KMOD_SHIFT: + if current_object_type == 'ball': + add_ball(space, pygame.mouse.get_pos()) + elif current_object_type == 'box': + add_box(space, pygame.mouse.get_pos()) + + # Limpar a tela + screen.fill((255, 255, 255)) + + if drawing_mode and len(drawing_points) > 1: + pygame.draw.lines(screen, (0, 0, 0), False, drawing_points, 2) + + space.debug_draw(draw_options) + space.step(1 / 60.0) + + pygame.display.flip() + + img_array = pygame.surfarray.array3d(screen) + img_array = cv2.cvtColor(img_array.swapaxes(0, 1), cv2.COLOR_RGB2BGR) + out.write(img_array) + + clock.tick(60) + + out.release() + pygame.quit() + print(f"Vídeo salvo como {video_path}") + +if __name__ == "__main__": + run_simulation_and_record() \ No newline at end of file diff --git a/dataset/scenarios/scenarios.md b/dataset/scenarios/scenarios.md new file mode 100644 index 0000000..a187673 --- /dev/null +++ b/dataset/scenarios/scenarios.md @@ -0,0 +1,67 @@ +# Cenários para criação do dataset + +## Cenário 1: Bola e chão + +> Esse cenário foca em testar colisões, gravidade e perda de energia. Ele foi projetado para ser interativo, proporcionando uma variedade de possibilidades de simulação. + +### 1. Objetivos + +- Verificar o comportamento de objetos em queda livre. + +- Testar a colisão com uma superfície estática (chão) e com outros objetos (bolas dinâmicamente inseridas) + +- Analisar o quique e a perda de energia (elasticidade). + +### 1. Objetos + +1. **Chão (Objeto estático)**: O chão é a única superfície estática do cenário, agindo como a principal barreira de colisão. Sua elasticidade e fricção podem ser alteradas em código para simular diferentes superfícies. + +2. **Bolas (Objetos dinâmicos)**: As bolas são os objetos dinâmicos do cenário, e podem ser criadas com um clique do mouse esquerdo. Sua massa, raio, elasticidade e fricção podem ser alterados em código. Além de colidirem com o chão, as bolas podem colidir entre si, o que permite a análise de colisões entre corpos dinâmicos e reações em cadeia. + +### 1. Interação com o usuário + +A principal forma de interação com o usuário é por meio da adição de bolas usando o mouse. Essa interação permite fazer várias aplicações do mesmo cenário, contribuindo para a geração de um dataset mais diversificado. Clicando com o botão esquerdo do mouse, será adicionada uma nova bola na posição que o mouse se encontra. + +### 1. Saída em forma de vídeo + +Dado que o objetivo dos cenários é criar um dataset, a simulação foi configurada para gravar um vídeo, desde o início até o momento em que a janela é fechada. O vídeo é salvo automaticamente com o nome `cenario1: data`, em que a "data" se refere ao dia e horário que a simulação foi salva. A simulação é salva na pasta `videos` em formato .mp4 + +### 1. Conclusão + +A diversidade do dataset pode ser alcaçada ao juntar a interação com o usuário mencionada e a alteração dos objetos da simulação. Dessa forma, esse cenário é uma forma flexível de testar colisões simples, gravidade e perda de energia. + +## Cenário 2: Bolas e obstáculos + +> Esse cenário foca em testar a interação entre múltiplos objetos e colisões com superfícies mais complexas e dinâmicas, que podem ser criadas pelo próprio usuário. + +### 2. Objetivos + +- Testar a física de colisão em superfícies não-planas (como rampas e curvas) + +- Analisar a interação entre diferentes formas de objetos (círculos e quadrados). + +- Avaliar a dinâmica de empilhamento e dispersão de um grande número de objetos. + +### 2. Objetos + +1. Obstáculos e Superfícies (Objetos Estáticos): Dessa vez, as superfícies estáticas são definidas diretamente pelo usuário, e atuam como paredes e obstáculos, com propriedades de elasticidade e fricção ajustáveis. + +2. Bolas e quadrados (Objetos Dinâmicos): O cenário agora suporta dois tipos de formas dinâmicas, que podem ser alternadas pelo usuário. A adição dos quadrados proporciona uma interação mais complexa, podendo deslizar ou tombar ao interagir com os obstáculos. + +### 2. Interação com o usuário + +A interação com o usuário é mais presente nesse cenário. Nele, podemos realizar: + +- Desenho Livre: Clique e arraste o botão direito do mouse para desenhar superfícies estáticas livres. Ao soltar o botão, o desenho é finalizado e se torna uma barreira de colisão. + +- Criar objetos: pressione `b` para selecionar o modo "bolas" ou `q` para selecionar o modo "quadrados". Apertar o botão esquerdo do mouse cria um objeto selecionado novo. + +- Criação em massa: Segurar o botão `Shift` enquanto aperta o botão esquerdo do mouse cria múltiplos objetos simultaneamente. + +### 2. Saída em forma de vídeo + +Novamente, a saída é salva em formato de vídeo com o dia e horario da simulação, e fica armazenado na pasta `videos` sob o formato .mp4 + +### 2. Conclusão + +A adição de obstáculos dinâmicos determinados pelo usuário, a funcionalidade de criação em massa e a possibilidade de simular mais uma forma geométrica contribuem para a flexibilidade do cenário, o que ajudará na criação do dataset futuramente. diff --git a/dataset/videos/cenario1:2025-09-14_14-32-13.mp4 b/dataset/videos/cenario1:2025-09-14_14-32-13.mp4 new file mode 100644 index 0000000..4f707f4 Binary files /dev/null and b/dataset/videos/cenario1:2025-09-14_14-32-13.mp4 differ diff --git a/dataset/videos/cenario2:2025-09-14_14-46-55.mp4 b/dataset/videos/cenario2:2025-09-14_14-46-55.mp4 new file mode 100644 index 0000000..8245f41 Binary files /dev/null and b/dataset/videos/cenario2:2025-09-14_14-46-55.mp4 differ