201 lines
7.1 KiB
Python
201 lines
7.1 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk
|
|
import math
|
|
|
|
import matplotlib
|
|
matplotlib.use("TkAgg")
|
|
import matplotlib.pyplot as plt
|
|
from mpl_toolkits.mplot3d import Axes3D
|
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
|
import numpy as np
|
|
|
|
class TabDrag:
|
|
def __init__(self, notebook, tab_simulator):
|
|
"""
|
|
Pestaña para calcular un coef. 'b' a partir de la geometría.
|
|
Luego se pasa a tab_simulator.set_b_value(...) para usarlo en la simulación.
|
|
"""
|
|
self.notebook = notebook
|
|
self.tab_simulator = tab_simulator
|
|
|
|
self.frame = tk.Frame(notebook)
|
|
self.frame.pack(fill="both", expand=True)
|
|
|
|
# Layout principal
|
|
frame_left = tk.Frame(self.frame)
|
|
frame_left.pack(side="left", fill="y", padx=5, pady=5)
|
|
|
|
frame_right = tk.Frame(self.frame, bd=2, relief="groove")
|
|
frame_right.pack(side="right", fill="both", expand=True, padx=5, pady=5)
|
|
|
|
self.frame_3d = tk.Frame(frame_right)
|
|
self.frame_3d.pack(fill="both", expand=True)
|
|
|
|
# Sección Izquierda: geometría + parámetros
|
|
tk.Label(frame_left, text="Selecciona geometría:").pack(anchor="w")
|
|
self.geometria_var = tk.StringVar(value="Prisma cuadrado")
|
|
self.combo_geometrias = ttk.Combobox(
|
|
frame_left, textvariable=self.geometria_var,
|
|
values=["Prisma cuadrado", "Cilindro", "Esfera"],
|
|
state="readonly"
|
|
)
|
|
self.combo_geometrias.pack(anchor="w", pady=5)
|
|
|
|
self.frame_parametros = tk.Frame(frame_left, bd=1, relief="sunken")
|
|
self.frame_parametros.pack(fill="x", pady=5)
|
|
|
|
self.label_param1 = tk.Label(self.frame_parametros, text="Parámetro 1:")
|
|
self.label_param1.grid(row=0, column=0, sticky="w", padx=5, pady=2)
|
|
self.entry_param1 = tk.Entry(self.frame_parametros, width=8)
|
|
self.entry_param1.grid(row=0, column=1, padx=5, pady=2)
|
|
self.entry_param1.insert(0, "1")
|
|
|
|
self.label_param2 = tk.Label(self.frame_parametros, text="Parámetro 2:")
|
|
self.label_param2.grid(row=1, column=0, sticky="w", padx=5, pady=2)
|
|
self.entry_param2 = tk.Entry(self.frame_parametros, width=8)
|
|
self.entry_param2.grid(row=1, column=1, padx=5, pady=2)
|
|
self.entry_param2.insert(0, "7")
|
|
|
|
self.label_result_b = tk.Label(frame_left, text="Coef (b): N/A", fg="blue")
|
|
self.label_result_b.pack()
|
|
|
|
btn_calc_b = tk.Button(
|
|
frame_left, text="Calcular Coef. Rozamiento",
|
|
command=self.calcular_coef_rozamiento
|
|
)
|
|
btn_calc_b.pack(pady=5)
|
|
|
|
tk.Button(
|
|
frame_left, text="Refrescar Vista 3D",
|
|
command=self.refrescar_3d
|
|
).pack(pady=10)
|
|
|
|
# Creamos la figura 3D
|
|
self.fig = plt.Figure(figsize=(4,3), dpi=100)
|
|
self.ax = self.fig.add_subplot(111, projection='3d')
|
|
self.canvas_3d = FigureCanvasTkAgg(self.fig, master=self.frame_3d)
|
|
self.canvas_widget = self.canvas_3d.get_tk_widget()
|
|
self.canvas_widget.pack(fill="both", expand=True)
|
|
|
|
self.combo_geometrias.bind("<<ComboboxSelected>>", self.on_change_geometria)
|
|
self.update_param_labels()
|
|
self.refrescar_3d()
|
|
|
|
def on_change_geometria(self, event=None):
|
|
self.update_param_labels()
|
|
self.refrescar_3d()
|
|
|
|
def update_param_labels(self):
|
|
geom = self.geometria_var.get()
|
|
self.entry_param2.config(state="normal", fg="black")
|
|
if geom=="Prisma cuadrado":
|
|
self.label_param1.config(text="Lado base (m):")
|
|
self.label_param2.config(text="Longitud (m):")
|
|
elif geom=="Cilindro":
|
|
self.label_param1.config(text="Radio (m):")
|
|
self.label_param2.config(text="Altura (m):")
|
|
elif geom=="Esfera":
|
|
self.label_param1.config(text="Radio (m):")
|
|
self.label_param2.config(text="(no aplica):")
|
|
self.entry_param2.delete(0, tk.END)
|
|
self.entry_param2.config(state="disabled", fg="gray")
|
|
else:
|
|
self.label_param1.config(text="Parámetro 1:")
|
|
self.label_param2.config(text="Parámetro 2:")
|
|
|
|
def refrescar_3d(self):
|
|
# Dibuja la geometría en self.ax
|
|
geom = self.geometria_var.get()
|
|
try:
|
|
p1 = float(self.entry_param1.get())
|
|
except ValueError:
|
|
p1=1.0
|
|
try:
|
|
if self.entry_param2.cget("state")!="disabled":
|
|
p2 = float(self.entry_param2.get())
|
|
else:
|
|
p2=1.0
|
|
except ValueError:
|
|
p2=1.0
|
|
|
|
self.ax.clear()
|
|
self.ax.set_axis_off()
|
|
|
|
if geom=="Prisma cuadrado":
|
|
Xs=[0,p1,p1,0,0,p1,p1,0]
|
|
Ys=[0,0,p1,p1,0,0,p1,p1]
|
|
Zs=[0,0,0,0,p2,p2,p2,p2]
|
|
edges=[(0,1),(1,2),(2,3),(3,0),
|
|
(4,5),(5,6),(6,7),(7,4),
|
|
(0,4),(1,5),(2,6),(3,7)]
|
|
for (i,j) in edges:
|
|
self.ax.plot([Xs[i],Xs[j]], [Ys[i],Ys[j]], [Zs[i],Zs[j]], color='orange')
|
|
self.ax.set_box_aspect((p1,p1,p2))
|
|
elif geom=="Cilindro":
|
|
import numpy as np
|
|
import math
|
|
r=p1
|
|
h=p2
|
|
theta=np.linspace(0,2*math.pi,30)
|
|
z=np.linspace(0,h,30)
|
|
T,Z=np.meshgrid(theta,z)
|
|
X=r*np.cos(T)
|
|
Y=r*np.sin(T)
|
|
self.ax.plot_surface(X, Y, Z, color='orange', alpha=0.8)
|
|
self.ax.set_box_aspect((2*r,2*r,h))
|
|
elif geom=="Esfera":
|
|
import numpy as np
|
|
import math
|
|
r=p1
|
|
phi=np.linspace(0,math.pi,30)
|
|
t=np.linspace(0,2*math.pi,30)
|
|
phi_grid,t_grid=np.meshgrid(phi,t)
|
|
X=r*np.sin(phi_grid)*np.cos(t_grid)
|
|
Y=r*np.sin(phi_grid)*np.sin(t_grid)
|
|
Z=r*np.cos(phi_grid)
|
|
self.ax.plot_surface(X,Y,Z,color='orange',alpha=0.8)
|
|
self.ax.set_box_aspect((2*r,2*r,2*r))
|
|
else:
|
|
self.ax.text2D(0.3,0.5,"Geom. desconocida", transform=self.ax.transAxes)
|
|
|
|
self.ax.set_title(geom)
|
|
self.canvas_3d.draw()
|
|
|
|
def calcular_coef_rozamiento(self):
|
|
geom = self.geometria_var.get()
|
|
try:
|
|
p1 = float(self.entry_param1.get())
|
|
except:
|
|
self.label_result_b.config(text="Error param1", fg="red")
|
|
return
|
|
|
|
Cd=1.0
|
|
A=1.0
|
|
if geom=="Prisma cuadrado":
|
|
try:
|
|
p2=float(self.entry_param2.get())
|
|
except:
|
|
self.label_result_b.config(text="Error param2", fg="red")
|
|
return
|
|
Cd=1.15
|
|
A=p1*p1
|
|
elif geom=="Cilindro":
|
|
try:
|
|
p2=float(self.entry_param2.get())
|
|
except:
|
|
self.label_result_b.config(text="Error param2", fg="red")
|
|
return
|
|
Cd=0.82
|
|
import math
|
|
A=math.pi*(p1**2)
|
|
elif geom=="Esfera":
|
|
Cd=0.47
|
|
import math
|
|
A=math.pi*(p1**2)
|
|
|
|
rho=1.225
|
|
b_calc=0.5*rho*Cd*A
|
|
|
|
self.label_result_b.config(text=f"Coef (b) ~ {b_calc:.4f}", fg="blue")
|
|
self.tab_simulator.set_b_value(b_calc)
|