source/src/geometry_viewer.py
2025-04-07 12:43:28 +02:00

105 lines
3.8 KiB
Python

import matplotlib
matplotlib.use("TkAgg") # Para usar Tkinter como backend
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # Necesario para 3D
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
def plot_geometry_in_frame(parent_frame, geom, p1, p2):
"""Dibuja distintas geometrías 3D en un Frame de Tkinter, sin abrir ventana nueva."""
fig = plt.Figure(figsize=(4, 3), dpi=100)
ax = fig.add_subplot(111, projection='3d')
ax.set_title(f"{geom}", fontsize=10)
if geom == "Prisma cuadrado":
lado, largo = p1, p2
Xs = [0, lado, lado, 0, 0, lado, lado, 0]
Ys = [0, 0, lado, lado, 0, 0, lado, lado]
Zs = [0, 0, 0, 0, largo, largo, largo, largo]
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:
ax.plot([Xs[i], Xs[j]], [Ys[i], Ys[j]], [Zs[i], Zs[j]], color='g')
ax.set_xlim(0, max(lado,1))
ax.set_ylim(0, max(lado,1))
ax.set_zlim(0, max(largo,1))
elif geom == "Cilindro":
r, h = p1, p2
theta = np.linspace(0, 2*np.pi, 30)
z = np.linspace(0, h, 30)
T, Z = np.meshgrid(theta, z)
X = r*np.cos(T)
Y = r*np.sin(T)
ax.plot_surface(X, Y, Z, color='cyan', alpha=0.5)
ax.set_xlim(-r, r)
ax.set_ylim(-r, r)
ax.set_zlim(0, h)
elif geom == "Esfera":
r = p1
phi = np.linspace(0, np.pi, 30)
theta = np.linspace(0, 2*np.pi, 30)
Phi, Theta = np.meshgrid(phi, theta)
X = r*np.sin(Phi)*np.cos(Theta)
Y = r*np.sin(Phi)*np.sin(Theta)
Z = r*np.cos(Phi)
ax.plot_surface(X, Y, Z, color='yellow', alpha=0.6)
ax.set_xlim(-r, r)
ax.set_ylim(-r, r)
ax.set_zlim(-r, r)
else:
ax.text2D(0.2, 0.5, "Geometría desconocida", transform=ax.transAxes)
for child in parent_frame.winfo_children():
child.destroy()
canvas = FigureCanvasTkAgg(fig, master=parent_frame)
canvas_widget = canvas.get_tk_widget()
canvas_widget.pack(fill="both", expand=True)
canvas.draw()
def plot_coil_in_frame(parent_frame, N=10, e_pvc=1.0, r_int=5.0, r_ext=8.0, h_c=10.0, d_cu=0.5):
"""Dibuja de forma aproximada una bobina en 2D (vista de corte)."""
r_capas = r_ext - (r_int + e_pvc)
if r_capas < 0: r_capas = 0.0
fig = plt.Figure(figsize=(4, 3), dpi=100)
ax = fig.add_subplot(111)
ax.set_aspect("equal", adjustable="box")
ax.set_title("Bobina (vista 2D)", fontsize=10)
# PVC a izquierda y derecha
ax.fill_between(x=[-(r_int + e_pvc), -r_int], y1=0, y2=h_c, color="black", alpha=0.3)
ax.fill_between(x=[r_int, r_int + e_pvc], y1=0, y2=h_c, color="black", alpha=0.3)
num_capas = int(np.floor(r_capas / d_cu))
if num_capas < 1: num_capas = 1
vueltas_por_capa = int(np.ceil(N / num_capas))
delta_h = h_c / (vueltas_por_capa + 1)
def dibuja_conductor(xc, yc, radio):
circle = plt.Circle((xc, yc), radio, color="orange", fill=True)
ax.add_patch(circle)
for i in range(num_capas):
x_left = -(r_int + e_pvc + (2*i + 1) * (d_cu / 2))
x_right = +(r_int + e_pvc + (2*i + 1) * (d_cu / 2))
for j in range(vueltas_por_capa):
y = (j + 1)*delta_h
if y > h_c: break
dibuja_conductor(x_left, y, d_cu/2)
dibuja_conductor(x_right, y, d_cu/2)
ax.set_xlim(-r_ext - d_cu, r_ext + d_cu)
ax.set_ylim(0, h_c + d_cu)
ax.set_xlabel("Radio (X)")
ax.set_ylabel("Altura (Y)")
ax.grid(True)
for child in parent_frame.winfo_children():
child.destroy()
canvas = FigureCanvasTkAgg(fig, master=parent_frame)
canvas_widget = canvas.get_tk_widget()
canvas_widget.pack(fill="both", expand=True)
canvas.draw()