x2XcarleX2x commited on
Commit
f461e9f
·
verified ·
1 Parent(s): dcfb810

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -46
app.py CHANGED
@@ -8,11 +8,11 @@ from scipy.special import comb
8
  import random
9
  import json
10
 
11
- # --- Funções Matemáticas (as mesmas que já dominamos) ---
12
  def bernstein_poly(i, n, t):
13
  return comb(n, i) * (t**(i)) * ((1 - t)**(n - i))
14
 
15
- def bezier_curve_3d(points, n_times=100):
16
  n_points = len(points)
17
  x_points, y_points, z_points = np.array([p[0] for p in points]), np.array([p[1] for p in points]), np.array([p[2] for p in points])
18
  t = np.linspace(0.0, 1.0, n_times)
@@ -25,32 +25,31 @@ 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 Gerador de Ciclos) ---
29
 
30
- def gerar_proximo_ciclo(estado_anterior_json: str, progress=gr.Progress(track_tqdm=True)):
31
  """
32
- Gera um único trecho da jornada (de A para B) e o renderiza como um vídeo.
33
  """
34
  progress(0, desc="Decodificando estado anterior...")
35
-
36
- # 1. Carrega o estado do ciclo anterior (ou cria um novo se for o primeiro)
37
  if estado_anterior_json:
38
  estado = json.loads(estado_anterior_json)
39
- ponto_a = np.array(estado["ponto_b"]) # O destino se torna a origem
40
  vetor_inercia_anterior = np.array(estado["vetor_inercia"])
41
  else: # Primeiro ciclo
42
- ponto_a = np.array([0., 0., 0.])
43
- vetor_inercia_anterior = np.array([10., 10., 10.])
44
 
45
  progress(0.1, desc="Gerando novo checkpoint aleatório...")
46
  # 2. Gera um novo destino (Ponto B)
47
  ponto_b = np.random.rand(3) * 120 - 60
48
 
49
- progress(0.2, desc="Calculando trajetória com convergência...")
50
  # 3. Calcula a nova trajetória
51
  ponto_controle = ponto_a + vetor_inercia_anterior
52
  pontos_curva = [ponto_a, ponto_controle, ponto_b]
53
- x_traj, y_traj, z_traj = bezier_curve_3d(pontos_curva, n_times=120) # 120 frames
54
  total_frames = len(x_traj)
55
 
56
  # 4. Aprende o "eco" para o próximo ciclo
