x2XcarleX2x commited on
Commit
f9704b1
·
verified ·
1 Parent(s): e2829c8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -50
app.py CHANGED
@@ -5,8 +5,6 @@ from mpl_toolkits.mplot3d import Axes3D
5
  from matplotlib.animation import FuncAnimation
6
  import math
7
  from scipy.special import comb
8
- import random
9
- import os
10
 
11
  # --- Funções Matemáticas (Inalteradas) ---
12
  def bernstein_poly(i, n, t):
@@ -25,49 +23,50 @@ def aprender_com_o_eco_3d(pontos_do_eco: list):
25
  p1, p2 = np.array(pontos_do_eco[0]), np.array(pontos_do_eco[-1])
26
  return {"velocity_vector": p2 - p1}
27
 
28
- # --- Função Principal do Gradio (O Estúdio da Jornada Contínua) ---
29
 
30
- def gerar_jornada_completa(angulo_camera: int, progress=gr.Progress(track_tqdm=True)):
31
  """
32
- Gera uma única trajetória contínua para 10 ciclos e a renderiza
33
- como um único vídeo animado.
34
  """
35
  NUM_CICLOS = 10
 
 
 
 
36
 
37
- # Listas para armazenar a jornada completa
38
  x_jornada_total, y_jornada_total, z_jornada_total = [], [], []
39
- checkpoints = []
40
-
41
- # Estado inicial da simulação
42
- estado = {
43
- "ponto_b": np.array([-40., 20., 10.]),
44
- "vetor_inercia": np.array([30., 10., -20.])
45
- }
46
- checkpoints.append(estado["ponto_b"])
47
 
48
- progress(0, desc="Calculando trajetória para 10 ciclos...")
49
- # --- 1. CALCULAR TUDO PRIMEIRO ---
50
  for i in range(NUM_CICLOS):
51
- ponto_a = estado["ponto_b"]
52
- vetor_inercia_anterior = estado["vetor_inercia"]
53
- ponto_b = np.random.rand(3) * 120 - 60
 
 
 
 
 
 
54
  checkpoints.append(ponto_b)
55
 
56
- ponto_controle = ponto_a + vetor_inercia_anterior
57
- pontos_curva = [ponto_a, ponto_controle, ponto_b]
58
- x_ciclo, y_ciclo, z_ciclo = bezier_curve_3d(pontos_curva)
 
 
59
 
60
  x_jornada_total.extend(x_ciclo); y_jornada_total.extend(y_ciclo); z_jornada_total.extend(z_ciclo)
61
 
62
  tamanho_eco = 20
63
  pontos_eco = list(zip(x_ciclo[-tamanho_eco:], y_ciclo[-tamanho_eco:], z_ciclo[-tamanho_eco:]))
64
- vetor_inercia_novo = aprender_com_o_eco_3d(pontos_eco)["velocity_vector"]
65
- estado = {"ponto_b": ponto_b, "vetor_inercia": vetor_inercia_novo}
66
 
67
  total_frames = len(x_jornada_total)
68
  progress(0.2, desc=f"Trajetória de {total_frames} vetores calculada. Iniciando renderização...")
69
-
70
- # --- 2. RENDERIZAÇÃO ÚNICA ---
71
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
72
  cor_fundo = '#0a0a0a'; fig.patch.set_facecolor(cor_fundo); ax.set_facecolor(cor_fundo)
73
  ax.xaxis.pane.fill = False; ax.yaxis.pane.fill = False; ax.zaxis.pane.fill = False