@@ -58,41 +57,37 @@ def gerar_proximo_ciclo(estado_anterior_json: str, progress=gr.Progress(track_tq
58
  pontos_eco = list(zip(x_traj[-tamanho_eco:], y_traj[-tamanho_eco:], z_traj[-tamanho_eco:]))
59
  vetor_inercia_novo = aprender_com_o_eco_3d(pontos_eco)["velocity_vector"]
60
 
61
- # 5. Salva o novo estado para o próximo clique do botão
62
- estado_novo = {
63
- "ponto_a": ponto_a.tolist(),
64
- "ponto_b": ponto_b.tolist(),
65
- "vetor_inercia": vetor_inercia_novo.tolist()
66
- }
67
  estado_novo_json = json.dumps(estado_novo)
68
 
69
  # 6. Setup da Animação
70
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
71
  fig.patch.set_facecolor('#111111'); ax.set_facecolor('#111111')
72
 
73
- bola, = ax.plot([], [], [], 'o', color='red', markersize=10, markeredgecolor='white')
 
 
 
 
 
74
  ax.set_xlim(-70, 70); ax.set_ylim(-70, 70); ax.set_zlim(-70, 70)
75
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
 
 
 
 
76
 
77
  def update(frame):
78
- # Desenha a cena estática em cada frame
79
- ax.cla() # Limpa o eixo para redesenhar
80
- ax.set_xlim(-70, 70); ax.set_ylim(-70, 70); ax.set_zlim(-70, 70)
81
- ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
82
- ax.plot(x_traj, y_traj, z_traj, color='cyan', linewidth=2, alpha=0.5)
83
- ax.scatter(*ponto_a, s=400, c='lime', alpha=0.7, label='A')
84
- ax.scatter(*ponto_b, s=400, c='yellow', marker='X', alpha=0.7, label='B')
85
-
86
- # Anima a bola
87
  bola.set_data_3d([x_traj[frame]], [y_traj[frame]], [z_traj[frame]])
88
- ax.view_init(elev=30., azim=frame * 0.7)
89
  return bola,
90
 
91
  # 7. Renderiza e Salva o Vídeo
92
  progress(0.5, desc="Renderizando animação do ciclo...")
93
- ani = FuncAnimation(fig, update, frames=total_frames, interval=33, blit=False)
94
- output_filename = "ciclo_atual.mp4"
95
- ani.save(output_filename, writer='ffmpeg', fps=30, dpi=100, progress_callback=lambda i, n: progress(0.5 + 0.5 * (i/n), desc=f"Renderizando frame {i+1}/{n}"))
96
  plt.close(fig)
97
 
98
  info_ciclo = f"Ciclo Concluído.\nInício (A): {np.round(ponto_a, 1)}\nDestino (B): {np.round(ponto_b, 1)}\nInércia Aprendida: {np.round(vetor_inercia_novo, 1)}"
@@ -101,27 +96,25 @@ def gerar_proximo_ciclo(estado_anterior_json: str, progress=gr.Progress(track_tq
101
 
102
  # --- Interface Gradio ---
103
 
104
- with gr.Blocks(theme=gr.themes.Base(primary_hue="lime")) as demo:
105
  gr.Markdown(
106
  """
107
- # 🌀 Simulador de Convergência Causal 3D Interativo
108
- Clique em "Gerar Próximo Ciclo" para ver o agente (bola vermelha) viajar do checkpoint A (verde) para um novo checkpoint B (amarelo) aleatório.
109
- A trajetória é guiada pela inércia aprendida do ciclo anterior. Cada clique gera a continuação da jornada.
110
  """
111
  )
112
 
113
  with gr.Row():
114
  with gr.Column(scale=1):
115
  gr.Markdown("### 🎮 Controles")
116
- # O estado é armazenado em um Textbox invisível
117
  estado_oculto = gr.Textbox(label="Estado da Simulação (JSON)", interactive=True, visible=False)
118
-
119
  info_output = gr.Textbox(label="Dados do Ciclo Atual", lines=4, interactive=False)
120
 
121
- # Botão para iniciar o primeiro ciclo (sem estado anterior)
122
- start_btn = gr.Button("🚀 Iniciar Simulação (Primeiro Ciclo)", variant="primary")
123
- # Botão para continuar a simulação (usa o estado anterior)
124
- next_btn = gr.Button("➡️ Gerar Próximo Ciclo", variant="secondary")
125
 
126
  with gr.Column(scale=2):
127
  gr.Markdown("### 📽️ Visualização do Ciclo")
@@ -129,14 +122,14 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="lime")) as demo:
129
 
130
  # Conexões dos botões
131
  start_btn.click(
132
- fn=lambda: gerar_proximo_ciclo(None), # Passa None para indicar o primeiro ciclo
133
- inputs=None,
134
  outputs=[video_output, estado_oculto, info_output]
135
  )
136
 
137
  next_btn.click(
138
- fn=gerar_proximo_ciclo,
139
- inputs=[estado_oculto],
140
  outputs=[video_output, estado_oculto, info_output]
141
  )
142
 
 
8
  import random
9
  import json
10
 
11
+ # --- Funções Matemáticas (Inalteradas) ---
12
  def bernstein_poly(i, n, t):
13
  return comb(n, i) * (t**(i)) * ((1 - t)**(n - i))
14
 
15
+ def bezier_curve_3d(points, n_times=120): # Fixo em 120 vetores/frames
16
  n_points = len(points)
17
  x_points, y_points, z_points = np.array([p[0] for p in points]), np.array([p[1] for p in points]), np.array([p[2] for p in points])
18
  t = np.linspace(0.0, 1.0, n_times)
 
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 (Gerador de Diagrama Animado) ---
29
 
30
+ def gerar_diagrama_animado(estado_anterior_json: str, angulo_camera: int, progress=gr.Progress(track_tqdm=True)):
31
  """
32
+ Gera um ciclo da jornada com ambiente estático e movimento discreto da bola.
33
  """
34
  progress(0, desc="Decodificando estado anterior...")
35
+ # 1. Carrega ou inicializa o estado
 
36
  if estado_anterior_json:
37
  estado = json.loads(estado_anterior_json)
38
+ ponto_a = np.array(estado["ponto_b"])
39
  vetor_inercia_anterior = np.array(estado["vetor_inercia"])
40
  else: # Primeiro ciclo
41
+ ponto_a = np.array([-40., 20., 10.])
42
+ vetor_inercia_anterior = np.array([30., 10., -20.])
43
 
44
  progress(0.1, desc="Gerando novo checkpoint aleatório...")
45
  # 2. Gera um novo destino (Ponto B)
46
  ponto_b = np.random.rand(3) * 120 - 60
47
 
48
+ progress(0.2, desc="Calculando trajetória (120 vetores)...")
49
  # 3. Calcula a nova trajetória
50
  ponto_controle = ponto_a + vetor_inercia_anterior
51
  pontos_curva = [ponto_a, ponto_controle, ponto_b]
52
+ x_traj, y_traj, z_traj = bezier_curve_3d(pontos_curva) # Gera 120 vetores
53
  total_frames = len(x_traj)
54
 
55
  # 4. Aprende o "eco" para o próximo ciclo
 
57
  pontos_eco = list(zip(x_traj[-tamanho_eco:], y_traj[-tamanho_eco:], z_traj[-tamanho_eco:]))
58
  vetor_inercia_novo = aprender_com_o_eco_3d(pontos_eco)["velocity_vector"]
59
 
60
+ # 5. Salva o novo estado
61
+ estado_novo = {"ponto_a": ponto_a.tolist(), "ponto_b": ponto_b.tolist(), "vetor_inercia": vetor_inercia_novo.tolist()}
 
 
 
 
62
  estado_novo_json = json.dumps(estado_novo)
63
 
64
  # 6. Setup da Animação
65
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
66
  fig.patch.set_facecolor('#111111'); ax.set_facecolor('#111111')
67
 
68
+ # --- A MUDANÇA PRINCIPAL: Ambiente Fixo ---
69
+ # Desenha a cena estática UMA VEZ
70
+ ax.plot(x_traj, y_traj, z_traj, color='cyan', linewidth=2, alpha=0.4, label='Trajetória (Linhas ABC)')
71
+ ax.scatter(*ponto_a, s=400, c='lime', alpha=0.7, label='Checkpoint A (Início)')
72
+ ax.scatter(*ponto_b, s=400, c='yellow', marker='X', alpha=0.7, label='Checkpoint B (Destino)')
73
+ ax.view_init(elev=30., azim=angulo_camera) # Usa o ângulo da UI
74
  ax.set_xlim(-70, 70); ax.set_ylim(-70, 70); ax.set_zlim(-70, 70)
75
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
76
+ ax.legend()
77
+
78
+ # Inicializa apenas a bola, que é o único elemento que se move
79
+ bola, = ax.plot([], [], [], 'o', color='red', markersize=10, markeredgecolor='white')
80
 
81
  def update(frame):
82
+ # A bola avança um vetor (frame) de cada vez
 
 
 
 
 
 
 
 
83
  bola.set_data_3d([x_traj[frame]], [y_traj[frame]], [z_traj[frame]])
 
84
  return bola,
85
 
86
  # 7. Renderiza e Salva o Vídeo
87
  progress(0.5, desc="Renderizando animação do ciclo...")
88
+ ani = FuncAnimation(fig, update, frames=total_frames, interval=33, blit=True)
89
+ output_filename = "diagrama_animado.mp4"
90
+ ani.save(output_filename, writer='ffmpeg', fps=30, dpi=100, progress_callback=lambda i, n: progress(0.5 + 0.5 * (i/n), desc=f"Renderizando vetor {i+1}/{n}"))
91
  plt.close(fig)
92
 
93
  info_ciclo = f"Ciclo Concluído.\nInício (A): {np.round(ponto_a, 1)}\nDestino (B): {np.round(ponto_b, 1)}\nInércia Aprendida: {np.round(vetor_inercia_novo, 1)}"
 
96
 
97
  # --- Interface Gradio ---
98
 
99
+ with gr.Blocks(theme=gr.themes.Base(primary_hue="cyan")) as demo:
100
  gr.Markdown(
101
  """
102
+ # 📈 Diagrama 3D Animado de Convergência
103
+ Gere um ciclo da simulação. O ambiente (câmera, checkpoints, trajetória ABC) é FIXO.
104
+ A animação mostra apenas a **bola vermelha se movendo no tempo**, avançando um vetor a cada frame, sobre o caminho pré-calculado.
105
  """
106
  )
107
 
108
  with gr.Row():
109
  with gr.Column(scale=1):
110
  gr.Markdown("### 🎮 Controles")
 
111
  estado_oculto = gr.Textbox(label="Estado da Simulação (JSON)", interactive=True, visible=False)
112
+ angulo_camera_slider = gr.Slider(-180, 180, value=45, label="Ângulo da Câmera (Azimute)")
113
  info_output = gr.Textbox(label="Dados do Ciclo Atual", lines=4, interactive=False)
114
 
115
+ with gr.Row():
116
+ start_btn = gr.Button("🚀 Iniciar Simulação", variant="primary")
117
+ next_btn = gr.Button("➡️ Gerar Próximo Ciclo", variant="secondary")
 
118
 
119
  with gr.Column(scale=2):
120
  gr.Markdown("### 📽️ Visualização do Ciclo")
 
122
 
123
  # Conexões dos botões
124
  start_btn.click(
125
+ fn=lambda angulo: gerar_diagrama_animado(None, angulo),
126
+ inputs=[angulo_camera_slider],
127
  outputs=[video_output, estado_oculto, info_output]
128
  )
129
 
130
  next_btn.click(
131
+ fn=gerar_diagrama_animado,
132
+ inputs=[estado_oculto, angulo_camera_slider],
133
  outputs=[video_output, estado_oculto, info_output]
134
  )
135