@@ -76,56 +75,61 @@ def gerar_jornada_completa(angulo_camera: int, progress=gr.Progress(track_tqdm=T
76
  ax.set_xlim(-70, 70); ax.set_ylim(-70, 70); ax.set_zlim(-70, 70)
77
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
78
 
79
- # Desenha todos os checkpoints
80
- checkpoints_np = np.array(checkpoints)
81
- ax.scatter(checkpoints_np[0,0], checkpoints_np[0,1], checkpoints_np[0,2], s=150, c='yellow', marker='X', alpha=0.9, label='')
82
- ax.scatter(checkpoints_np[1:,0], checkpoints_np[1:,1], checkpoints_np[1:,2], s=150, c='yellow', marker='X', alpha=0.9, label='')
83
-
84
  # Inicializa os elementos animados
85
- bola, = ax.plot([], [], [], 'o', color='#ff4500', markersize=8, markeredgecolor='white', linewidth=2)
86
  rastro, = ax.plot([], [], [], '-', color='#ff4500', linewidth=4, alpha=0.6)
 
 
87
  tamanho_rastro = 40
88
 
89
  def update(frame):
 
90
  bola.set_data_3d([x_jornada_total[frame]], [y_jornada_total[frame]], [z_jornada_total[frame]])
91
  start_index = max(0, frame - tamanho_rastro)
92
  rastro.set_data_3d(x_jornada_total[start_index:frame+1], y_jornada_total[start_index:frame+1], z_jornada_total[start_index:frame+1])
93
- return bola, rastro,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  # --- 3. UMA ÚNICA ANIMAÇÃO E UM ÚNICO VÍDEO ---
96
- ani = FuncAnimation(fig, update, frames=total_frames, interval=33, blit=True)
97
- video_final = "jornada_continua.mp4"
98
  ani.save(video_final, writer='ffmpeg', fps=30, dpi=120, progress_callback=lambda i, n: progress(0.2 + 0.8 * (i/n), desc=f"Renderizando vetor {i+1}/{n}"))
99
  plt.close(fig)
100
 
101
  return video_final
102
 
103
  # --- Interface Gradio (Inalterada) ---
104
-
105
- with gr.Blocks(theme=gr.themes.Base(primary_hue="orange")) as demo:
106
  gr.Markdown(
107
  """
108
- # 🎬 Estúdio da Jornada Contínua 3D
109
- Clique no botão para gerar uma **jornada ininterrupta de 10 ciclos**.
110
- O sistema irá calcular toda a trajetória e renderizá-la como um único vídeo, mostrando a continuidade do rastro da bola.
111
  """
112
  )
113
-
114
  with gr.Row():
115
  with gr.Column(scale=1):
116
  gr.Markdown("### 🎮 Controles")
117
  angulo_camera_slider = gr.Slider(-180, 180, value=30, label="Ângulo da Câmera (Fixo)")
118
- generate_btn = gr.Button("🚀 Gerar Jornada Completa", variant="primary")
119
-
120
  with gr.Column(scale=2):
121
  gr.Markdown("### 📽️ Vídeo Final")
122
  video_output = gr.Video(label="Animação da Jornada Contínua", autoplay=True)
123
-
124
- generate_btn.click(
125
- fn=gerar_jornada_completa,
126
- inputs=[angulo_camera_slider],
127
- outputs=[video_output]
128
- )
129
 
130
  if __name__ == "__main__":
131
  demo.launch()
 
5
  from matplotlib.animation import FuncAnimation
6
  import math
7
  from scipy.special import comb
 
 
8
 
9
  # --- Funções Matemáticas (Inalteradas) ---
10
  def bernstein_poly(i, n, t):
 
23
  p1, p2 = np.array(pontos_do_eco[0]), np.array(pontos_do_eco[-1])
24
  return {"velocity_vector": p2 - p1}
25
 
26
+ # --- Função Principal do Gradio (O Simulador Inteligente) ---
27
 
28
+ def gerar_simulacao_inteligente(angulo_camera: int, progress=gr.Progress(track_tqdm=True)):
29
  """
30
+ Gera uma jornada contínua com checkpoints dinâmicos e um loop perfeito.
 
31
  """
32
  NUM_CICLOS = 10
33
+ VETORES_POR_CICLO = 60
34
+
35
+ # --- 1. CALCULAR A JORNADA COMPLETA E OS CHECKPOINTS ---
36
+ progress(0, desc="Calculando trajetória completa para 10 ciclos...")
37
 
 
38
  x_jornada_total, y_jornada_total, z_jornada_total = [], [], []
39
+ checkpoints = [np.array([-40., 20., 10.])]
40
+ vetor_inercia = np.array([30., 10., -20.])
 
 
 
 
 
 
41
 
 
 
42
  for i in range(NUM_CICLOS):
43
+ ponto_a = checkpoints[-1]
44
+
45
+ # --- LÓGICA DO LOOP PERFEITO ---
46
+ if i < NUM_CICLOS - 1:
47
+ ponto_b = np.random.rand(3) * 120 - 60
48
+ else: # Último ciclo
49
+ ponto_b = checkpoints[0] # O alvo é o primeiro checkpoint
50
+ # -----------------------------
51
+
52
  checkpoints.append(ponto_b)
53
 
54
+ ponto_controle = ponto_a + vetor_inercia
55
+ # Para o loop final, adicionamos um ponto de controle extra para suavizar a chegada
56
+ pontos_curva = [ponto_a, ponto_controle, ponto_b] if i < NUM_CICLOS - 1 else [ponto_a, ponto_controle, checkpoints[1], ponto_b]
57
+
58
+ x_ciclo, y_ciclo, z_ciclo = bezier_curve_3d(pontos_curva, n_times=VETORES_POR_CICLO)
59
 
60
  x_jornada_total.extend(x_ciclo); y_jornada_total.extend(y_ciclo); z_jornada_total.extend(z_ciclo)
61
 
62
  tamanho_eco = 20
63
  pontos_eco = list(zip(x_ciclo[-tamanho_eco:], y_ciclo[-tamanho_eco:], z_ciclo[-tamanho_eco:]))
64
+ vetor_inercia = aprender_com_o_eco_3d(pontos_eco)["velocity_vector"]
 
65
 
66
  total_frames = len(x_jornada_total)
67
  progress(0.2, desc=f"Trajetória de {total_frames} vetores calculada. Iniciando renderização...")
68
+
69
+ # --- 2. RENDERIZAÇÃO INTELIGENTE ---
70
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
71
  cor_fundo = '#0a0a0a'; fig.patch.set_facecolor(cor_fundo); ax.set_facecolor(cor_fundo)
72
  ax.xaxis.pane.fill = False; ax.yaxis.pane.fill = False; ax.zaxis.pane.fill = False
 
75
  ax.set_xlim(-70, 70); ax.set_ylim(-70, 70); ax.set_zlim(-70, 70)
76
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
77
 
 
 
 
 
 
78
  # Inicializa os elementos animados
79
+ bola, = ax.plot([], [], [], 'o', color='#ff4500', markersize=8, markeredgecolor='white')
80
  rastro, = ax.plot([], [], [], '-', color='#ff4500', linewidth=4, alpha=0.6)
81
+ checkpoints_passados_scatter = ax.scatter([], [], [], s=150, c='lime', alpha=0.7)
82
+ proximo_checkpoint_scatter = ax.scatter([], [], [], s=150, c='red', marker='X', alpha=0.9)
83
  tamanho_rastro = 40
84
 
85
  def update(frame):
86
+ # Atualiza a bola e o rastro
87
  bola.set_data_3d([x_jornada_total[frame]], [y_jornada_total[frame]], [z_jornada_total[frame]])
88
  start_index = max(0, frame - tamanho_rastro)
89
  rastro.set_data_3d(x_jornada_total[start_index:frame+1], y_jornada_total[start_index:frame+1], z_jornada_total[start_index:frame+1])
90
+
91
+ # --- LÓGICA DOS CHECKPOINTS DINÂMICOS ---
92
+ ciclo_atual = frame // VETORES_POR_CICLO
93
+
94
+ # Mostra todos os checkpoints que já foram visitados (em verde)
95
+ pontos_passados = np.array(checkpoints[:ciclo_atual + 1])
96
+ checkpoints_passados_scatter._offsets3d = (pontos_passados[:,0], pontos_passados[:,1], pontos_passados[:,2])
97
+
98
+ # Mostra o próximo alvo (em vermelho), mas apenas se não for o último
99
+ if ciclo_atual + 1 < len(checkpoints):
100
+ proximo_ponto = checkpoints[ciclo_atual + 1]
101
+ proximo_checkpoint_scatter._offsets3d = ([proximo_ponto[0]], [proximo_ponto[1]], [proximo_ponto[2]])
102
+ else: # Se chegou no final, esconde o marcador de alvo
103
+ proximo_checkpoint_scatter._offsets3d = ([], [], [])
104
+
105
+ return bola, rastro, checkpoints_passados_scatter, proximo_checkpoint_scatter
106
 
107
  # --- 3. UMA ÚNICA ANIMAÇÃO E UM ÚNICO VÍDEO ---
108
+ ani = FuncAnimation(fig, update, frames=total_frames, interval=33, blit=False) # blit=False é mais robusto para 3D
109
+ video_final = "simulacao_inteligente.mp4"
110
  ani.save(video_final, writer='ffmpeg', fps=30, dpi=120, progress_callback=lambda i, n: progress(0.2 + 0.8 * (i/n), desc=f"Renderizando vetor {i+1}/{n}"))
111
  plt.close(fig)
112
 
113
  return video_final
114
 
115
  # --- Interface Gradio (Inalterada) ---
116
+ with gr.Blocks(theme=gr.themes.Base(primary_hue="purple")) as demo:
 
117
  gr.Markdown(
118
  """
119
+ # 🧠 Simulador de Jornada Inteligente 3D
120
+ Gere uma jornada contínua de **10 ciclos**. Os checkpoints (alvos em vermelho) só aparecem quando a bola se aproxima.
121
+ Checkpoints visitados se tornam verdes. A trajetória final é calculada para criar um **loop perfeito**.
122
  """
123
  )
 
124
  with gr.Row():
125
  with gr.Column(scale=1):
126
  gr.Markdown("### 🎮 Controles")
127
  angulo_camera_slider = gr.Slider(-180, 180, value=30, label="Ângulo da Câmera (Fixo)")
128
+ generate_btn = gr.Button("🚀 Gerar Jornada Inteligente", variant="primary")
 
129
  with gr.Column(scale=2):
130
  gr.Markdown("### 📽️ Vídeo Final")
131
  video_output = gr.Video(label="Animação da Jornada Contínua", autoplay=True)
132
+ generate_btn.click(fn=gerar_simulacao_inteligente, inputs=[angulo_camera_slider], outputs=[video_output])
 
 
 
 
 
133
 
134
  if __name__ == "__main__":
135
  demo.launch()